diff options
852 files changed, 13378 insertions, 5324 deletions
diff --git a/Android.mk b/Android.mk index 4dc5fd349109..cf6d946f7406 100644 --- a/Android.mk +++ b/Android.mk @@ -42,7 +42,7 @@ LOCAL_SRC_FILES := $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS)) # EventLogTags files. LOCAL_SRC_FILES += \ - core/java/android/auditing/SecurityLogTags.logtags \ + core/java/android/app/admin/SecurityLogTags.logtags \ core/java/android/content/EventLogTags.logtags \ core/java/android/speech/tts/EventLogTags.logtags \ core/java/android/webkit/EventLogTags.logtags \ @@ -117,6 +117,7 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothManager.aidl \ core/java/android/bluetooth/IBluetoothManagerCallback.aidl \ core/java/android/bluetooth/IBluetoothPbap.aidl \ + core/java/android/bluetooth/IBluetoothPbapClient.aidl \ core/java/android/bluetooth/IBluetoothMap.aidl \ core/java/android/bluetooth/IBluetoothSap.aidl \ core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \ @@ -413,6 +414,8 @@ LOCAL_SRC_FILES += \ telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl \ telephony/java/com/android/ims/internal/IImsEcbm.aidl \ telephony/java/com/android/ims/internal/IImsEcbmListener.aidl \ + telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl \ + telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl \ telephony/java/com/android/ims/internal/IImsService.aidl \ telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl \ telephony/java/com/android/ims/internal/IImsUt.aidl \ diff --git a/api/current.txt b/api/current.txt index e253ae1e01b4..015c03509b90 100644 --- a/api/current.txt +++ b/api/current.txt @@ -559,6 +559,7 @@ package android { field public static final int fillBefore = 16843196; // 0x10101bc field public static final int fillColor = 16843780; // 0x1010404 field public static final int fillEnabled = 16843343; // 0x101024f + field public static final int fillType = 16844064; // 0x1010520 field public static final int fillViewport = 16843130; // 0x101017a field public static final int filter = 16843035; // 0x101011b field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4 @@ -3442,7 +3443,7 @@ package android.app { method public android.view.View getCurrentFocus(); method public android.app.FragmentManager getFragmentManager(); method public android.content.Intent getIntent(); - method public deprecated java.lang.Object getLastNonConfigurationInstance(); + method public java.lang.Object getLastNonConfigurationInstance(); method public android.view.LayoutInflater getLayoutInflater(); method public android.app.LoaderManager getLoaderManager(); method public java.lang.String getLocalClassName(); @@ -3536,14 +3537,13 @@ package android.app { method public boolean onPreparePanel(int, android.view.View, android.view.Menu); method public void onProvideAssistContent(android.app.assist.AssistContent); method public void onProvideAssistData(android.os.Bundle); - method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public android.net.Uri onProvideReferrer(); method public void onRequestPermissionsResult(int, java.lang.String[], int[]); method protected void onRestart(); method protected void onRestoreInstanceState(android.os.Bundle); method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle); method protected void onResume(); - method public deprecated java.lang.Object onRetainNonConfigurationInstance(); + method public java.lang.Object onRetainNonConfigurationInstance(); method protected void onSaveInstanceState(android.os.Bundle); method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle); method public boolean onSearchRequested(android.view.SearchEvent); @@ -4218,7 +4218,6 @@ package android.app { method public void onPanelClosed(int, android.view.Menu); method public boolean onPrepareOptionsMenu(android.view.Menu); method public boolean onPreparePanel(int, android.view.View, android.view.Menu); - method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public void onRestoreInstanceState(android.os.Bundle); method public android.os.Bundle onSaveInstanceState(); method public boolean onSearchRequested(android.view.SearchEvent); @@ -5852,7 +5851,6 @@ package android.app.admin { method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName); method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName); method public int getCurrentFailedPasswordAttempts(); - method public boolean getDeviceLoggingEnabled(android.content.ComponentName); method public java.lang.String getDeviceOwnerLockScreenInfo(); method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); @@ -5901,6 +5899,7 @@ package android.app.admin { method public boolean isMasterVolumeMuted(android.content.ComponentName); method public boolean isProfileOwnerApp(java.lang.String); method public boolean isProvisioningAllowed(java.lang.String); + method public boolean isSecurityLoggingEnabled(android.content.ComponentName); method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String); method public void lockNow(); method public void reboot(android.content.ComponentName); @@ -5910,8 +5909,8 @@ package android.app.admin { method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); method public boolean requestBugreport(android.content.ComponentName); method public boolean resetPassword(java.lang.String, int); - method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName); - method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName); + method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName); + method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String); method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); @@ -5923,7 +5922,6 @@ package android.app.admin { method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean); method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean); - method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean); method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); @@ -5956,6 +5954,7 @@ package android.app.admin { method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); method public void setScreenCaptureDisabled(android.content.ComponentName, boolean); method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); + method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean); method public void setShortSupportMessage(android.content.ComponentName, java.lang.String); method public boolean setStatusBarDisabled(android.content.ComponentName, boolean); method public int setStorageEncryption(android.content.ComponentName, boolean); @@ -5979,6 +5978,7 @@ package android.app.admin { field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2 field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3 field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4 + field public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5; // 0x5 field public static final int ENCRYPTION_STATUS_INACTIVE = 1; // 0x1 field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0 field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION"; @@ -6040,6 +6040,27 @@ package android.app.admin { field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } + public class SecurityLog { + ctor public SecurityLog(); + field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452 + field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451 + field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455 + field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456 + field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457 + field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458 + field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453 + field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 + } + + public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.Object getData(); + method public int getTag(); + method public long getTimeNanos(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR; + } + public class SystemUpdatePolicy implements android.os.Parcelable { method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy(); method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy(); @@ -6244,6 +6265,8 @@ package android.app.job { method public long getIntervalMillis(); method public long getMaxExecutionDelayMillis(); method public long getMinLatencyMillis(); + method public static final long getMinimumFlex(); + method public static final long getMinimumPeriod(); method public int getNetworkType(); method public android.content.ComponentName getService(); method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris(); @@ -6257,8 +6280,6 @@ package android.app.job { field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR; field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L - field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L - field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L field public static final int NETWORK_TYPE_ANY = 1; // 0x1 field public static final int NETWORK_TYPE_NONE = 0; // 0x0 field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2 @@ -6372,8 +6393,8 @@ package android.app.usage { method public long getTxPackets(); method public int getUid(); field public static final int ROAMING_ALL = -1; // 0xffffffff - field public static final int ROAMING_DEFAULT = 1; // 0x1 - field public static final int ROAMING_ROAMING = 2; // 0x2 + field public static final int ROAMING_NO = 1; // 0x1 + field public static final int ROAMING_YES = 2; // 0x2 field public static final int STATE_ALL = -1; // 0xffffffff field public static final int STATE_DEFAULT = 1; // 0x1 field public static final int STATE_FOREGROUND = 2; // 0x2 @@ -6580,31 +6601,6 @@ package android.appwidget { } -package android.auditing { - - public class SecurityLog { - ctor public SecurityLog(); - field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452 - field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451 - field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455 - field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456 - field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457 - field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458 - field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453 - field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 - } - - public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { - method public int describeContents(); - method public java.lang.Object getData(); - method public int getTag(); - method public long getTimeNanos(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR; - } - -} - package android.bluetooth { public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile { @@ -8113,7 +8109,7 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; - field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties"; + field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler"; @@ -9453,6 +9449,7 @@ package android.content.pm { method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle); method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle); method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle); + method public boolean hasShortcutHostPermission(); method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle); method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle); method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle); @@ -10115,7 +10112,6 @@ package android.content.res { method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); - method public int getChangingConfigurations(); method public int getColorForState(int[], int); method public int getDefaultColor(); method public boolean isOpaque(); @@ -10127,6 +10123,7 @@ package android.content.res { public abstract class ComplexColor { ctor public ComplexColor(); + method public int getChangingConfigurations(); method public abstract int getDefaultColor(); method public boolean isStateful(); } @@ -11474,17 +11471,6 @@ package android.gesture { package android.graphics { - public deprecated class AvoidXfermode extends android.graphics.Xfermode { - ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode); - } - - public static final class AvoidXfermode.Mode extends java.lang.Enum { - method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String); - method public static final android.graphics.AvoidXfermode.Mode[] values(); - enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID; - enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; - } - public final class Bitmap implements android.os.Parcelable { method public boolean compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream); method public android.graphics.Bitmap copy(android.graphics.Bitmap.Config, boolean); @@ -12351,10 +12337,6 @@ package android.graphics { field public int bytesPerPixel; } - public deprecated class PixelXorXfermode extends android.graphics.Xfermode { - ctor public PixelXorXfermode(int); - } - public class Point implements android.os.Parcelable { ctor public Point(); ctor public Point(int, int); @@ -13034,9 +13016,9 @@ package android.graphics.drawable { method public void setPaddingMode(int); method public void setPaddingRelative(int, int, int, int); method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); + field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000 field public static final int PADDING_MODE_NEST = 0; // 0x0 field public static final int PADDING_MODE_STACK = 1; // 0x1 - field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000 } public class LevelListDrawable extends android.graphics.drawable.DrawableContainer { @@ -19280,7 +19262,6 @@ package android.location { method public boolean hasCarrierPhase(); method public boolean hasCarrierPhaseUncertainty(); method public boolean hasSnrInDb(); - method public boolean isPseudorangeRateCorrected(); method public void writeToParcel(android.os.Parcel, int); field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4 field public static final int ADR_STATE_RESET = 2; // 0x2 @@ -23103,6 +23084,7 @@ package android.media.tv { method public void notifyError(int); method public void notifyRecordingStopped(android.net.Uri); method public void notifyTuned(android.net.Uri); + method public void onAppPrivateCommand(java.lang.String, android.os.Bundle); method public abstract void onRelease(); method public abstract void onStartRecording(android.net.Uri); method public abstract void onStopRecording(); @@ -23120,6 +23102,7 @@ package android.media.tv { method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>); method public void notifyVideoAvailable(); method public void notifyVideoUnavailable(int); + method public void onAppPrivateCommand(java.lang.String, android.os.Bundle); method public android.view.View onCreateOverlayView(); method public boolean onGenericMotionEvent(android.view.MotionEvent); method public boolean onKeyDown(int, android.view.KeyEvent); @@ -23151,6 +23134,7 @@ package android.media.tv { public class TvRecordingClient { ctor public TvRecordingClient(android.content.Context, java.lang.String, android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler); method public void release(); + method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle); method public void startRecording(android.net.Uri); method public void stopRecording(); method public void tune(java.lang.String, android.net.Uri); @@ -23212,6 +23196,7 @@ package android.media.tv { method public boolean onUnhandledInputEvent(android.view.InputEvent); method public void reset(); method public void selectTrack(int, java.lang.String); + method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle); method public void setCallback(android.media.tv.TvView.TvInputCallback); method public void setCaptionEnabled(boolean); method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener); @@ -30761,6 +30746,7 @@ package android.provider { public static class CallLog.Calls implements android.provider.BaseColumns { ctor public CallLog.Calls(); method public static java.lang.String getLastOutgoingCall(android.content.Context); + field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7 field public static final int BLOCKED_TYPE = 6; // 0x6 field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number"; field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri"; @@ -30783,6 +30769,7 @@ package android.provider { field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; field public static final java.lang.String FEATURES = "features"; + field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 field public static final int FEATURES_VIDEO = 1; // 0x1 field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location"; field public static final int INCOMING_TYPE = 1; // 0x1 @@ -32426,7 +32413,6 @@ package android.provider { field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; - field public static final java.lang.String ACTION_SCREEN_READER_TUTORIAL = "android.settings.SCREEN_READER_TUTORIAL"; field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; @@ -36057,9 +36043,11 @@ package android.telecom { method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.Call.Callback); method public void registerCallback(android.telecom.Call.Callback, android.os.Handler); method public void reject(boolean, java.lang.String); + method public void sendCallEvent(java.lang.String, android.os.Bundle); method public void splitFromConference(); method public void stopDtmfTone(); method public void swapConference(); @@ -36073,6 +36061,7 @@ package android.telecom { field public static final int STATE_DISCONNECTING = 10; // 0xa field public static final int STATE_HOLDING = 3; // 0x3 field public static final int STATE_NEW = 0; // 0x0 + field public static final int STATE_PULLING_CALL = 11; // 0xb field public static final int STATE_RINGING = 2; // 0x2 field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8 } @@ -36083,6 +36072,7 @@ package android.telecom { method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>); method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>); method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details); method public void onParentChanged(android.telecom.Call, android.telecom.Call); method public void onPostDialWait(android.telecom.Call, java.lang.String); @@ -36113,6 +36103,7 @@ package android.telecom { method public static java.lang.String propertiesToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 @@ -36132,6 +36123,7 @@ package android.telecom { field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4 field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40 field public static final int PROPERTY_WIFI = 8; // 0x8 field public static final int PROPERTY_WORK_CALL = 32; // 0x20 } @@ -36246,15 +36238,19 @@ package android.telecom { method public void onAnswer(int); method public void onAnswer(); method public void onCallAudioStateChanged(android.telecom.CallAudioState); + method public void onCallEvent(java.lang.String, android.os.Bundle); method public void onDisconnect(); method public void onHold(); method public void onPlayDtmfTone(char); method public void onPostDialContinue(boolean); + method public void onPullExternalCall(); method public void onReject(); + method public void onReject(java.lang.String); method public void onSeparate(); method public void onStateChanged(int); method public void onStopDtmfTone(); method public void onUnhold(); + method public void sendConnectionEvent(java.lang.String, android.os.Bundle); method public final void setActive(); method public final void setAddress(android.net.Uri, int); method public final void setAudioModeIsVoip(boolean); @@ -36278,9 +36274,12 @@ package android.telecom { method public static java.lang.String stateToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000 + field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 + field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4 field public static final int CAPABILITY_MUTE = 64; // 0x40 @@ -36294,6 +36293,7 @@ package android.telecom { field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800 field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2 field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8 + field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED"; field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS"; field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER"; @@ -36303,6 +36303,7 @@ package android.telecom { field public static final int STATE_HOLDING = 5; // 0x5 field public static final int STATE_INITIALIZING = 0; // 0x0 field public static final int STATE_NEW = 1; // 0x1 + field public static final int STATE_PULLING_CALL = 7; // 0x7 field public static final int STATE_RINGING = 2; // 0x2 } @@ -36380,7 +36381,9 @@ package android.telecom { method public java.lang.String getReason(); method public int getTone(); method public void writeToParcel(android.os.Parcel, int); + field public static final int ANSWERED_ELSEWHERE = 11; // 0xb field public static final int BUSY = 7; // 0x7 + field public static final int CALL_PULLED = 12; // 0xc field public static final int CANCELED = 4; // 0x4 field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR; @@ -36416,6 +36419,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onCallRemoved(android.telecom.Call); method public void onCanAddCallChanged(boolean); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onSilenceRinger(); method public final void setAudioRoute(int); method public final void setMuted(boolean); @@ -36566,6 +36570,7 @@ package android.telecom { method public boolean isVoipAudioMode(); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.RemoteConnection.Callback); method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler); method public void reject(); @@ -36582,6 +36587,7 @@ package android.telecom { method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference); method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int); + method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle); method public void onDestroyed(android.telecom.RemoteConnection); method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause); method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle); @@ -36679,6 +36685,7 @@ package android.telecom { field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"; field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; + field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI"; field public static final int PRESENTATION_ALLOWED = 1; // 0x1 @@ -36820,6 +36827,7 @@ package android.telephony { field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_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_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool"; field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool"; @@ -42584,6 +42592,7 @@ package android.view { method public void onStartTemporaryDetach(); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); + method public void onVisibilityAggregated(boolean); method protected void onVisibilityChanged(android.view.View, int); method public void onWindowFocusChanged(boolean); method public void onWindowSystemUiVisibilityChanged(int); @@ -43680,7 +43689,7 @@ package android.view { method public abstract boolean onMenuOpened(int, android.view.Menu); method public abstract void onPanelClosed(int, android.view.Menu); method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu); - method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); + method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public abstract boolean onSearchRequested(); method public abstract boolean onSearchRequested(android.view.SearchEvent); method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams); @@ -57343,6 +57352,7 @@ package java.util { method public void ensureCapacity(int); method public void forEach(java.util.function.Consumer<? super E>); method public E get(int); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); method public java.util.Spliterator<E> spliterator(); method public void trimToSize(); @@ -57427,6 +57437,28 @@ package java.util { method public static int hashCode(float[]); method public static int hashCode(double[]); method public static int hashCode(java.lang.Object[]); + method public static void parallelSort(byte[]); + method public static void parallelSort(byte[], int, int); + method public static void parallelSort(char[]); + method public static void parallelSort(char[], int, int); + method public static void parallelSort(short[]); + method public static void parallelSort(short[], int, int); + method public static void parallelSort(int[]); + method public static void parallelSort(int[], int, int); + method public static void parallelSort(long[]); + method public static void parallelSort(long[], int, int); + method public static void parallelSort(float[]); + method public static void parallelSort(float[], int, int); + method public static void parallelSort(double[]); + method public static void parallelSort(double[], int, int); + method public static void parallelSort(T[]); + method public static void parallelSort(T[], int, int); + method public static void parallelSort(T[], java.util.Comparator<? super T>); + method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>); + method public static void setAll(T[], java.util.function.IntFunction<? extends T>); + method public static void setAll(int[], java.util.function.IntUnaryOperator); + method public static void setAll(long[], java.util.function.IntToLongFunction); + method public static void setAll(double[], java.util.function.IntToDoubleFunction); method public static void sort(int[]); method public static void sort(int[], int, int); method public static void sort(long[]); @@ -57614,6 +57646,7 @@ package java.util { method public abstract java.util.Iterator<E> iterator(); method public abstract boolean remove(java.lang.Object); method public abstract boolean removeAll(java.util.Collection<?>); + method public default boolean removeIf(java.util.function.Predicate<? super E>); method public abstract boolean retainAll(java.util.Collection<?>); method public abstract int size(); method public abstract java.lang.Object[] toArray(); @@ -58247,18 +58280,28 @@ package java.util { public abstract interface Map { method public abstract void clear(); + method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public abstract boolean containsKey(java.lang.Object); method public abstract boolean containsValue(java.lang.Object); method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet(); method public abstract boolean equals(java.lang.Object); method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public abstract V get(java.lang.Object); + method public default V getOrDefault(java.lang.Object, V); method public abstract int hashCode(); method public abstract boolean isEmpty(); method public abstract java.util.Set<K> keySet(); + method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); method public abstract V put(K, V); method public abstract void putAll(java.util.Map<? extends K, ? extends V>); + method public default V putIfAbsent(K, V); method public abstract V remove(java.lang.Object); + method public default boolean remove(java.lang.Object, java.lang.Object); + method public default boolean replace(K, V, V); + method public default V replace(K, V); + method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public abstract int size(); method public abstract java.util.Collection<V> values(); } @@ -58266,6 +58309,8 @@ package java.util { public static abstract interface Map.Entry { method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(); method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>); + method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(); + method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>); method public abstract boolean equals(java.lang.Object); method public abstract K getKey(); method public abstract V getValue(); @@ -58996,6 +59041,7 @@ package java.util { method public synchronized void removeAllElements(); method public synchronized boolean removeElement(java.lang.Object); method public synchronized void removeElementAt(int); + method public synchronized boolean removeIf(java.util.function.Predicate<? super E>); method public synchronized void setElementAt(E, int); method public synchronized void setSize(int); method public synchronized int size(); @@ -59047,6 +59093,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -59110,6 +59157,78 @@ package java.util.concurrent { ctor public CancellationException(java.lang.String); } + public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future { + ctor public CompletableFuture(); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...); + method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...); + method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor); + method public boolean cancel(boolean); + method public boolean complete(T); + method public boolean completeExceptionally(java.lang.Throwable); + method public static java.util.concurrent.CompletableFuture<U> completedFuture(U); + method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>); + method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; + method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; + method public T getNow(T); + method public int getNumberOfDependents(); + method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor); + method public boolean isCancelled(); + method public boolean isCompletedExceptionally(); + method public boolean isDone(); + method public T join(); + method public void obtrudeException(java.lang.Throwable); + method public void obtrudeValue(T); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>); + method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<T> toCompletableFuture(); + method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor); + } + + public static abstract interface CompletableFuture.AsynchronousCompletionTask { + } + + public class CompletionException extends java.lang.RuntimeException { + ctor protected CompletionException(); + ctor protected CompletionException(java.lang.String); + ctor public CompletionException(java.lang.String, java.lang.Throwable); + ctor public CompletionException(java.lang.Throwable); + } + public abstract interface CompletionService { method public abstract java.util.concurrent.Future<V> poll(); method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; @@ -59118,20 +59237,130 @@ package java.util.concurrent { method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException; } + public abstract interface CompletionStage { + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>); + method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture(); + method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor); + } + public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable { ctor public ConcurrentHashMap(); ctor public ConcurrentHashMap(int); ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>); ctor public ConcurrentHashMap(int, float); ctor public ConcurrentHashMap(int, float, int); + method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public boolean contains(java.lang.Object); method public java.util.Enumeration<V> elements(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); + method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>); + method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>); + method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachKey(long, java.util.function.Consumer<? super K>); + method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachValue(long, java.util.function.Consumer<? super V>); + method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>); + method public V getOrDefault(java.lang.Object, V); + method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V); method public java.util.Enumeration<K> keys(); + method public long mappingCount(); + method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); + method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(); + method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int); method public V putIfAbsent(K, V); + method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>); + method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator); + method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator); + method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator); + method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>); + method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator); + method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator); + method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator); + method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator); + method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator); + method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator); + method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>); + method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator); + method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator); + method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator); method public boolean remove(java.lang.Object, java.lang.Object); method public boolean replace(K, V, V); method public V replace(K, V); + method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>); + method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>); + method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>); + method public U searchValues(long, java.util.function.Function<? super V, ? extends U>); + } + + static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable { + method public final void clear(); + method public abstract boolean contains(java.lang.Object); + method public final boolean containsAll(java.util.Collection<?>); + method public java.util.concurrent.ConcurrentHashMap<K, V> getMap(); + method public final boolean isEmpty(); + method public abstract java.util.Iterator<E> iterator(); + method public abstract boolean remove(java.lang.Object); + method public final boolean removeAll(java.util.Collection<?>); + method public final boolean retainAll(java.util.Collection<?>); + method public final int size(); + method public final java.lang.Object[] toArray(); + method public final T[] toArray(T[]); + method public final java.lang.String toString(); + } + + public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set { + method public boolean add(K); + method public boolean addAll(java.util.Collection<? extends K>); + method public boolean contains(java.lang.Object); + method public void forEach(java.util.function.Consumer<? super K>); + method public V getMappedValue(); + method public java.util.Iterator<K> iterator(); + method public boolean remove(java.lang.Object); + method public java.util.Spliterator<K> spliterator(); } public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable { @@ -59161,6 +59390,7 @@ package java.util.concurrent { method public E removeLast(); method public boolean removeLastOccurrence(java.lang.Object); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable { @@ -59171,6 +59401,7 @@ package java.util.concurrent { method public E peek(); method public E poll(); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public abstract interface ConcurrentMap implements java.util.Map { @@ -59202,6 +59433,9 @@ package java.util.concurrent { method public K ceilingKey(K); method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone(); method public java.util.Comparator<? super K> comparator(); + method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public java.util.NavigableSet<K> descendingKeySet(); method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); @@ -59209,6 +59443,8 @@ package java.util.concurrent { method public K firstKey(); method public java.util.Map.Entry<K, V> floorEntry(K); method public K floorKey(K); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); + method public V getOrDefault(java.lang.Object, V); method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean); method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K); method public java.util.Map.Entry<K, V> higherEntry(K); @@ -59217,6 +59453,7 @@ package java.util.concurrent { method public K lastKey(); method public java.util.Map.Entry<K, V> lowerEntry(K); method public K lowerKey(K); + method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); method public java.util.NavigableSet<K> navigableKeySet(); method public java.util.Map.Entry<K, V> pollFirstEntry(); method public java.util.Map.Entry<K, V> pollLastEntry(); @@ -59224,6 +59461,7 @@ package java.util.concurrent { method public boolean remove(java.lang.Object, java.lang.Object); method public boolean replace(K, V, V); method public V replace(K, V); + method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean); method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K); method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean); @@ -59251,6 +59489,7 @@ package java.util.concurrent { method public E pollFirst(); method public E pollLast(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean); method public java.util.NavigableSet<E> subSet(E, E); method public java.util.NavigableSet<E> tailSet(E, boolean); @@ -59294,8 +59533,11 @@ package java.util.concurrent { public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable { ctor public CopyOnWriteArraySet(); ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>); + method public void forEach(java.util.function.Consumer<? super E>); method public java.util.Iterator<E> iterator(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public class CountDownLatch { @@ -59306,6 +59548,32 @@ package java.util.concurrent { method public long getCount(); } + public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask { + ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int); + ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>); + ctor protected CountedCompleter(); + method public final void addToPendingCount(int); + method public final boolean compareAndSetPendingCount(int, int); + method public void complete(T); + method public abstract void compute(); + method public final int decrementPendingCountUnlessZero(); + method protected final boolean exec(); + method public final java.util.concurrent.CountedCompleter<?> firstComplete(); + method public final java.util.concurrent.CountedCompleter<?> getCompleter(); + method public final int getPendingCount(); + method public T getRawResult(); + method public final java.util.concurrent.CountedCompleter<?> getRoot(); + method public final void helpComplete(int); + method public final java.util.concurrent.CountedCompleter<?> nextComplete(); + method public void onCompletion(java.util.concurrent.CountedCompleter<?>); + method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>); + method public final void propagateCompletion(); + method public final void quietlyCompleteRoot(); + method public final void setPendingCount(int); + method protected void setRawResult(T); + method public final void tryComplete(); + } + public class CyclicBarrier { ctor public CyclicBarrier(int, java.lang.Runnable); ctor public CyclicBarrier(int); @@ -59396,6 +59664,8 @@ package java.util.concurrent { method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory); method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(); method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory); + method public static java.util.concurrent.ExecutorService newWorkStealingPool(int); + method public static java.util.concurrent.ExecutorService newWorkStealingPool(); method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>); method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>); method public static java.util.concurrent.ThreadFactory privilegedThreadFactory(); @@ -59409,11 +59679,13 @@ package java.util.concurrent { ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean); method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit); method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public static java.util.concurrent.ForkJoinPool commonPool(); method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>); method public void execute(java.util.concurrent.ForkJoinTask<?>); method public void execute(java.lang.Runnable); method public int getActiveThreadCount(); method public boolean getAsyncMode(); + method public static int getCommonPoolParallelism(); method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory(); method public int getParallelism(); method public int getPoolSize(); @@ -59451,6 +59723,7 @@ package java.util.concurrent { method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T); method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>); method public boolean cancel(boolean); + method public final boolean compareAndSetForkJoinTaskTag(short, short); method public void complete(V); method public void completeExceptionally(java.lang.Throwable); method protected abstract boolean exec(); @@ -59458,6 +59731,7 @@ package java.util.concurrent { method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; method public final java.lang.Throwable getException(); + method public final short getForkJoinTaskTag(); method public static java.util.concurrent.ForkJoinPool getPool(); method public static int getQueuedTaskCount(); method public abstract V getRawResult(); @@ -59476,9 +59750,11 @@ package java.util.concurrent { method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask(); method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask(); method protected static java.util.concurrent.ForkJoinTask<?> pollTask(); + method public final void quietlyComplete(); method public final void quietlyInvoke(); method public final void quietlyJoin(); method public void reinitialize(); + method public final short setForkJoinTaskTag(short); method protected abstract void setRawResult(V); method public boolean tryUnfork(); } @@ -59552,6 +59828,7 @@ package java.util.concurrent { method public E removeLast(); method public boolean removeLastOccurrence(java.lang.Object); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; method public E takeFirst() throws java.lang.InterruptedException; method public E takeLast() throws java.lang.InterruptedException; @@ -59572,6 +59849,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -59591,6 +59869,7 @@ package java.util.concurrent { method public void put(E); method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; method public void transfer(E) throws java.lang.InterruptedException; method public boolean tryTransfer(E); @@ -59638,6 +59917,7 @@ package java.util.concurrent { method public void put(E); method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -59741,6 +60021,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -59870,112 +60151,136 @@ package java.util.concurrent.atomic { public class AtomicInteger extends java.lang.Number implements java.io.Serializable { ctor public AtomicInteger(int); ctor public AtomicInteger(); + method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator); method public final int addAndGet(int); method public final boolean compareAndSet(int, int); method public final int decrementAndGet(); method public double doubleValue(); method public float floatValue(); method public final int get(); + method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator); method public final int getAndAdd(int); method public final int getAndDecrement(); method public final int getAndIncrement(); method public final int getAndSet(int); + method public final int getAndUpdate(java.util.function.IntUnaryOperator); method public final int incrementAndGet(); method public int intValue(); method public final void lazySet(int); method public long longValue(); method public final void set(int); + method public final int updateAndGet(java.util.function.IntUnaryOperator); method public final boolean weakCompareAndSet(int, int); } public class AtomicIntegerArray implements java.io.Serializable { ctor public AtomicIntegerArray(int); ctor public AtomicIntegerArray(int[]); + method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator); method public final int addAndGet(int, int); method public final boolean compareAndSet(int, int, int); method public final int decrementAndGet(int); method public final int get(int); + method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator); method public final int getAndAdd(int, int); method public final int getAndDecrement(int); method public final int getAndIncrement(int); method public final int getAndSet(int, int); + method public final int getAndUpdate(int, java.util.function.IntUnaryOperator); method public final int incrementAndGet(int); method public final void lazySet(int, int); method public final int length(); method public final void set(int, int); + method public final int updateAndGet(int, java.util.function.IntUnaryOperator); method public final boolean weakCompareAndSet(int, int, int); } public abstract class AtomicIntegerFieldUpdater { ctor protected AtomicIntegerFieldUpdater(); + method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator); method public int addAndGet(T, int); method public abstract boolean compareAndSet(T, int, int); method public int decrementAndGet(T); method public abstract int get(T); + method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator); method public int getAndAdd(T, int); method public int getAndDecrement(T); method public int getAndIncrement(T); method public int getAndSet(T, int); + method public final int getAndUpdate(T, java.util.function.IntUnaryOperator); method public int incrementAndGet(T); method public abstract void lazySet(T, int); method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String); method public abstract void set(T, int); + method public final int updateAndGet(T, java.util.function.IntUnaryOperator); method public abstract boolean weakCompareAndSet(T, int, int); } public class AtomicLong extends java.lang.Number implements java.io.Serializable { ctor public AtomicLong(long); ctor public AtomicLong(); + method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator); method public final long addAndGet(long); method public final boolean compareAndSet(long, long); method public final long decrementAndGet(); method public double doubleValue(); method public float floatValue(); method public final long get(); + method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator); method public final long getAndAdd(long); method public final long getAndDecrement(); method public final long getAndIncrement(); method public final long getAndSet(long); + method public final long getAndUpdate(java.util.function.LongUnaryOperator); method public final long incrementAndGet(); method public int intValue(); method public final void lazySet(long); method public long longValue(); method public final void set(long); + method public final long updateAndGet(java.util.function.LongUnaryOperator); method public final boolean weakCompareAndSet(long, long); } public class AtomicLongArray implements java.io.Serializable { ctor public AtomicLongArray(int); ctor public AtomicLongArray(long[]); + method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator); method public long addAndGet(int, long); method public final boolean compareAndSet(int, long, long); method public final long decrementAndGet(int); method public final long get(int); + method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator); method public final long getAndAdd(int, long); method public final long getAndDecrement(int); method public final long getAndIncrement(int); method public final long getAndSet(int, long); + method public final long getAndUpdate(int, java.util.function.LongUnaryOperator); method public final long incrementAndGet(int); method public final void lazySet(int, long); method public final int length(); method public final void set(int, long); + method public final long updateAndGet(int, java.util.function.LongUnaryOperator); method public final boolean weakCompareAndSet(int, long, long); } public abstract class AtomicLongFieldUpdater { ctor protected AtomicLongFieldUpdater(); + method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator); method public long addAndGet(T, long); method public abstract boolean compareAndSet(T, long, long); method public long decrementAndGet(T); method public abstract long get(T); + method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator); method public long getAndAdd(T, long); method public long getAndDecrement(T); method public long getAndIncrement(T); method public long getAndSet(T, long); + method public final long getAndUpdate(T, java.util.function.LongUnaryOperator); method public long incrementAndGet(T); method public abstract void lazySet(T, long); method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String); method public abstract void set(T, long); + method public final long updateAndGet(T, java.util.function.LongUnaryOperator); method public abstract boolean weakCompareAndSet(T, long, long); } @@ -59993,34 +60298,46 @@ package java.util.concurrent.atomic { public class AtomicReference implements java.io.Serializable { ctor public AtomicReference(V); ctor public AtomicReference(); + method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>); method public final boolean compareAndSet(V, V); method public final V get(); + method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>); method public final V getAndSet(V); + method public final V getAndUpdate(java.util.function.UnaryOperator<V>); method public final void lazySet(V); method public final void set(V); + method public final V updateAndGet(java.util.function.UnaryOperator<V>); method public final boolean weakCompareAndSet(V, V); } public class AtomicReferenceArray implements java.io.Serializable { ctor public AtomicReferenceArray(int); ctor public AtomicReferenceArray(E[]); + method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>); method public final boolean compareAndSet(int, E, E); method public final E get(int); + method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>); method public final E getAndSet(int, E); + method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>); method public final void lazySet(int, E); method public final int length(); method public final void set(int, E); + method public final E updateAndGet(int, java.util.function.UnaryOperator<E>); method public final boolean weakCompareAndSet(int, E, E); } public abstract class AtomicReferenceFieldUpdater { ctor protected AtomicReferenceFieldUpdater(); + method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>); method public abstract boolean compareAndSet(T, V, V); method public abstract V get(T); + method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>); method public V getAndSet(T, V); + method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>); method public abstract void lazySet(T, V); method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String); method public abstract void set(T, V); + method public final V updateAndGet(T, java.util.function.UnaryOperator<V>); method public abstract boolean weakCompareAndSet(T, V, V); } @@ -60035,6 +60352,59 @@ package java.util.concurrent.atomic { method public boolean weakCompareAndSet(V, V, int, int); } + public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double); + method public void accumulate(double); + method public double doubleValue(); + method public float floatValue(); + method public double get(); + method public double getThenReset(); + method public int intValue(); + method public long longValue(); + method public void reset(); + } + + public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public DoubleAdder(); + method public void add(double); + method public double doubleValue(); + method public float floatValue(); + method public int intValue(); + method public long longValue(); + method public void reset(); + method public double sum(); + method public double sumThenReset(); + } + + public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public LongAccumulator(java.util.function.LongBinaryOperator, long); + method public void accumulate(long); + method public double doubleValue(); + method public float floatValue(); + method public long get(); + method public long getThenReset(); + method public int intValue(); + method public long longValue(); + method public void reset(); + } + + public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public LongAdder(); + method public void add(long); + method public void decrement(); + method public double doubleValue(); + method public float floatValue(); + method public void increment(); + method public int intValue(); + method public long longValue(); + method public void reset(); + method public long sum(); + method public long sumThenReset(); + } + + abstract class Striped64 extends java.lang.Number { + } + } package java.util.concurrent.locks { @@ -60242,6 +60612,34 @@ package java.util.concurrent.locks { method public void unlock(); } + public class StampedLock implements java.io.Serializable { + ctor public StampedLock(); + method public java.util.concurrent.locks.Lock asReadLock(); + method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock(); + method public java.util.concurrent.locks.Lock asWriteLock(); + method public int getReadLockCount(); + method public boolean isReadLocked(); + method public boolean isWriteLocked(); + method public long readLock(); + method public long readLockInterruptibly() throws java.lang.InterruptedException; + method public long tryConvertToOptimisticRead(long); + method public long tryConvertToReadLock(long); + method public long tryConvertToWriteLock(long); + method public long tryOptimisticRead(); + method public long tryReadLock(); + method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public boolean tryUnlockRead(); + method public boolean tryUnlockWrite(); + method public long tryWriteLock(); + method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public void unlock(long); + method public void unlockRead(long); + method public void unlockWrite(long); + method public boolean validate(long); + method public long writeLock(); + method public long writeLockInterruptibly() throws java.lang.InterruptedException; + } + } package java.util.function { diff --git a/api/removed.txt b/api/removed.txt index 2f553734068a..8ac2d63d99a2 100644 --- a/api/removed.txt +++ b/api/removed.txt @@ -35,6 +35,25 @@ package android.database { } +package android.graphics { + + public deprecated class AvoidXfermode extends android.graphics.Xfermode { + ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode); + } + + public static final class AvoidXfermode.Mode extends java.lang.Enum { + method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String); + method public static final android.graphics.AvoidXfermode.Mode[] values(); + enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID; + enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; + } + + public deprecated class PixelXorXfermode extends android.graphics.Xfermode { + ctor public PixelXorXfermode(int); + } + +} + package android.media { public final class AudioFormat implements android.os.Parcelable { diff --git a/api/system-current.txt b/api/system-current.txt index 0743b9154c38..741290848faf 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -654,6 +654,7 @@ package android { field public static final int fillBefore = 16843196; // 0x10101bc field public static final int fillColor = 16843780; // 0x1010404 field public static final int fillEnabled = 16843343; // 0x101024f + field public static final int fillType = 16844064; // 0x1010520 field public static final int fillViewport = 16843130; // 0x101017a field public static final int filter = 16843035; // 0x101011b field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4 @@ -3557,7 +3558,7 @@ package android.app { method public android.view.View getCurrentFocus(); method public android.app.FragmentManager getFragmentManager(); method public android.content.Intent getIntent(); - method public deprecated java.lang.Object getLastNonConfigurationInstance(); + method public java.lang.Object getLastNonConfigurationInstance(); method public android.view.LayoutInflater getLayoutInflater(); method public android.app.LoaderManager getLoaderManager(); method public java.lang.String getLocalClassName(); @@ -3653,14 +3654,13 @@ package android.app { method public boolean onPreparePanel(int, android.view.View, android.view.Menu); method public void onProvideAssistContent(android.app.assist.AssistContent); method public void onProvideAssistData(android.os.Bundle); - method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public android.net.Uri onProvideReferrer(); method public void onRequestPermissionsResult(int, java.lang.String[], int[]); method protected void onRestart(); method protected void onRestoreInstanceState(android.os.Bundle); method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle); method protected void onResume(); - method public deprecated java.lang.Object onRetainNonConfigurationInstance(); + method public java.lang.Object onRetainNonConfigurationInstance(); method protected void onSaveInstanceState(android.os.Bundle); method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle); method public boolean onSearchRequested(android.view.SearchEvent); @@ -4350,7 +4350,6 @@ package android.app { method public void onPanelClosed(int, android.view.Menu); method public boolean onPrepareOptionsMenu(android.view.Menu); method public boolean onPreparePanel(int, android.view.View, android.view.Menu); - method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public void onRestoreInstanceState(android.os.Bundle); method public android.os.Bundle onSaveInstanceState(); method public boolean onSearchRequested(android.view.SearchEvent); @@ -5991,7 +5990,6 @@ package android.app.admin { method public int getCurrentFailedPasswordAttempts(); method public deprecated java.lang.String getDeviceInitializerApp(); method public deprecated android.content.ComponentName getDeviceInitializerComponent(); - method public boolean getDeviceLoggingEnabled(android.content.ComponentName); method public java.lang.String getDeviceOwner(); method public java.lang.String getDeviceOwnerLockScreenInfo(); method public java.lang.String getDeviceOwnerNameOnAnyUser(); @@ -6047,6 +6045,7 @@ package android.app.admin { method public boolean isMasterVolumeMuted(android.content.ComponentName); method public boolean isProfileOwnerApp(java.lang.String); method public boolean isProvisioningAllowed(java.lang.String); + method public boolean isSecurityLoggingEnabled(android.content.ComponentName); method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String); method public void lockNow(); method public void notifyPendingSystemUpdate(long); @@ -6057,8 +6056,8 @@ package android.app.admin { method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); method public boolean requestBugreport(android.content.ComponentName); method public boolean resetPassword(java.lang.String, int); - method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName); - method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName); + method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName); + method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException; method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String); @@ -6071,7 +6070,6 @@ package android.app.admin { method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean); method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean); - method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean); method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); @@ -6104,6 +6102,7 @@ package android.app.admin { method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); method public void setScreenCaptureDisabled(android.content.ComponentName, boolean); method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); + method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean); method public void setShortSupportMessage(android.content.ComponentName, java.lang.String); method public boolean setStatusBarDisabled(android.content.ComponentName, boolean); method public int setStorageEncryption(android.content.ComponentName, boolean); @@ -6130,6 +6129,7 @@ package android.app.admin { field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2 field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3 field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4 + field public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5; // 0x5 field public static final int ENCRYPTION_STATUS_INACTIVE = 1; // 0x1 field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0 field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION"; @@ -6197,6 +6197,27 @@ package android.app.admin { field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } + public class SecurityLog { + ctor public SecurityLog(); + field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452 + field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451 + field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455 + field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456 + field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457 + field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458 + field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453 + field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 + } + + public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.Object getData(); + method public int getTag(); + method public long getTimeNanos(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR; + } + public class SystemUpdatePolicy implements android.os.Parcelable { method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy(); method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy(); @@ -6510,6 +6531,8 @@ package android.app.job { method public long getIntervalMillis(); method public long getMaxExecutionDelayMillis(); method public long getMinLatencyMillis(); + method public static final long getMinimumFlex(); + method public static final long getMinimumPeriod(); method public int getNetworkType(); method public android.content.ComponentName getService(); method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris(); @@ -6523,8 +6546,6 @@ package android.app.job { field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR; field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L - field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L - field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L field public static final int NETWORK_TYPE_ANY = 1; // 0x1 field public static final int NETWORK_TYPE_NONE = 0; // 0x0 field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2 @@ -6638,8 +6659,8 @@ package android.app.usage { method public long getTxPackets(); method public int getUid(); field public static final int ROAMING_ALL = -1; // 0xffffffff - field public static final int ROAMING_DEFAULT = 1; // 0x1 - field public static final int ROAMING_ROAMING = 2; // 0x2 + field public static final int ROAMING_NO = 1; // 0x1 + field public static final int ROAMING_YES = 2; // 0x2 field public static final int STATE_ALL = -1; // 0xffffffff field public static final int STATE_DEFAULT = 1; // 0x1 field public static final int STATE_FOREGROUND = 2; // 0x2 @@ -6847,31 +6868,6 @@ package android.appwidget { } -package android.auditing { - - public class SecurityLog { - ctor public SecurityLog(); - field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452 - field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451 - field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455 - field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456 - field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457 - field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458 - field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453 - field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 - } - - public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { - method public int describeContents(); - method public java.lang.Object getData(); - method public int getTag(); - method public long getTimeNanos(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR; - } - -} - package android.bluetooth { public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile { @@ -8408,6 +8404,7 @@ package android.content { field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard"; field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity"; field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir"; + field public static final java.lang.String CONTEXTHUB_SERVICE = "contexthub"; field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2 field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1 field public static final int CONTEXT_RESTRICTED = 4; // 0x4 @@ -8416,7 +8413,7 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; - field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties"; + field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; @@ -9787,6 +9784,7 @@ package android.content.pm { method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle); method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle); method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle); + method public boolean hasShortcutHostPermission(); method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle); method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle); method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle); @@ -9927,11 +9925,12 @@ package android.content.pm { public static class PackageInstaller.SessionParams implements android.os.Parcelable { ctor public PackageInstaller.SessionParams(int); method public int describeContents(); + method public void setAllowDowngrade(boolean); method public void setAppIcon(android.graphics.Bitmap); method public void setAppLabel(java.lang.CharSequence); method public void setAppPackageName(java.lang.String); + method public void setDontKillApp(boolean); method public void setGrantedRuntimePermissions(java.lang.String[]); - method public void setInstallFlagsDowngrade(); method public void setInstallLocation(int); method public void setOriginatingUid(int); method public void setOriginatingUri(android.net.Uri); @@ -10510,7 +10509,6 @@ package android.content.res { method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); - method public int getChangingConfigurations(); method public int getColorForState(int[], int); method public int getDefaultColor(); method public boolean isOpaque(); @@ -10522,6 +10520,7 @@ package android.content.res { public abstract class ComplexColor { ctor public ComplexColor(); + method public int getChangingConfigurations(); method public abstract int getDefaultColor(); method public boolean isStateful(); } @@ -11869,17 +11868,6 @@ package android.gesture { package android.graphics { - public deprecated class AvoidXfermode extends android.graphics.Xfermode { - ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode); - } - - public static final class AvoidXfermode.Mode extends java.lang.Enum { - method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String); - method public static final android.graphics.AvoidXfermode.Mode[] values(); - enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID; - enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; - } - public final class Bitmap implements android.os.Parcelable { method public boolean compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream); method public android.graphics.Bitmap copy(android.graphics.Bitmap.Config, boolean); @@ -12746,10 +12734,6 @@ package android.graphics { field public int bytesPerPixel; } - public deprecated class PixelXorXfermode extends android.graphics.Xfermode { - ctor public PixelXorXfermode(int); - } - public class Point implements android.os.Parcelable { ctor public Point(); ctor public Point(int, int); @@ -13429,9 +13413,9 @@ package android.graphics.drawable { method public void setPaddingMode(int); method public void setPaddingRelative(int, int, int, int); method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); + field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000 field public static final int PADDING_MODE_NEST = 0; // 0x0 field public static final int PADDING_MODE_STACK = 1; // 0x1 - field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000 } public class LevelListDrawable extends android.graphics.drawable.DrawableContainer { @@ -15290,37 +15274,32 @@ package android.hardware.location { method public java.lang.String getToolchain(); method public int getToolchainVersion(); method public java.lang.String getVendor(); - method public void setId(int); - method public void setMemoryRegions(android.hardware.location.MemoryRegion[]); - method public void setName(java.lang.String); - method public void setPeakMips(float); - method public void setPeakPowerDrawMw(float); - method public void setPlatformVersion(int); - method public void setSleepPowerDrawMw(float); - method public void setStaticSwVersion(int); - method public void setStoppedPowerDrawMw(float); - method public void setSupportedSensors(int[]); - method public void setToolchain(java.lang.String); - method public void setToolchainVersion(int); - method public void setVendor(java.lang.String); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubInfo> CREATOR; } public final class ContextHubManager { - method public java.lang.Integer[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter); - method public int[] getContexthubHandles(); - method public android.hardware.location.ContextHubInfo getContexthubInfo(int); + method public int[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter); + method public int[] getContextHubHandles(); + method public android.hardware.location.ContextHubInfo getContextHubInfo(int); method public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int); method public int loadNanoApp(int, android.hardware.location.NanoApp); + method public int registerContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback); + method public int registerContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback, android.os.Handler); method public int sendMessage(int, int, android.hardware.location.ContextHubMessage); method public int unloadNanoApp(int); + method public int unregisterContextHubCallback(android.hardware.location.ContextHubManager.ContextHubCallback); field public static final int ANY_HUB = -1; // 0xffffffff field public static final int MSG_DATA_SEND = 3; // 0x3 field public static final int MSG_LOAD_NANO_APP = 1; // 0x1 field public static final int MSG_UNLOAD_NANO_APP = 2; // 0x2 } + public static abstract class ContextHubManager.ContextHubCallback { + ctor protected ContextHubManager.ContextHubCallback(); + method public abstract void onMessageReceipt(int, int, android.hardware.location.ContextHubMessage); + } + public class ContextHubMessage { ctor public ContextHubMessage(int, int, byte[]); method public int describeContents(); @@ -20454,7 +20433,6 @@ package android.location { method public boolean hasCarrierPhase(); method public boolean hasCarrierPhaseUncertainty(); method public boolean hasSnrInDb(); - method public boolean isPseudorangeRateCorrected(); method public void writeToParcel(android.os.Parcel, int); field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4 field public static final int ADR_STATE_RESET = 2; // 0x2 @@ -25742,9 +25720,11 @@ package android.net { public class ScoredNetwork implements android.os.Parcelable { ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve); + ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean); method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR; + field public final boolean meteredHint; field public final android.net.NetworkKey networkKey; field public final android.net.RssiCurve rssiCurve; } @@ -33113,6 +33093,7 @@ package android.provider { public static class CallLog.Calls implements android.provider.BaseColumns { ctor public CallLog.Calls(); method public static java.lang.String getLastOutgoingCall(android.content.Context); + field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7 field public static final int BLOCKED_TYPE = 6; // 0x6 field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number"; field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri"; @@ -33135,6 +33116,7 @@ package android.provider { field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; field public static final java.lang.String FEATURES = "features"; + field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 field public static final int FEATURES_VIDEO = 1; // 0x1 field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location"; field public static final int INCOMING_TYPE = 1; // 0x1 @@ -34910,7 +34892,6 @@ package android.provider { field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; - field public static final java.lang.String ACTION_SCREEN_READER_TUTORIAL = "android.settings.SCREEN_READER_TUTORIAL"; field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; @@ -38657,10 +38638,12 @@ package android.telecom { method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.Call.Callback); method public void registerCallback(android.telecom.Call.Callback, android.os.Handler); method public void reject(boolean, java.lang.String); method public deprecated void removeListener(android.telecom.Call.Listener); + method public void sendCallEvent(java.lang.String, android.os.Bundle); method public void splitFromConference(); method public void stopDtmfTone(); method public void swapConference(); @@ -38675,6 +38658,7 @@ package android.telecom { field public static final int STATE_HOLDING = 3; // 0x3 field public static final int STATE_NEW = 0; // 0x0 field public static final deprecated int STATE_PRE_DIAL_WAIT = 8; // 0x8 + field public static final int STATE_PULLING_CALL = 11; // 0xb field public static final int STATE_RINGING = 2; // 0x2 field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8 } @@ -38685,6 +38669,7 @@ package android.telecom { method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>); method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>); method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details); method public void onParentChanged(android.telecom.Call, android.telecom.Call); method public void onPostDialWait(android.telecom.Call, java.lang.String); @@ -38715,6 +38700,7 @@ package android.telecom { method public static java.lang.String propertiesToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 @@ -38734,6 +38720,7 @@ package android.telecom { field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4 field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40 field public static final int PROPERTY_WIFI = 8; // 0x8 field public static final int PROPERTY_WORK_CALL = 32; // 0x20 } @@ -38859,15 +38846,19 @@ package android.telecom { method public void onAnswer(); method public deprecated void onAudioStateChanged(android.telecom.AudioState); method public void onCallAudioStateChanged(android.telecom.CallAudioState); + method public void onCallEvent(java.lang.String, android.os.Bundle); method public void onDisconnect(); method public void onHold(); method public void onPlayDtmfTone(char); method public void onPostDialContinue(boolean); + method public void onPullExternalCall(); method public void onReject(); + method public void onReject(java.lang.String); method public void onSeparate(); method public void onStateChanged(int); method public void onStopDtmfTone(); method public void onUnhold(); + method public void sendConnectionEvent(java.lang.String, android.os.Bundle); method public final void setActive(); method public final void setAddress(android.net.Uri, int); method public final void setAudioModeIsVoip(boolean); @@ -38891,9 +38882,12 @@ package android.telecom { method public static java.lang.String stateToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000 + field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 + field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4 field public static final int CAPABILITY_MUTE = 64; // 0x40 @@ -38907,6 +38901,7 @@ package android.telecom { field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800 field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2 field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8 + field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED"; field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS"; field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER"; @@ -38916,6 +38911,7 @@ package android.telecom { field public static final int STATE_HOLDING = 5; // 0x5 field public static final int STATE_INITIALIZING = 0; // 0x0 field public static final int STATE_NEW = 1; // 0x1 + field public static final int STATE_PULLING_CALL = 7; // 0x7 field public static final int STATE_RINGING = 2; // 0x2 } @@ -38993,7 +38989,9 @@ package android.telecom { method public java.lang.String getReason(); method public int getTone(); method public void writeToParcel(android.os.Parcel, int); + field public static final int ANSWERED_ELSEWHERE = 11; // 0xb field public static final int BUSY = 7; // 0x7 + field public static final int CALL_PULLED = 12; // 0xc field public static final int CANCELED = 4; // 0x4 field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR; @@ -39030,6 +39028,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onCallRemoved(android.telecom.Call); method public void onCanAddCallChanged(boolean); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public deprecated void onPhoneCreated(android.telecom.Phone); method public deprecated void onPhoneDestroyed(android.telecom.Phone); method public void onSilenceRinger(); @@ -39235,6 +39234,7 @@ package android.telecom { method public boolean isVoipAudioMode(); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.RemoteConnection.Callback); method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler); method public void reject(); @@ -39252,6 +39252,7 @@ package android.telecom { method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference); method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int); + method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle); method public void onDestroyed(android.telecom.RemoteConnection); method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause); method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle); @@ -39376,6 +39377,7 @@ package android.telecom { field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"; field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; + field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI"; field public static final int PRESENTATION_ALLOWED = 1; // 0x1 @@ -39519,6 +39521,7 @@ package android.telephony { field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_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_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool"; field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool"; @@ -45347,6 +45350,7 @@ package android.view { method public void onStartTemporaryDetach(); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); + method public void onVisibilityAggregated(boolean); method protected void onVisibilityChanged(android.view.View, int); method public void onWindowFocusChanged(boolean); method public void onWindowSystemUiVisibilityChanged(int); @@ -46444,7 +46448,7 @@ package android.view { method public abstract boolean onMenuOpened(int, android.view.Menu); method public abstract void onPanelClosed(int, android.view.Menu); method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu); - method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); + method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public abstract boolean onSearchRequested(); method public abstract boolean onSearchRequested(android.view.SearchEvent); method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams); @@ -48698,12 +48702,13 @@ package android.webkit { ctor public WebViewFactory(); method public static android.content.pm.PackageInfo getLoadedPackageInfo(); method public static java.lang.String getWebViewPackageName(); - method public static int loadWebViewNativeLibraryFromPackage(java.lang.String); + method public static int loadWebViewNativeLibraryFromPackage(java.lang.String, java.lang.ClassLoader); method public static void prepareWebViewInZygote(); field public static final java.lang.String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = "persist.sys.webview.vmsize"; field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2 field public static final int LIBLOAD_FAILED_JNI_CALL = 7; // 0x7 field public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4; // 0x4 + field public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10; // 0xa field public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6; // 0x6 field public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5; // 0x5 field public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3; // 0x3 @@ -48848,7 +48853,9 @@ package android.webkit { public static abstract interface WebViewProvider.ViewDelegate { method public abstract boolean dispatchKeyEvent(android.view.KeyEvent); + method public abstract android.view.View findFocus(android.view.View); method public abstract android.view.accessibility.AccessibilityNodeProvider getAccessibilityNodeProvider(); + method public abstract android.os.Handler getHandler(android.os.Handler); method public abstract void onActivityResult(int, int, android.content.Intent); method public abstract void onAttachedToWindow(); method public abstract void onConfigurationChanged(android.content.res.Configuration); @@ -60443,6 +60450,7 @@ package java.util { method public void ensureCapacity(int); method public void forEach(java.util.function.Consumer<? super E>); method public E get(int); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); method public java.util.Spliterator<E> spliterator(); method public void trimToSize(); @@ -60527,6 +60535,28 @@ package java.util { method public static int hashCode(float[]); method public static int hashCode(double[]); method public static int hashCode(java.lang.Object[]); + method public static void parallelSort(byte[]); + method public static void parallelSort(byte[], int, int); + method public static void parallelSort(char[]); + method public static void parallelSort(char[], int, int); + method public static void parallelSort(short[]); + method public static void parallelSort(short[], int, int); + method public static void parallelSort(int[]); + method public static void parallelSort(int[], int, int); + method public static void parallelSort(long[]); + method public static void parallelSort(long[], int, int); + method public static void parallelSort(float[]); + method public static void parallelSort(float[], int, int); + method public static void parallelSort(double[]); + method public static void parallelSort(double[], int, int); + method public static void parallelSort(T[]); + method public static void parallelSort(T[], int, int); + method public static void parallelSort(T[], java.util.Comparator<? super T>); + method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>); + method public static void setAll(T[], java.util.function.IntFunction<? extends T>); + method public static void setAll(int[], java.util.function.IntUnaryOperator); + method public static void setAll(long[], java.util.function.IntToLongFunction); + method public static void setAll(double[], java.util.function.IntToDoubleFunction); method public static void sort(int[]); method public static void sort(int[], int, int); method public static void sort(long[]); @@ -60714,6 +60744,7 @@ package java.util { method public abstract java.util.Iterator<E> iterator(); method public abstract boolean remove(java.lang.Object); method public abstract boolean removeAll(java.util.Collection<?>); + method public default boolean removeIf(java.util.function.Predicate<? super E>); method public abstract boolean retainAll(java.util.Collection<?>); method public abstract int size(); method public abstract java.lang.Object[] toArray(); @@ -61347,18 +61378,28 @@ package java.util { public abstract interface Map { method public abstract void clear(); + method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public abstract boolean containsKey(java.lang.Object); method public abstract boolean containsValue(java.lang.Object); method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet(); method public abstract boolean equals(java.lang.Object); method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public abstract V get(java.lang.Object); + method public default V getOrDefault(java.lang.Object, V); method public abstract int hashCode(); method public abstract boolean isEmpty(); method public abstract java.util.Set<K> keySet(); + method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); method public abstract V put(K, V); method public abstract void putAll(java.util.Map<? extends K, ? extends V>); + method public default V putIfAbsent(K, V); method public abstract V remove(java.lang.Object); + method public default boolean remove(java.lang.Object, java.lang.Object); + method public default boolean replace(K, V, V); + method public default V replace(K, V); + method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public abstract int size(); method public abstract java.util.Collection<V> values(); } @@ -61366,6 +61407,8 @@ package java.util { public static abstract interface Map.Entry { method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(); method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>); + method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(); + method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>); method public abstract boolean equals(java.lang.Object); method public abstract K getKey(); method public abstract V getValue(); @@ -62096,6 +62139,7 @@ package java.util { method public synchronized void removeAllElements(); method public synchronized boolean removeElement(java.lang.Object); method public synchronized void removeElementAt(int); + method public synchronized boolean removeIf(java.util.function.Predicate<? super E>); method public synchronized void setElementAt(E, int); method public synchronized void setSize(int); method public synchronized int size(); @@ -62147,6 +62191,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -62210,6 +62255,78 @@ package java.util.concurrent { ctor public CancellationException(java.lang.String); } + public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future { + ctor public CompletableFuture(); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...); + method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...); + method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor); + method public boolean cancel(boolean); + method public boolean complete(T); + method public boolean completeExceptionally(java.lang.Throwable); + method public static java.util.concurrent.CompletableFuture<U> completedFuture(U); + method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>); + method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; + method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; + method public T getNow(T); + method public int getNumberOfDependents(); + method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor); + method public boolean isCancelled(); + method public boolean isCompletedExceptionally(); + method public boolean isDone(); + method public T join(); + method public void obtrudeException(java.lang.Throwable); + method public void obtrudeValue(T); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>); + method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<T> toCompletableFuture(); + method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor); + } + + public static abstract interface CompletableFuture.AsynchronousCompletionTask { + } + + public class CompletionException extends java.lang.RuntimeException { + ctor protected CompletionException(); + ctor protected CompletionException(java.lang.String); + ctor public CompletionException(java.lang.String, java.lang.Throwable); + ctor public CompletionException(java.lang.Throwable); + } + public abstract interface CompletionService { method public abstract java.util.concurrent.Future<V> poll(); method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; @@ -62218,20 +62335,130 @@ package java.util.concurrent { method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException; } + public abstract interface CompletionStage { + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>); + method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture(); + method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor); + } + public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable { ctor public ConcurrentHashMap(); ctor public ConcurrentHashMap(int); ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>); ctor public ConcurrentHashMap(int, float); ctor public ConcurrentHashMap(int, float, int); + method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public boolean contains(java.lang.Object); method public java.util.Enumeration<V> elements(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); + method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>); + method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>); + method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachKey(long, java.util.function.Consumer<? super K>); + method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachValue(long, java.util.function.Consumer<? super V>); + method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>); + method public V getOrDefault(java.lang.Object, V); + method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V); method public java.util.Enumeration<K> keys(); + method public long mappingCount(); + method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); + method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(); + method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int); method public V putIfAbsent(K, V); + method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>); + method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator); + method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator); + method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator); + method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>); + method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator); + method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator); + method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator); + method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator); + method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator); + method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator); + method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>); + method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator); + method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator); + method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator); method public boolean remove(java.lang.Object, java.lang.Object); method public boolean replace(K, V, V); method public V replace(K, V); + method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>); + method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>); + method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>); + method public U searchValues(long, java.util.function.Function<? super V, ? extends U>); + } + + static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable { + method public final void clear(); + method public abstract boolean contains(java.lang.Object); + method public final boolean containsAll(java.util.Collection<?>); + method public java.util.concurrent.ConcurrentHashMap<K, V> getMap(); + method public final boolean isEmpty(); + method public abstract java.util.Iterator<E> iterator(); + method public abstract boolean remove(java.lang.Object); + method public final boolean removeAll(java.util.Collection<?>); + method public final boolean retainAll(java.util.Collection<?>); + method public final int size(); + method public final java.lang.Object[] toArray(); + method public final T[] toArray(T[]); + method public final java.lang.String toString(); + } + + public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set { + method public boolean add(K); + method public boolean addAll(java.util.Collection<? extends K>); + method public boolean contains(java.lang.Object); + method public void forEach(java.util.function.Consumer<? super K>); + method public V getMappedValue(); + method public java.util.Iterator<K> iterator(); + method public boolean remove(java.lang.Object); + method public java.util.Spliterator<K> spliterator(); } public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable { @@ -62261,6 +62488,7 @@ package java.util.concurrent { method public E removeLast(); method public boolean removeLastOccurrence(java.lang.Object); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable { @@ -62271,6 +62499,7 @@ package java.util.concurrent { method public E peek(); method public E poll(); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public abstract interface ConcurrentMap implements java.util.Map { @@ -62302,6 +62531,9 @@ package java.util.concurrent { method public K ceilingKey(K); method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone(); method public java.util.Comparator<? super K> comparator(); + method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public java.util.NavigableSet<K> descendingKeySet(); method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); @@ -62309,6 +62541,8 @@ package java.util.concurrent { method public K firstKey(); method public java.util.Map.Entry<K, V> floorEntry(K); method public K floorKey(K); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); + method public V getOrDefault(java.lang.Object, V); method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean); method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K); method public java.util.Map.Entry<K, V> higherEntry(K); @@ -62317,6 +62551,7 @@ package java.util.concurrent { method public K lastKey(); method public java.util.Map.Entry<K, V> lowerEntry(K); method public K lowerKey(K); + method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); method public java.util.NavigableSet<K> navigableKeySet(); method public java.util.Map.Entry<K, V> pollFirstEntry(); method public java.util.Map.Entry<K, V> pollLastEntry(); @@ -62324,6 +62559,7 @@ package java.util.concurrent { method public boolean remove(java.lang.Object, java.lang.Object); method public boolean replace(K, V, V); method public V replace(K, V); + method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean); method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K); method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean); @@ -62351,6 +62587,7 @@ package java.util.concurrent { method public E pollFirst(); method public E pollLast(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean); method public java.util.NavigableSet<E> subSet(E, E); method public java.util.NavigableSet<E> tailSet(E, boolean); @@ -62394,8 +62631,11 @@ package java.util.concurrent { public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable { ctor public CopyOnWriteArraySet(); ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>); + method public void forEach(java.util.function.Consumer<? super E>); method public java.util.Iterator<E> iterator(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public class CountDownLatch { @@ -62406,6 +62646,32 @@ package java.util.concurrent { method public long getCount(); } + public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask { + ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int); + ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>); + ctor protected CountedCompleter(); + method public final void addToPendingCount(int); + method public final boolean compareAndSetPendingCount(int, int); + method public void complete(T); + method public abstract void compute(); + method public final int decrementPendingCountUnlessZero(); + method protected final boolean exec(); + method public final java.util.concurrent.CountedCompleter<?> firstComplete(); + method public final java.util.concurrent.CountedCompleter<?> getCompleter(); + method public final int getPendingCount(); + method public T getRawResult(); + method public final java.util.concurrent.CountedCompleter<?> getRoot(); + method public final void helpComplete(int); + method public final java.util.concurrent.CountedCompleter<?> nextComplete(); + method public void onCompletion(java.util.concurrent.CountedCompleter<?>); + method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>); + method public final void propagateCompletion(); + method public final void quietlyCompleteRoot(); + method public final void setPendingCount(int); + method protected void setRawResult(T); + method public final void tryComplete(); + } + public class CyclicBarrier { ctor public CyclicBarrier(int, java.lang.Runnable); ctor public CyclicBarrier(int); @@ -62496,6 +62762,8 @@ package java.util.concurrent { method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory); method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(); method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory); + method public static java.util.concurrent.ExecutorService newWorkStealingPool(int); + method public static java.util.concurrent.ExecutorService newWorkStealingPool(); method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>); method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>); method public static java.util.concurrent.ThreadFactory privilegedThreadFactory(); @@ -62509,11 +62777,13 @@ package java.util.concurrent { ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean); method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit); method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public static java.util.concurrent.ForkJoinPool commonPool(); method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>); method public void execute(java.util.concurrent.ForkJoinTask<?>); method public void execute(java.lang.Runnable); method public int getActiveThreadCount(); method public boolean getAsyncMode(); + method public static int getCommonPoolParallelism(); method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory(); method public int getParallelism(); method public int getPoolSize(); @@ -62551,6 +62821,7 @@ package java.util.concurrent { method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T); method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>); method public boolean cancel(boolean); + method public final boolean compareAndSetForkJoinTaskTag(short, short); method public void complete(V); method public void completeExceptionally(java.lang.Throwable); method protected abstract boolean exec(); @@ -62558,6 +62829,7 @@ package java.util.concurrent { method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; method public final java.lang.Throwable getException(); + method public final short getForkJoinTaskTag(); method public static java.util.concurrent.ForkJoinPool getPool(); method public static int getQueuedTaskCount(); method public abstract V getRawResult(); @@ -62576,9 +62848,11 @@ package java.util.concurrent { method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask(); method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask(); method protected static java.util.concurrent.ForkJoinTask<?> pollTask(); + method public final void quietlyComplete(); method public final void quietlyInvoke(); method public final void quietlyJoin(); method public void reinitialize(); + method public final short setForkJoinTaskTag(short); method protected abstract void setRawResult(V); method public boolean tryUnfork(); } @@ -62652,6 +62926,7 @@ package java.util.concurrent { method public E removeLast(); method public boolean removeLastOccurrence(java.lang.Object); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; method public E takeFirst() throws java.lang.InterruptedException; method public E takeLast() throws java.lang.InterruptedException; @@ -62672,6 +62947,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -62691,6 +62967,7 @@ package java.util.concurrent { method public void put(E); method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; method public void transfer(E) throws java.lang.InterruptedException; method public boolean tryTransfer(E); @@ -62738,6 +63015,7 @@ package java.util.concurrent { method public void put(E); method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -62841,6 +63119,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -62970,112 +63249,136 @@ package java.util.concurrent.atomic { public class AtomicInteger extends java.lang.Number implements java.io.Serializable { ctor public AtomicInteger(int); ctor public AtomicInteger(); + method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator); method public final int addAndGet(int); method public final boolean compareAndSet(int, int); method public final int decrementAndGet(); method public double doubleValue(); method public float floatValue(); method public final int get(); + method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator); method public final int getAndAdd(int); method public final int getAndDecrement(); method public final int getAndIncrement(); method public final int getAndSet(int); + method public final int getAndUpdate(java.util.function.IntUnaryOperator); method public final int incrementAndGet(); method public int intValue(); method public final void lazySet(int); method public long longValue(); method public final void set(int); + method public final int updateAndGet(java.util.function.IntUnaryOperator); method public final boolean weakCompareAndSet(int, int); } public class AtomicIntegerArray implements java.io.Serializable { ctor public AtomicIntegerArray(int); ctor public AtomicIntegerArray(int[]); + method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator); method public final int addAndGet(int, int); method public final boolean compareAndSet(int, int, int); method public final int decrementAndGet(int); method public final int get(int); + method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator); method public final int getAndAdd(int, int); method public final int getAndDecrement(int); method public final int getAndIncrement(int); method public final int getAndSet(int, int); + method public final int getAndUpdate(int, java.util.function.IntUnaryOperator); method public final int incrementAndGet(int); method public final void lazySet(int, int); method public final int length(); method public final void set(int, int); + method public final int updateAndGet(int, java.util.function.IntUnaryOperator); method public final boolean weakCompareAndSet(int, int, int); } public abstract class AtomicIntegerFieldUpdater { ctor protected AtomicIntegerFieldUpdater(); + method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator); method public int addAndGet(T, int); method public abstract boolean compareAndSet(T, int, int); method public int decrementAndGet(T); method public abstract int get(T); + method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator); method public int getAndAdd(T, int); method public int getAndDecrement(T); method public int getAndIncrement(T); method public int getAndSet(T, int); + method public final int getAndUpdate(T, java.util.function.IntUnaryOperator); method public int incrementAndGet(T); method public abstract void lazySet(T, int); method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String); method public abstract void set(T, int); + method public final int updateAndGet(T, java.util.function.IntUnaryOperator); method public abstract boolean weakCompareAndSet(T, int, int); } public class AtomicLong extends java.lang.Number implements java.io.Serializable { ctor public AtomicLong(long); ctor public AtomicLong(); + method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator); method public final long addAndGet(long); method public final boolean compareAndSet(long, long); method public final long decrementAndGet(); method public double doubleValue(); method public float floatValue(); method public final long get(); + method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator); method public final long getAndAdd(long); method public final long getAndDecrement(); method public final long getAndIncrement(); method public final long getAndSet(long); + method public final long getAndUpdate(java.util.function.LongUnaryOperator); method public final long incrementAndGet(); method public int intValue(); method public final void lazySet(long); method public long longValue(); method public final void set(long); + method public final long updateAndGet(java.util.function.LongUnaryOperator); method public final boolean weakCompareAndSet(long, long); } public class AtomicLongArray implements java.io.Serializable { ctor public AtomicLongArray(int); ctor public AtomicLongArray(long[]); + method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator); method public long addAndGet(int, long); method public final boolean compareAndSet(int, long, long); method public final long decrementAndGet(int); method public final long get(int); + method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator); method public final long getAndAdd(int, long); method public final long getAndDecrement(int); method public final long getAndIncrement(int); method public final long getAndSet(int, long); + method public final long getAndUpdate(int, java.util.function.LongUnaryOperator); method public final long incrementAndGet(int); method public final void lazySet(int, long); method public final int length(); method public final void set(int, long); + method public final long updateAndGet(int, java.util.function.LongUnaryOperator); method public final boolean weakCompareAndSet(int, long, long); } public abstract class AtomicLongFieldUpdater { ctor protected AtomicLongFieldUpdater(); + method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator); method public long addAndGet(T, long); method public abstract boolean compareAndSet(T, long, long); method public long decrementAndGet(T); method public abstract long get(T); + method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator); method public long getAndAdd(T, long); method public long getAndDecrement(T); method public long getAndIncrement(T); method public long getAndSet(T, long); + method public final long getAndUpdate(T, java.util.function.LongUnaryOperator); method public long incrementAndGet(T); method public abstract void lazySet(T, long); method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String); method public abstract void set(T, long); + method public final long updateAndGet(T, java.util.function.LongUnaryOperator); method public abstract boolean weakCompareAndSet(T, long, long); } @@ -63093,34 +63396,46 @@ package java.util.concurrent.atomic { public class AtomicReference implements java.io.Serializable { ctor public AtomicReference(V); ctor public AtomicReference(); + method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>); method public final boolean compareAndSet(V, V); method public final V get(); + method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>); method public final V getAndSet(V); + method public final V getAndUpdate(java.util.function.UnaryOperator<V>); method public final void lazySet(V); method public final void set(V); + method public final V updateAndGet(java.util.function.UnaryOperator<V>); method public final boolean weakCompareAndSet(V, V); } public class AtomicReferenceArray implements java.io.Serializable { ctor public AtomicReferenceArray(int); ctor public AtomicReferenceArray(E[]); + method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>); method public final boolean compareAndSet(int, E, E); method public final E get(int); + method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>); method public final E getAndSet(int, E); + method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>); method public final void lazySet(int, E); method public final int length(); method public final void set(int, E); + method public final E updateAndGet(int, java.util.function.UnaryOperator<E>); method public final boolean weakCompareAndSet(int, E, E); } public abstract class AtomicReferenceFieldUpdater { ctor protected AtomicReferenceFieldUpdater(); + method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>); method public abstract boolean compareAndSet(T, V, V); method public abstract V get(T); + method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>); method public V getAndSet(T, V); + method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>); method public abstract void lazySet(T, V); method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String); method public abstract void set(T, V); + method public final V updateAndGet(T, java.util.function.UnaryOperator<V>); method public abstract boolean weakCompareAndSet(T, V, V); } @@ -63135,6 +63450,59 @@ package java.util.concurrent.atomic { method public boolean weakCompareAndSet(V, V, int, int); } + public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double); + method public void accumulate(double); + method public double doubleValue(); + method public float floatValue(); + method public double get(); + method public double getThenReset(); + method public int intValue(); + method public long longValue(); + method public void reset(); + } + + public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public DoubleAdder(); + method public void add(double); + method public double doubleValue(); + method public float floatValue(); + method public int intValue(); + method public long longValue(); + method public void reset(); + method public double sum(); + method public double sumThenReset(); + } + + public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public LongAccumulator(java.util.function.LongBinaryOperator, long); + method public void accumulate(long); + method public double doubleValue(); + method public float floatValue(); + method public long get(); + method public long getThenReset(); + method public int intValue(); + method public long longValue(); + method public void reset(); + } + + public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public LongAdder(); + method public void add(long); + method public void decrement(); + method public double doubleValue(); + method public float floatValue(); + method public void increment(); + method public int intValue(); + method public long longValue(); + method public void reset(); + method public long sum(); + method public long sumThenReset(); + } + + abstract class Striped64 extends java.lang.Number { + } + } package java.util.concurrent.locks { @@ -63342,6 +63710,34 @@ package java.util.concurrent.locks { method public void unlock(); } + public class StampedLock implements java.io.Serializable { + ctor public StampedLock(); + method public java.util.concurrent.locks.Lock asReadLock(); + method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock(); + method public java.util.concurrent.locks.Lock asWriteLock(); + method public int getReadLockCount(); + method public boolean isReadLocked(); + method public boolean isWriteLocked(); + method public long readLock(); + method public long readLockInterruptibly() throws java.lang.InterruptedException; + method public long tryConvertToOptimisticRead(long); + method public long tryConvertToReadLock(long); + method public long tryConvertToWriteLock(long); + method public long tryOptimisticRead(); + method public long tryReadLock(); + method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public boolean tryUnlockRead(); + method public boolean tryUnlockWrite(); + method public long tryWriteLock(); + method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public void unlock(long); + method public void unlockRead(long); + method public void unlockWrite(long); + method public boolean validate(long); + method public long writeLock(); + method public long writeLockInterruptibly() throws java.lang.InterruptedException; + } + } package java.util.function { diff --git a/api/system-removed.txt b/api/system-removed.txt index 79f72975a194..caeecf5d544d 100644 --- a/api/system-removed.txt +++ b/api/system-removed.txt @@ -33,6 +33,25 @@ package android.database { } +package android.graphics { + + public deprecated class AvoidXfermode extends android.graphics.Xfermode { + ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode); + } + + public static final class AvoidXfermode.Mode extends java.lang.Enum { + method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String); + method public static final android.graphics.AvoidXfermode.Mode[] values(); + enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID; + enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; + } + + public deprecated class PixelXorXfermode extends android.graphics.Xfermode { + ctor public PixelXorXfermode(int); + } + +} + package android.media { public final class AudioFormat implements android.os.Parcelable { diff --git a/api/test-current.txt b/api/test-current.txt index a7b434ca6f2b..34c14d4e54f5 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -559,6 +559,7 @@ package android { field public static final int fillBefore = 16843196; // 0x10101bc field public static final int fillColor = 16843780; // 0x1010404 field public static final int fillEnabled = 16843343; // 0x101024f + field public static final int fillType = 16844064; // 0x1010520 field public static final int fillViewport = 16843130; // 0x101017a field public static final int filter = 16843035; // 0x101011b field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4 @@ -3442,7 +3443,7 @@ package android.app { method public android.view.View getCurrentFocus(); method public android.app.FragmentManager getFragmentManager(); method public android.content.Intent getIntent(); - method public deprecated java.lang.Object getLastNonConfigurationInstance(); + method public java.lang.Object getLastNonConfigurationInstance(); method public android.view.LayoutInflater getLayoutInflater(); method public android.app.LoaderManager getLoaderManager(); method public java.lang.String getLocalClassName(); @@ -3536,14 +3537,13 @@ package android.app { method public boolean onPreparePanel(int, android.view.View, android.view.Menu); method public void onProvideAssistContent(android.app.assist.AssistContent); method public void onProvideAssistData(android.os.Bundle); - method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public android.net.Uri onProvideReferrer(); method public void onRequestPermissionsResult(int, java.lang.String[], int[]); method protected void onRestart(); method protected void onRestoreInstanceState(android.os.Bundle); method public void onRestoreInstanceState(android.os.Bundle, android.os.PersistableBundle); method protected void onResume(); - method public deprecated java.lang.Object onRetainNonConfigurationInstance(); + method public java.lang.Object onRetainNonConfigurationInstance(); method protected void onSaveInstanceState(android.os.Bundle); method public void onSaveInstanceState(android.os.Bundle, android.os.PersistableBundle); method public boolean onSearchRequested(android.view.SearchEvent); @@ -4218,7 +4218,6 @@ package android.app { method public void onPanelClosed(int, android.view.Menu); method public boolean onPrepareOptionsMenu(android.view.Menu); method public boolean onPreparePanel(int, android.view.View, android.view.Menu); - method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public void onRestoreInstanceState(android.os.Bundle); method public android.os.Bundle onSaveInstanceState(); method public boolean onSearchRequested(android.view.SearchEvent); @@ -5856,7 +5855,6 @@ package android.app.admin { method public boolean getCrossProfileContactsSearchDisabled(android.content.ComponentName); method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName); method public int getCurrentFailedPasswordAttempts(); - method public boolean getDeviceLoggingEnabled(android.content.ComponentName); method public java.lang.String getDeviceOwnerLockScreenInfo(); method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); @@ -5905,6 +5903,7 @@ package android.app.admin { method public boolean isMasterVolumeMuted(android.content.ComponentName); method public boolean isProfileOwnerApp(java.lang.String); method public boolean isProvisioningAllowed(java.lang.String); + method public boolean isSecurityLoggingEnabled(android.content.ComponentName); method public boolean isUninstallBlocked(android.content.ComponentName, java.lang.String); method public void lockNow(); method public void reboot(android.content.ComponentName); @@ -5914,8 +5913,8 @@ package android.app.admin { method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); method public boolean requestBugreport(android.content.ComponentName); method public boolean resetPassword(java.lang.String, int); - method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrieveDeviceLogs(android.content.ComponentName); - method public java.util.List<android.auditing.SecurityLog.SecurityEvent> retrievePreviousDeviceLogs(android.content.ComponentName); + method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrievePreRebootSecurityLogs(android.content.ComponentName); + method public java.util.List<android.app.admin.SecurityLog.SecurityEvent> retrieveSecurityLogs(android.content.ComponentName); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); method public boolean setAlwaysOnVpnPackage(android.content.ComponentName, java.lang.String); method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); @@ -5927,7 +5926,6 @@ package android.app.admin { method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException; method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean); method public void setCrossProfileContactsSearchDisabled(android.content.ComponentName, boolean); - method public void setDeviceLoggingEnabled(android.content.ComponentName, boolean); method public boolean setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.String); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); @@ -5960,6 +5958,7 @@ package android.app.admin { method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName); method public void setScreenCaptureDisabled(android.content.ComponentName, boolean); method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String); + method public void setSecurityLoggingEnabled(android.content.ComponentName, boolean); method public void setShortSupportMessage(android.content.ComponentName, java.lang.String); method public boolean setStatusBarDisabled(android.content.ComponentName, boolean); method public int setStorageEncryption(android.content.ComponentName, boolean); @@ -5983,6 +5982,7 @@ package android.app.admin { field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2 field public static final int ENCRYPTION_STATUS_ACTIVE = 3; // 0x3 field public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; // 0x4 + field public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5; // 0x5 field public static final int ENCRYPTION_STATUS_INACTIVE = 1; // 0x1 field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0 field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION"; @@ -6044,6 +6044,27 @@ package android.app.admin { field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } + public class SecurityLog { + ctor public SecurityLog(); + field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452 + field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451 + field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455 + field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456 + field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457 + field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458 + field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453 + field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 + } + + public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.Object getData(); + method public int getTag(); + method public long getTimeNanos(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.app.admin.SecurityLog.SecurityEvent> CREATOR; + } + public class SystemUpdatePolicy implements android.os.Parcelable { method public static android.app.admin.SystemUpdatePolicy createAutomaticInstallPolicy(); method public static android.app.admin.SystemUpdatePolicy createPostponeInstallPolicy(); @@ -6248,6 +6269,8 @@ package android.app.job { method public long getIntervalMillis(); method public long getMaxExecutionDelayMillis(); method public long getMinLatencyMillis(); + method public static final long getMinimumFlex(); + method public static final long getMinimumPeriod(); method public int getNetworkType(); method public android.content.ComponentName getService(); method public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris(); @@ -6261,8 +6284,6 @@ package android.app.job { field public static final android.os.Parcelable.Creator<android.app.job.JobInfo> CREATOR; field public static final long DEFAULT_INITIAL_BACKOFF_MILLIS = 30000L; // 0x7530L field public static final long MAX_BACKOFF_DELAY_MILLIS = 18000000L; // 0x112a880L - field public static final long MIN_FLEX_MILLIS = 300000L; // 0x493e0L - field public static final long MIN_PERIOD_MILLIS = 3600000L; // 0x36ee80L field public static final int NETWORK_TYPE_ANY = 1; // 0x1 field public static final int NETWORK_TYPE_NONE = 0; // 0x0 field public static final int NETWORK_TYPE_UNMETERED = 2; // 0x2 @@ -6376,8 +6397,8 @@ package android.app.usage { method public long getTxPackets(); method public int getUid(); field public static final int ROAMING_ALL = -1; // 0xffffffff - field public static final int ROAMING_DEFAULT = 1; // 0x1 - field public static final int ROAMING_ROAMING = 2; // 0x2 + field public static final int ROAMING_NO = 1; // 0x1 + field public static final int ROAMING_YES = 2; // 0x2 field public static final int STATE_ALL = -1; // 0xffffffff field public static final int STATE_DEFAULT = 1; // 0x1 field public static final int STATE_FOREGROUND = 2; // 0x2 @@ -6584,31 +6605,6 @@ package android.appwidget { } -package android.auditing { - - public class SecurityLog { - ctor public SecurityLog(); - field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452 - field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451 - field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455 - field public static final int TAG_KEYGUARD_DISMISSED = 210006; // 0x33456 - field public static final int TAG_KEYGUARD_DISMISS_AUTH_ATTEMPT = 210007; // 0x33457 - field public static final int TAG_KEYGUARD_SECURED = 210008; // 0x33458 - field public static final int TAG_SYNC_RECV_FILE = 210003; // 0x33453 - field public static final int TAG_SYNC_SEND_FILE = 210004; // 0x33454 - } - - public static final class SecurityLog.SecurityEvent implements android.os.Parcelable { - method public int describeContents(); - method public java.lang.Object getData(); - method public int getTag(); - method public long getTimeNanos(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.auditing.SecurityLog.SecurityEvent> CREATOR; - } - -} - package android.bluetooth { public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile { @@ -8119,7 +8115,7 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; - field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties"; + field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler"; @@ -9462,6 +9458,7 @@ package android.content.pm { method public int getShortcutIconResId(android.content.pm.ShortcutInfo, android.os.UserHandle); method public java.util.List<android.content.pm.ShortcutInfo> getShortcutInfo(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle); method public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(android.content.pm.LauncherApps.ShortcutQuery, android.os.UserHandle); + method public boolean hasShortcutHostPermission(); method public boolean isActivityEnabled(android.content.ComponentName, android.os.UserHandle); method public boolean isPackageEnabled(java.lang.String, android.os.UserHandle); method public void pinShortcuts(java.lang.String, java.util.List<java.lang.String>, android.os.UserHandle); @@ -10125,7 +10122,6 @@ package android.content.res { method public static deprecated android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public static android.content.res.ColorStateList createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public int describeContents(); - method public int getChangingConfigurations(); method public int getColorForState(int[], int); method public int getDefaultColor(); method public boolean isOpaque(); @@ -10137,6 +10133,7 @@ package android.content.res { public abstract class ComplexColor { ctor public ComplexColor(); + method public int getChangingConfigurations(); method public abstract int getDefaultColor(); method public boolean isStateful(); } @@ -11484,17 +11481,6 @@ package android.gesture { package android.graphics { - public deprecated class AvoidXfermode extends android.graphics.Xfermode { - ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode); - } - - public static final class AvoidXfermode.Mode extends java.lang.Enum { - method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String); - method public static final android.graphics.AvoidXfermode.Mode[] values(); - enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID; - enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; - } - public final class Bitmap implements android.os.Parcelable { method public boolean compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream); method public android.graphics.Bitmap copy(android.graphics.Bitmap.Config, boolean); @@ -12361,10 +12347,6 @@ package android.graphics { field public int bytesPerPixel; } - public deprecated class PixelXorXfermode extends android.graphics.Xfermode { - ctor public PixelXorXfermode(int); - } - public class Point implements android.os.Parcelable { ctor public Point(); ctor public Point(int, int); @@ -13044,9 +13026,9 @@ package android.graphics.drawable { method public void setPaddingMode(int); method public void setPaddingRelative(int, int, int, int); method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable); + field public static final int INSET_UNDEFINED = -2147483648; // 0x80000000 field public static final int PADDING_MODE_NEST = 0; // 0x0 field public static final int PADDING_MODE_STACK = 1; // 0x1 - field public static final int UNDEFINED_INSET = -2147483648; // 0x80000000 } public class LevelListDrawable extends android.graphics.drawable.DrawableContainer { @@ -19310,7 +19292,6 @@ package android.location { method public boolean hasCarrierPhase(); method public boolean hasCarrierPhaseUncertainty(); method public boolean hasSnrInDb(); - method public boolean isPseudorangeRateCorrected(); method public void reset(); method public void resetCarrierCycles(); method public void resetCarrierFrequencyHz(); @@ -19328,7 +19309,6 @@ package android.location { method public void setCn0DbHz(double); method public void setConstellationType(int); method public void setMultipathIndicator(int); - method public void setPseudorangeRateCorrected(boolean); method public void setPseudorangeRateMetersPerSecond(double); method public void setPseudorangeRateUncertaintyMetersPerSecond(double); method public void setReceivedSvTimeNanos(long); @@ -23169,6 +23149,7 @@ package android.media.tv { method public void notifyError(int); method public void notifyRecordingStopped(android.net.Uri); method public void notifyTuned(android.net.Uri); + method public void onAppPrivateCommand(java.lang.String, android.os.Bundle); method public abstract void onRelease(); method public abstract void onStartRecording(android.net.Uri); method public abstract void onStopRecording(); @@ -23186,6 +23167,7 @@ package android.media.tv { method public void notifyTracksChanged(java.util.List<android.media.tv.TvTrackInfo>); method public void notifyVideoAvailable(); method public void notifyVideoUnavailable(int); + method public void onAppPrivateCommand(java.lang.String, android.os.Bundle); method public android.view.View onCreateOverlayView(); method public boolean onGenericMotionEvent(android.view.MotionEvent); method public boolean onKeyDown(int, android.view.KeyEvent); @@ -23217,6 +23199,7 @@ package android.media.tv { public class TvRecordingClient { ctor public TvRecordingClient(android.content.Context, java.lang.String, android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler); method public void release(); + method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle); method public void startRecording(android.net.Uri); method public void stopRecording(); method public void tune(java.lang.String, android.net.Uri); @@ -23278,6 +23261,7 @@ package android.media.tv { method public boolean onUnhandledInputEvent(android.view.InputEvent); method public void reset(); method public void selectTrack(int, java.lang.String); + method public void sendAppPrivateCommand(java.lang.String, android.os.Bundle); method public void setCallback(android.media.tv.TvView.TvInputCallback); method public void setCaptionEnabled(boolean); method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener); @@ -30831,6 +30815,7 @@ package android.provider { public static class CallLog.Calls implements android.provider.BaseColumns { ctor public CallLog.Calls(); method public static java.lang.String getLastOutgoingCall(android.content.Context); + field public static final int ANSWERED_EXTERNALLY_TYPE = 7; // 0x7 field public static final int BLOCKED_TYPE = 6; // 0x6 field public static final java.lang.String CACHED_FORMATTED_NUMBER = "formatted_number"; field public static final java.lang.String CACHED_LOOKUP_URI = "lookup_uri"; @@ -30853,6 +30838,7 @@ package android.provider { field public static final java.lang.String DURATION = "duration"; field public static final java.lang.String EXTRA_CALL_TYPE_FILTER = "android.provider.extra.CALL_TYPE_FILTER"; field public static final java.lang.String FEATURES = "features"; + field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2 field public static final int FEATURES_VIDEO = 1; // 0x1 field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location"; field public static final int INCOMING_TYPE = 1; // 0x1 @@ -32496,7 +32482,6 @@ package android.provider { field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS"; field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS"; field public static final java.lang.String ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; - field public static final java.lang.String ACTION_SCREEN_READER_TUTORIAL = "android.settings.SCREEN_READER_TUTORIAL"; field public static final java.lang.String ACTION_SEARCH_SETTINGS = "android.search.action.SEARCH_SETTINGS"; field public static final java.lang.String ACTION_SECURITY_SETTINGS = "android.settings.SECURITY_SETTINGS"; field public static final java.lang.String ACTION_SETTINGS = "android.settings.SETTINGS"; @@ -36129,9 +36114,11 @@ package android.telecom { method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.Call.Callback); method public void registerCallback(android.telecom.Call.Callback, android.os.Handler); method public void reject(boolean, java.lang.String); + method public void sendCallEvent(java.lang.String, android.os.Bundle); method public void splitFromConference(); method public void stopDtmfTone(); method public void swapConference(); @@ -36145,6 +36132,7 @@ package android.telecom { field public static final int STATE_DISCONNECTING = 10; // 0xa field public static final int STATE_HOLDING = 3; // 0x3 field public static final int STATE_NEW = 0; // 0x0 + field public static final int STATE_PULLING_CALL = 11; // 0xb field public static final int STATE_RINGING = 2; // 0x2 field public static final int STATE_SELECT_PHONE_ACCOUNT = 8; // 0x8 } @@ -36155,6 +36143,7 @@ package android.telecom { method public void onCannedTextResponsesLoaded(android.telecom.Call, java.util.List<java.lang.String>); method public void onChildrenChanged(android.telecom.Call, java.util.List<android.telecom.Call>); method public void onConferenceableCallsChanged(android.telecom.Call, java.util.List<android.telecom.Call>); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details); method public void onParentChanged(android.telecom.Call, android.telecom.Call); method public void onPostDialWait(android.telecom.Call, java.lang.String); @@ -36185,6 +36174,7 @@ package android.telecom { method public static java.lang.String propertiesToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 @@ -36204,6 +36194,7 @@ package android.telecom { field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4 field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2 field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10 + field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40 field public static final int PROPERTY_WIFI = 8; // 0x8 field public static final int PROPERTY_WORK_CALL = 32; // 0x20 } @@ -36318,15 +36309,19 @@ package android.telecom { method public void onAnswer(int); method public void onAnswer(); method public void onCallAudioStateChanged(android.telecom.CallAudioState); + method public void onCallEvent(java.lang.String, android.os.Bundle); method public void onDisconnect(); method public void onHold(); method public void onPlayDtmfTone(char); method public void onPostDialContinue(boolean); + method public void onPullExternalCall(); method public void onReject(); + method public void onReject(java.lang.String); method public void onSeparate(); method public void onStateChanged(int); method public void onStopDtmfTone(); method public void onUnhold(); + method public void sendConnectionEvent(java.lang.String, android.os.Bundle); method public final void setActive(); method public final void setAddress(android.net.Uri, int); method public final void setAudioModeIsVoip(boolean); @@ -36350,9 +36345,12 @@ package android.telecom { method public static java.lang.String stateToString(int); field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000 field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000 + field public static final int CAPABILITY_CAN_PULL_CALL = 33554432; // 0x2000000 + field public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 4194304; // 0x400000 field public static final int CAPABILITY_CAN_UPGRADE_TO_VIDEO = 524288; // 0x80000 field public static final int CAPABILITY_DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000 field public static final int CAPABILITY_HOLD = 1; // 0x1 + field public static final int CAPABILITY_IS_EXTERNAL_CALL = 16777216; // 0x1000000 field public static final int CAPABILITY_MANAGE_CONFERENCE = 128; // 0x80 field public static final int CAPABILITY_MERGE_CONFERENCE = 4; // 0x4 field public static final int CAPABILITY_MUTE = 64; // 0x40 @@ -36366,6 +36364,7 @@ package android.telecom { field public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 2048; // 0x800 field public static final int CAPABILITY_SUPPORT_HOLD = 2; // 0x2 field public static final int CAPABILITY_SWAP_CONFERENCE = 8; // 0x8 + field public static final java.lang.String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED"; field public static final java.lang.String EXTRA_CALL_SUBJECT = "android.telecom.extra.CALL_SUBJECT"; field public static final java.lang.String EXTRA_CHILD_ADDRESS = "android.telecom.extra.CHILD_ADDRESS"; field public static final java.lang.String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER"; @@ -36375,6 +36374,7 @@ package android.telecom { field public static final int STATE_HOLDING = 5; // 0x5 field public static final int STATE_INITIALIZING = 0; // 0x0 field public static final int STATE_NEW = 1; // 0x1 + field public static final int STATE_PULLING_CALL = 7; // 0x7 field public static final int STATE_RINGING = 2; // 0x2 } @@ -36452,7 +36452,9 @@ package android.telecom { method public java.lang.String getReason(); method public int getTone(); method public void writeToParcel(android.os.Parcel, int); + field public static final int ANSWERED_ELSEWHERE = 11; // 0xb field public static final int BUSY = 7; // 0x7 + field public static final int CALL_PULLED = 12; // 0xc field public static final int CANCELED = 4; // 0x4 field public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; // 0xa field public static final android.os.Parcelable.Creator<android.telecom.DisconnectCause> CREATOR; @@ -36488,6 +36490,7 @@ package android.telecom { method public void onCallAudioStateChanged(android.telecom.CallAudioState); method public void onCallRemoved(android.telecom.Call); method public void onCanAddCallChanged(boolean); + method public void onConnectionEvent(android.telecom.Call, java.lang.String, android.os.Bundle); method public void onSilenceRinger(); method public final void setAudioRoute(int); method public final void setMuted(boolean); @@ -36638,6 +36641,7 @@ package android.telecom { method public boolean isVoipAudioMode(); method public void playDtmfTone(char); method public void postDialContinue(boolean); + method public void pullExternalCall(); method public void registerCallback(android.telecom.RemoteConnection.Callback); method public void registerCallback(android.telecom.RemoteConnection.Callback, android.os.Handler); method public void reject(); @@ -36654,6 +36658,7 @@ package android.telecom { method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference); method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>); method public void onConnectionCapabilitiesChanged(android.telecom.RemoteConnection, int); + method public void onConnectionEvent(android.telecom.RemoteConnection, java.lang.String, android.os.Bundle); method public void onDestroyed(android.telecom.RemoteConnection); method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause); method public void onExtrasChanged(android.telecom.RemoteConnection, android.os.Bundle); @@ -36751,6 +36756,7 @@ package android.telecom { field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE"; field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS"; field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE"; + field public static final java.lang.String METADATA_INCLUDE_EXTERNAL_CALLS = "android.telecom.INCLUDE_EXTERNAL_CALLS"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_RINGING = "android.telecom.IN_CALL_SERVICE_RINGING"; field public static final java.lang.String METADATA_IN_CALL_SERVICE_UI = "android.telecom.IN_CALL_SERVICE_UI"; field public static final int PRESENTATION_ALLOWED = 1; // 0x1 @@ -36892,6 +36898,7 @@ package android.telephony { field public static final java.lang.String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_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_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool"; field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool"; @@ -42658,6 +42665,7 @@ package android.view { method public void onStartTemporaryDetach(); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); + method public void onVisibilityAggregated(boolean); method protected void onVisibilityChanged(android.view.View, int); method public void onWindowFocusChanged(boolean); method public void onWindowSystemUiVisibilityChanged(int); @@ -43754,7 +43762,7 @@ package android.view { method public abstract boolean onMenuOpened(int, android.view.Menu); method public abstract void onPanelClosed(int, android.view.Menu); method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu); - method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); + method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu); method public abstract boolean onSearchRequested(); method public abstract boolean onSearchRequested(android.view.SearchEvent); method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams); @@ -57417,6 +57425,7 @@ package java.util { method public void ensureCapacity(int); method public void forEach(java.util.function.Consumer<? super E>); method public E get(int); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); method public java.util.Spliterator<E> spliterator(); method public void trimToSize(); @@ -57501,6 +57510,28 @@ package java.util { method public static int hashCode(float[]); method public static int hashCode(double[]); method public static int hashCode(java.lang.Object[]); + method public static void parallelSort(byte[]); + method public static void parallelSort(byte[], int, int); + method public static void parallelSort(char[]); + method public static void parallelSort(char[], int, int); + method public static void parallelSort(short[]); + method public static void parallelSort(short[], int, int); + method public static void parallelSort(int[]); + method public static void parallelSort(int[], int, int); + method public static void parallelSort(long[]); + method public static void parallelSort(long[], int, int); + method public static void parallelSort(float[]); + method public static void parallelSort(float[], int, int); + method public static void parallelSort(double[]); + method public static void parallelSort(double[], int, int); + method public static void parallelSort(T[]); + method public static void parallelSort(T[], int, int); + method public static void parallelSort(T[], java.util.Comparator<? super T>); + method public static void parallelSort(T[], int, int, java.util.Comparator<? super T>); + method public static void setAll(T[], java.util.function.IntFunction<? extends T>); + method public static void setAll(int[], java.util.function.IntUnaryOperator); + method public static void setAll(long[], java.util.function.IntToLongFunction); + method public static void setAll(double[], java.util.function.IntToDoubleFunction); method public static void sort(int[]); method public static void sort(int[], int, int); method public static void sort(long[]); @@ -57688,6 +57719,7 @@ package java.util { method public abstract java.util.Iterator<E> iterator(); method public abstract boolean remove(java.lang.Object); method public abstract boolean removeAll(java.util.Collection<?>); + method public default boolean removeIf(java.util.function.Predicate<? super E>); method public abstract boolean retainAll(java.util.Collection<?>); method public abstract int size(); method public abstract java.lang.Object[] toArray(); @@ -58321,18 +58353,28 @@ package java.util { public abstract interface Map { method public abstract void clear(); + method public default V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public default V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public default V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public abstract boolean containsKey(java.lang.Object); method public abstract boolean containsValue(java.lang.Object); method public abstract java.util.Set<java.util.Map.Entry<K, V>> entrySet(); method public abstract boolean equals(java.lang.Object); method public default void forEach(java.util.function.BiConsumer<? super K, ? super V>); method public abstract V get(java.lang.Object); + method public default V getOrDefault(java.lang.Object, V); method public abstract int hashCode(); method public abstract boolean isEmpty(); method public abstract java.util.Set<K> keySet(); + method public default V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); method public abstract V put(K, V); method public abstract void putAll(java.util.Map<? extends K, ? extends V>); + method public default V putIfAbsent(K, V); method public abstract V remove(java.lang.Object); + method public default boolean remove(java.lang.Object, java.lang.Object); + method public default boolean replace(K, V, V); + method public default V replace(K, V); + method public default void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public abstract int size(); method public abstract java.util.Collection<V> values(); } @@ -58340,6 +58382,8 @@ package java.util { public static abstract interface Map.Entry { method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(); method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByKey(java.util.Comparator<? super K>); + method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(); + method public static java.util.Comparator<java.util.Map.Entry<K, V>> comparingByValue(java.util.Comparator<? super V>); method public abstract boolean equals(java.lang.Object); method public abstract K getKey(); method public abstract V getValue(); @@ -59070,6 +59114,7 @@ package java.util { method public synchronized void removeAllElements(); method public synchronized boolean removeElement(java.lang.Object); method public synchronized void removeElementAt(int); + method public synchronized boolean removeIf(java.util.function.Predicate<? super E>); method public synchronized void setElementAt(E, int); method public synchronized void setSize(int); method public synchronized int size(); @@ -59121,6 +59166,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -59184,6 +59230,78 @@ package java.util.concurrent { ctor public CancellationException(java.lang.String); } + public class CompletableFuture implements java.util.concurrent.CompletionStage java.util.concurrent.Future { + ctor public CompletableFuture(); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> allOf(java.util.concurrent.CompletableFuture<?>...); + method public static java.util.concurrent.CompletableFuture<java.lang.Object> anyOf(java.util.concurrent.CompletableFuture<?>...); + method public java.util.concurrent.CompletableFuture<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public java.util.concurrent.CompletableFuture<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor); + method public boolean cancel(boolean); + method public boolean complete(T); + method public boolean completeExceptionally(java.lang.Throwable); + method public static java.util.concurrent.CompletableFuture<U> completedFuture(U); + method public java.util.concurrent.CompletableFuture<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>); + method public T get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; + method public T get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; + method public T getNow(T); + method public int getNumberOfDependents(); + method public java.util.concurrent.CompletableFuture<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor); + method public boolean isCancelled(); + method public boolean isCompletedExceptionally(); + method public boolean isDone(); + method public T join(); + method public void obtrudeException(java.lang.Throwable); + method public void obtrudeValue(T); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable); + method public static java.util.concurrent.CompletableFuture<java.lang.Void> runAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>); + method public static java.util.concurrent.CompletableFuture<U> supplyAsync(java.util.function.Supplier<U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<U> thenApply(java.util.function.Function<? super T, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>); + method public java.util.concurrent.CompletableFuture<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public java.util.concurrent.CompletableFuture<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public java.util.concurrent.CompletableFuture<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRun(java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable); + method public java.util.concurrent.CompletableFuture<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public java.util.concurrent.CompletableFuture<T> toCompletableFuture(); + method public java.util.concurrent.CompletableFuture<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public java.util.concurrent.CompletableFuture<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor); + } + + public static abstract interface CompletableFuture.AsynchronousCompletionTask { + } + + public class CompletionException extends java.lang.RuntimeException { + ctor protected CompletionException(); + ctor protected CompletionException(java.lang.String); + ctor public CompletionException(java.lang.String, java.lang.Throwable); + ctor public CompletionException(java.lang.Throwable); + } + public abstract interface CompletionService { method public abstract java.util.concurrent.Future<V> poll(); method public abstract java.util.concurrent.Future<V> poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; @@ -59192,20 +59310,130 @@ package java.util.concurrent { method public abstract java.util.concurrent.Future<V> take() throws java.lang.InterruptedException; } + public abstract interface CompletionStage { + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> acceptEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> applyToEither(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>); + method public abstract java.util.concurrent.CompletionStage<U> applyToEitherAsync(java.util.concurrent.CompletionStage<? extends T>, java.util.function.Function<? super T, U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<T> exceptionally(java.util.function.Function<java.lang.Throwable, ? extends T>); + method public abstract java.util.concurrent.CompletionStage<U> handle(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> handleAsync(java.util.function.BiFunction<? super T, java.lang.Throwable, ? extends U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBoth(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterBothAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEither(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> runAfterEitherAsync(java.util.concurrent.CompletionStage<?>, java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAccept(java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptAsync(java.util.function.Consumer<? super T>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBoth(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenAcceptBothAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiConsumer<? super T, ? super U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> thenApply(java.util.function.Function<? super T, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>); + method public abstract java.util.concurrent.CompletionStage<U> thenApplyAsync(java.util.function.Function<? super T, ? extends U>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<V> thenCombine(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>); + method public abstract java.util.concurrent.CompletionStage<V> thenCombineAsync(java.util.concurrent.CompletionStage<? extends U>, java.util.function.BiFunction<? super T, ? super U, ? extends V>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<U> thenCompose(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>); + method public abstract java.util.concurrent.CompletionStage<U> thenComposeAsync(java.util.function.Function<? super T, ? extends java.util.concurrent.CompletionStage<U>>, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRun(java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable); + method public abstract java.util.concurrent.CompletionStage<java.lang.Void> thenRunAsync(java.lang.Runnable, java.util.concurrent.Executor); + method public abstract java.util.concurrent.CompletableFuture<T> toCompletableFuture(); + method public abstract java.util.concurrent.CompletionStage<T> whenComplete(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>); + method public abstract java.util.concurrent.CompletionStage<T> whenCompleteAsync(java.util.function.BiConsumer<? super T, ? super java.lang.Throwable>, java.util.concurrent.Executor); + } + public class ConcurrentHashMap extends java.util.AbstractMap implements java.util.concurrent.ConcurrentMap java.io.Serializable { ctor public ConcurrentHashMap(); ctor public ConcurrentHashMap(int); ctor public ConcurrentHashMap(java.util.Map<? extends K, ? extends V>); ctor public ConcurrentHashMap(int, float); ctor public ConcurrentHashMap(int, float, int); + method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public boolean contains(java.lang.Object); method public java.util.Enumeration<V> elements(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); + method public void forEach(long, java.util.function.BiConsumer<? super K, ? super V>); + method public void forEach(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachEntry(long, java.util.function.Consumer<? super java.util.Map.Entry<K, V>>); + method public void forEachEntry(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachKey(long, java.util.function.Consumer<? super K>); + method public void forEachKey(long, java.util.function.Function<? super K, ? extends U>, java.util.function.Consumer<? super U>); + method public void forEachValue(long, java.util.function.Consumer<? super V>); + method public void forEachValue(long, java.util.function.Function<? super V, ? extends U>, java.util.function.Consumer<? super U>); + method public V getOrDefault(java.lang.Object, V); + method public java.util.concurrent.ConcurrentHashMap.KeySetView<K, V> keySet(V); method public java.util.Enumeration<K> keys(); + method public long mappingCount(); + method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); + method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(); + method public static java.util.concurrent.ConcurrentHashMap.KeySetView<K, java.lang.Boolean> newKeySet(int); method public V putIfAbsent(K, V); + method public U reduce(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public java.util.Map.Entry<K, V> reduceEntries(long, java.util.function.BiFunction<java.util.Map.Entry<K, V>, java.util.Map.Entry<K, V>, ? extends java.util.Map.Entry<K, V>>); + method public U reduceEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceEntriesToDouble(long, java.util.function.ToDoubleFunction<java.util.Map.Entry<K, V>>, double, java.util.function.DoubleBinaryOperator); + method public int reduceEntriesToInt(long, java.util.function.ToIntFunction<java.util.Map.Entry<K, V>>, int, java.util.function.IntBinaryOperator); + method public long reduceEntriesToLong(long, java.util.function.ToLongFunction<java.util.Map.Entry<K, V>>, long, java.util.function.LongBinaryOperator); + method public K reduceKeys(long, java.util.function.BiFunction<? super K, ? super K, ? extends K>); + method public U reduceKeys(long, java.util.function.Function<? super K, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceKeysToDouble(long, java.util.function.ToDoubleFunction<? super K>, double, java.util.function.DoubleBinaryOperator); + method public int reduceKeysToInt(long, java.util.function.ToIntFunction<? super K>, int, java.util.function.IntBinaryOperator); + method public long reduceKeysToLong(long, java.util.function.ToLongFunction<? super K>, long, java.util.function.LongBinaryOperator); + method public double reduceToDouble(long, java.util.function.ToDoubleBiFunction<? super K, ? super V>, double, java.util.function.DoubleBinaryOperator); + method public int reduceToInt(long, java.util.function.ToIntBiFunction<? super K, ? super V>, int, java.util.function.IntBinaryOperator); + method public long reduceToLong(long, java.util.function.ToLongBiFunction<? super K, ? super V>, long, java.util.function.LongBinaryOperator); + method public V reduceValues(long, java.util.function.BiFunction<? super V, ? super V, ? extends V>); + method public U reduceValues(long, java.util.function.Function<? super V, ? extends U>, java.util.function.BiFunction<? super U, ? super U, ? extends U>); + method public double reduceValuesToDouble(long, java.util.function.ToDoubleFunction<? super V>, double, java.util.function.DoubleBinaryOperator); + method public int reduceValuesToInt(long, java.util.function.ToIntFunction<? super V>, int, java.util.function.IntBinaryOperator); + method public long reduceValuesToLong(long, java.util.function.ToLongFunction<? super V>, long, java.util.function.LongBinaryOperator); method public boolean remove(java.lang.Object, java.lang.Object); method public boolean replace(K, V, V); method public V replace(K, V); + method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public U search(long, java.util.function.BiFunction<? super K, ? super V, ? extends U>); + method public U searchEntries(long, java.util.function.Function<java.util.Map.Entry<K, V>, ? extends U>); + method public U searchKeys(long, java.util.function.Function<? super K, ? extends U>); + method public U searchValues(long, java.util.function.Function<? super V, ? extends U>); + } + + static abstract class ConcurrentHashMap.CollectionView implements java.util.Collection java.io.Serializable { + method public final void clear(); + method public abstract boolean contains(java.lang.Object); + method public final boolean containsAll(java.util.Collection<?>); + method public java.util.concurrent.ConcurrentHashMap<K, V> getMap(); + method public final boolean isEmpty(); + method public abstract java.util.Iterator<E> iterator(); + method public abstract boolean remove(java.lang.Object); + method public final boolean removeAll(java.util.Collection<?>); + method public final boolean retainAll(java.util.Collection<?>); + method public final int size(); + method public final java.lang.Object[] toArray(); + method public final T[] toArray(T[]); + method public final java.lang.String toString(); + } + + public static class ConcurrentHashMap.KeySetView extends java.util.concurrent.ConcurrentHashMap.CollectionView implements java.io.Serializable java.util.Set { + method public boolean add(K); + method public boolean addAll(java.util.Collection<? extends K>); + method public boolean contains(java.lang.Object); + method public void forEach(java.util.function.Consumer<? super K>); + method public V getMappedValue(); + method public java.util.Iterator<K> iterator(); + method public boolean remove(java.lang.Object); + method public java.util.Spliterator<K> spliterator(); } public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable { @@ -59235,6 +59463,7 @@ package java.util.concurrent { method public E removeLast(); method public boolean removeLastOccurrence(java.lang.Object); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable { @@ -59245,6 +59474,7 @@ package java.util.concurrent { method public E peek(); method public E poll(); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public abstract interface ConcurrentMap implements java.util.Map { @@ -59276,6 +59506,9 @@ package java.util.concurrent { method public K ceilingKey(K); method public java.util.concurrent.ConcurrentSkipListMap<K, V> clone(); method public java.util.Comparator<? super K> comparator(); + method public V compute(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); + method public V computeIfAbsent(K, java.util.function.Function<? super K, ? extends V>); + method public V computeIfPresent(K, java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public java.util.NavigableSet<K> descendingKeySet(); method public java.util.concurrent.ConcurrentNavigableMap<K, V> descendingMap(); method public java.util.Set<java.util.Map.Entry<K, V>> entrySet(); @@ -59283,6 +59516,8 @@ package java.util.concurrent { method public K firstKey(); method public java.util.Map.Entry<K, V> floorEntry(K); method public K floorKey(K); + method public void forEach(java.util.function.BiConsumer<? super K, ? super V>); + method public V getOrDefault(java.lang.Object, V); method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K, boolean); method public java.util.concurrent.ConcurrentNavigableMap<K, V> headMap(K); method public java.util.Map.Entry<K, V> higherEntry(K); @@ -59291,6 +59526,7 @@ package java.util.concurrent { method public K lastKey(); method public java.util.Map.Entry<K, V> lowerEntry(K); method public K lowerKey(K); + method public V merge(K, V, java.util.function.BiFunction<? super V, ? super V, ? extends V>); method public java.util.NavigableSet<K> navigableKeySet(); method public java.util.Map.Entry<K, V> pollFirstEntry(); method public java.util.Map.Entry<K, V> pollLastEntry(); @@ -59298,6 +59534,7 @@ package java.util.concurrent { method public boolean remove(java.lang.Object, java.lang.Object); method public boolean replace(K, V, V); method public V replace(K, V); + method public void replaceAll(java.util.function.BiFunction<? super K, ? super V, ? extends V>); method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, boolean, K, boolean); method public java.util.concurrent.ConcurrentNavigableMap<K, V> subMap(K, K); method public java.util.concurrent.ConcurrentNavigableMap<K, V> tailMap(K, boolean); @@ -59325,6 +59562,7 @@ package java.util.concurrent { method public E pollFirst(); method public E pollLast(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public java.util.NavigableSet<E> subSet(E, boolean, E, boolean); method public java.util.NavigableSet<E> subSet(E, E); method public java.util.NavigableSet<E> tailSet(E, boolean); @@ -59368,8 +59606,11 @@ package java.util.concurrent { public class CopyOnWriteArraySet extends java.util.AbstractSet implements java.io.Serializable { ctor public CopyOnWriteArraySet(); ctor public CopyOnWriteArraySet(java.util.Collection<? extends E>); + method public void forEach(java.util.function.Consumer<? super E>); method public java.util.Iterator<E> iterator(); + method public boolean removeIf(java.util.function.Predicate<? super E>); method public int size(); + method public java.util.Spliterator<E> spliterator(); } public class CountDownLatch { @@ -59380,6 +59621,32 @@ package java.util.concurrent { method public long getCount(); } + public abstract class CountedCompleter extends java.util.concurrent.ForkJoinTask { + ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>, int); + ctor protected CountedCompleter(java.util.concurrent.CountedCompleter<?>); + ctor protected CountedCompleter(); + method public final void addToPendingCount(int); + method public final boolean compareAndSetPendingCount(int, int); + method public void complete(T); + method public abstract void compute(); + method public final int decrementPendingCountUnlessZero(); + method protected final boolean exec(); + method public final java.util.concurrent.CountedCompleter<?> firstComplete(); + method public final java.util.concurrent.CountedCompleter<?> getCompleter(); + method public final int getPendingCount(); + method public T getRawResult(); + method public final java.util.concurrent.CountedCompleter<?> getRoot(); + method public final void helpComplete(int); + method public final java.util.concurrent.CountedCompleter<?> nextComplete(); + method public void onCompletion(java.util.concurrent.CountedCompleter<?>); + method public boolean onExceptionalCompletion(java.lang.Throwable, java.util.concurrent.CountedCompleter<?>); + method public final void propagateCompletion(); + method public final void quietlyCompleteRoot(); + method public final void setPendingCount(int); + method protected void setRawResult(T); + method public final void tryComplete(); + } + public class CyclicBarrier { ctor public CyclicBarrier(int, java.lang.Runnable); ctor public CyclicBarrier(int); @@ -59470,6 +59737,8 @@ package java.util.concurrent { method public static java.util.concurrent.ExecutorService newSingleThreadExecutor(java.util.concurrent.ThreadFactory); method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(); method public static java.util.concurrent.ScheduledExecutorService newSingleThreadScheduledExecutor(java.util.concurrent.ThreadFactory); + method public static java.util.concurrent.ExecutorService newWorkStealingPool(int); + method public static java.util.concurrent.ExecutorService newWorkStealingPool(); method public static java.util.concurrent.Callable<T> privilegedCallable(java.util.concurrent.Callable<T>); method public static java.util.concurrent.Callable<T> privilegedCallableUsingCurrentClassLoader(java.util.concurrent.Callable<T>); method public static java.util.concurrent.ThreadFactory privilegedThreadFactory(); @@ -59483,11 +59752,13 @@ package java.util.concurrent { ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean); method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit); method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public static java.util.concurrent.ForkJoinPool commonPool(); method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>); method public void execute(java.util.concurrent.ForkJoinTask<?>); method public void execute(java.lang.Runnable); method public int getActiveThreadCount(); method public boolean getAsyncMode(); + method public static int getCommonPoolParallelism(); method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory(); method public int getParallelism(); method public int getPoolSize(); @@ -59525,6 +59796,7 @@ package java.util.concurrent { method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T); method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>); method public boolean cancel(boolean); + method public final boolean compareAndSetForkJoinTaskTag(short, short); method public void complete(V); method public void completeExceptionally(java.lang.Throwable); method protected abstract boolean exec(); @@ -59532,6 +59804,7 @@ package java.util.concurrent { method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException; method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException; method public final java.lang.Throwable getException(); + method public final short getForkJoinTaskTag(); method public static java.util.concurrent.ForkJoinPool getPool(); method public static int getQueuedTaskCount(); method public abstract V getRawResult(); @@ -59550,9 +59823,11 @@ package java.util.concurrent { method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask(); method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask(); method protected static java.util.concurrent.ForkJoinTask<?> pollTask(); + method public final void quietlyComplete(); method public final void quietlyInvoke(); method public final void quietlyJoin(); method public void reinitialize(); + method public final short setForkJoinTaskTag(short); method protected abstract void setRawResult(V); method public boolean tryUnfork(); } @@ -59626,6 +59901,7 @@ package java.util.concurrent { method public E removeLast(); method public boolean removeLastOccurrence(java.lang.Object); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; method public E takeFirst() throws java.lang.InterruptedException; method public E takeLast() throws java.lang.InterruptedException; @@ -59646,6 +59922,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -59665,6 +59942,7 @@ package java.util.concurrent { method public void put(E); method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; method public void transfer(E) throws java.lang.InterruptedException; method public boolean tryTransfer(E); @@ -59712,6 +59990,7 @@ package java.util.concurrent { method public void put(E); method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -59815,6 +60094,7 @@ package java.util.concurrent { method public void put(E) throws java.lang.InterruptedException; method public int remainingCapacity(); method public int size(); + method public java.util.Spliterator<E> spliterator(); method public E take() throws java.lang.InterruptedException; } @@ -59944,112 +60224,136 @@ package java.util.concurrent.atomic { public class AtomicInteger extends java.lang.Number implements java.io.Serializable { ctor public AtomicInteger(int); ctor public AtomicInteger(); + method public final int accumulateAndGet(int, java.util.function.IntBinaryOperator); method public final int addAndGet(int); method public final boolean compareAndSet(int, int); method public final int decrementAndGet(); method public double doubleValue(); method public float floatValue(); method public final int get(); + method public final int getAndAccumulate(int, java.util.function.IntBinaryOperator); method public final int getAndAdd(int); method public final int getAndDecrement(); method public final int getAndIncrement(); method public final int getAndSet(int); + method public final int getAndUpdate(java.util.function.IntUnaryOperator); method public final int incrementAndGet(); method public int intValue(); method public final void lazySet(int); method public long longValue(); method public final void set(int); + method public final int updateAndGet(java.util.function.IntUnaryOperator); method public final boolean weakCompareAndSet(int, int); } public class AtomicIntegerArray implements java.io.Serializable { ctor public AtomicIntegerArray(int); ctor public AtomicIntegerArray(int[]); + method public final int accumulateAndGet(int, int, java.util.function.IntBinaryOperator); method public final int addAndGet(int, int); method public final boolean compareAndSet(int, int, int); method public final int decrementAndGet(int); method public final int get(int); + method public final int getAndAccumulate(int, int, java.util.function.IntBinaryOperator); method public final int getAndAdd(int, int); method public final int getAndDecrement(int); method public final int getAndIncrement(int); method public final int getAndSet(int, int); + method public final int getAndUpdate(int, java.util.function.IntUnaryOperator); method public final int incrementAndGet(int); method public final void lazySet(int, int); method public final int length(); method public final void set(int, int); + method public final int updateAndGet(int, java.util.function.IntUnaryOperator); method public final boolean weakCompareAndSet(int, int, int); } public abstract class AtomicIntegerFieldUpdater { ctor protected AtomicIntegerFieldUpdater(); + method public final int accumulateAndGet(T, int, java.util.function.IntBinaryOperator); method public int addAndGet(T, int); method public abstract boolean compareAndSet(T, int, int); method public int decrementAndGet(T); method public abstract int get(T); + method public final int getAndAccumulate(T, int, java.util.function.IntBinaryOperator); method public int getAndAdd(T, int); method public int getAndDecrement(T); method public int getAndIncrement(T); method public int getAndSet(T, int); + method public final int getAndUpdate(T, java.util.function.IntUnaryOperator); method public int incrementAndGet(T); method public abstract void lazySet(T, int); method public static java.util.concurrent.atomic.AtomicIntegerFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String); method public abstract void set(T, int); + method public final int updateAndGet(T, java.util.function.IntUnaryOperator); method public abstract boolean weakCompareAndSet(T, int, int); } public class AtomicLong extends java.lang.Number implements java.io.Serializable { ctor public AtomicLong(long); ctor public AtomicLong(); + method public final long accumulateAndGet(long, java.util.function.LongBinaryOperator); method public final long addAndGet(long); method public final boolean compareAndSet(long, long); method public final long decrementAndGet(); method public double doubleValue(); method public float floatValue(); method public final long get(); + method public final long getAndAccumulate(long, java.util.function.LongBinaryOperator); method public final long getAndAdd(long); method public final long getAndDecrement(); method public final long getAndIncrement(); method public final long getAndSet(long); + method public final long getAndUpdate(java.util.function.LongUnaryOperator); method public final long incrementAndGet(); method public int intValue(); method public final void lazySet(long); method public long longValue(); method public final void set(long); + method public final long updateAndGet(java.util.function.LongUnaryOperator); method public final boolean weakCompareAndSet(long, long); } public class AtomicLongArray implements java.io.Serializable { ctor public AtomicLongArray(int); ctor public AtomicLongArray(long[]); + method public final long accumulateAndGet(int, long, java.util.function.LongBinaryOperator); method public long addAndGet(int, long); method public final boolean compareAndSet(int, long, long); method public final long decrementAndGet(int); method public final long get(int); + method public final long getAndAccumulate(int, long, java.util.function.LongBinaryOperator); method public final long getAndAdd(int, long); method public final long getAndDecrement(int); method public final long getAndIncrement(int); method public final long getAndSet(int, long); + method public final long getAndUpdate(int, java.util.function.LongUnaryOperator); method public final long incrementAndGet(int); method public final void lazySet(int, long); method public final int length(); method public final void set(int, long); + method public final long updateAndGet(int, java.util.function.LongUnaryOperator); method public final boolean weakCompareAndSet(int, long, long); } public abstract class AtomicLongFieldUpdater { ctor protected AtomicLongFieldUpdater(); + method public final long accumulateAndGet(T, long, java.util.function.LongBinaryOperator); method public long addAndGet(T, long); method public abstract boolean compareAndSet(T, long, long); method public long decrementAndGet(T); method public abstract long get(T); + method public final long getAndAccumulate(T, long, java.util.function.LongBinaryOperator); method public long getAndAdd(T, long); method public long getAndDecrement(T); method public long getAndIncrement(T); method public long getAndSet(T, long); + method public final long getAndUpdate(T, java.util.function.LongUnaryOperator); method public long incrementAndGet(T); method public abstract void lazySet(T, long); method public static java.util.concurrent.atomic.AtomicLongFieldUpdater<U> newUpdater(java.lang.Class<U>, java.lang.String); method public abstract void set(T, long); + method public final long updateAndGet(T, java.util.function.LongUnaryOperator); method public abstract boolean weakCompareAndSet(T, long, long); } @@ -60067,34 +60371,46 @@ package java.util.concurrent.atomic { public class AtomicReference implements java.io.Serializable { ctor public AtomicReference(V); ctor public AtomicReference(); + method public final V accumulateAndGet(V, java.util.function.BinaryOperator<V>); method public final boolean compareAndSet(V, V); method public final V get(); + method public final V getAndAccumulate(V, java.util.function.BinaryOperator<V>); method public final V getAndSet(V); + method public final V getAndUpdate(java.util.function.UnaryOperator<V>); method public final void lazySet(V); method public final void set(V); + method public final V updateAndGet(java.util.function.UnaryOperator<V>); method public final boolean weakCompareAndSet(V, V); } public class AtomicReferenceArray implements java.io.Serializable { ctor public AtomicReferenceArray(int); ctor public AtomicReferenceArray(E[]); + method public final E accumulateAndGet(int, E, java.util.function.BinaryOperator<E>); method public final boolean compareAndSet(int, E, E); method public final E get(int); + method public final E getAndAccumulate(int, E, java.util.function.BinaryOperator<E>); method public final E getAndSet(int, E); + method public final E getAndUpdate(int, java.util.function.UnaryOperator<E>); method public final void lazySet(int, E); method public final int length(); method public final void set(int, E); + method public final E updateAndGet(int, java.util.function.UnaryOperator<E>); method public final boolean weakCompareAndSet(int, E, E); } public abstract class AtomicReferenceFieldUpdater { ctor protected AtomicReferenceFieldUpdater(); + method public final V accumulateAndGet(T, V, java.util.function.BinaryOperator<V>); method public abstract boolean compareAndSet(T, V, V); method public abstract V get(T); + method public final V getAndAccumulate(T, V, java.util.function.BinaryOperator<V>); method public V getAndSet(T, V); + method public final V getAndUpdate(T, java.util.function.UnaryOperator<V>); method public abstract void lazySet(T, V); method public static java.util.concurrent.atomic.AtomicReferenceFieldUpdater<U, W> newUpdater(java.lang.Class<U>, java.lang.Class<W>, java.lang.String); method public abstract void set(T, V); + method public final V updateAndGet(T, java.util.function.UnaryOperator<V>); method public abstract boolean weakCompareAndSet(T, V, V); } @@ -60109,6 +60425,59 @@ package java.util.concurrent.atomic { method public boolean weakCompareAndSet(V, V, int, int); } + public class DoubleAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public DoubleAccumulator(java.util.function.DoubleBinaryOperator, double); + method public void accumulate(double); + method public double doubleValue(); + method public float floatValue(); + method public double get(); + method public double getThenReset(); + method public int intValue(); + method public long longValue(); + method public void reset(); + } + + public class DoubleAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public DoubleAdder(); + method public void add(double); + method public double doubleValue(); + method public float floatValue(); + method public int intValue(); + method public long longValue(); + method public void reset(); + method public double sum(); + method public double sumThenReset(); + } + + public class LongAccumulator extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public LongAccumulator(java.util.function.LongBinaryOperator, long); + method public void accumulate(long); + method public double doubleValue(); + method public float floatValue(); + method public long get(); + method public long getThenReset(); + method public int intValue(); + method public long longValue(); + method public void reset(); + } + + public class LongAdder extends java.util.concurrent.atomic.Striped64 implements java.io.Serializable { + ctor public LongAdder(); + method public void add(long); + method public void decrement(); + method public double doubleValue(); + method public float floatValue(); + method public void increment(); + method public int intValue(); + method public long longValue(); + method public void reset(); + method public long sum(); + method public long sumThenReset(); + } + + abstract class Striped64 extends java.lang.Number { + } + } package java.util.concurrent.locks { @@ -60316,6 +60685,34 @@ package java.util.concurrent.locks { method public void unlock(); } + public class StampedLock implements java.io.Serializable { + ctor public StampedLock(); + method public java.util.concurrent.locks.Lock asReadLock(); + method public java.util.concurrent.locks.ReadWriteLock asReadWriteLock(); + method public java.util.concurrent.locks.Lock asWriteLock(); + method public int getReadLockCount(); + method public boolean isReadLocked(); + method public boolean isWriteLocked(); + method public long readLock(); + method public long readLockInterruptibly() throws java.lang.InterruptedException; + method public long tryConvertToOptimisticRead(long); + method public long tryConvertToReadLock(long); + method public long tryConvertToWriteLock(long); + method public long tryOptimisticRead(); + method public long tryReadLock(); + method public long tryReadLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public boolean tryUnlockRead(); + method public boolean tryUnlockWrite(); + method public long tryWriteLock(); + method public long tryWriteLock(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException; + method public void unlock(long); + method public void unlockRead(long); + method public void unlockWrite(long); + method public boolean validate(long); + method public long writeLock(); + method public long writeLockInterruptibly() throws java.lang.InterruptedException; + } + } package java.util.function { diff --git a/api/test-removed.txt b/api/test-removed.txt index 2f553734068a..8ac2d63d99a2 100644 --- a/api/test-removed.txt +++ b/api/test-removed.txt @@ -35,6 +35,25 @@ package android.database { } +package android.graphics { + + public deprecated class AvoidXfermode extends android.graphics.Xfermode { + ctor public AvoidXfermode(int, int, android.graphics.AvoidXfermode.Mode); + } + + public static final class AvoidXfermode.Mode extends java.lang.Enum { + method public static android.graphics.AvoidXfermode.Mode valueOf(java.lang.String); + method public static final android.graphics.AvoidXfermode.Mode[] values(); + enum_constant public static final android.graphics.AvoidXfermode.Mode AVOID; + enum_constant public static final android.graphics.AvoidXfermode.Mode TARGET; + } + + public deprecated class PixelXorXfermode extends android.graphics.Xfermode { + ctor public PixelXorXfermode(int); + } + +} + package android.media { public final class AudioFormat implements android.os.Parcelable { diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp index 8bcbf51cc857..7590325982f5 100644 --- a/cmds/app_process/app_main.cpp +++ b/cmds/app_process/app_main.cpp @@ -305,7 +305,7 @@ int main(int argc, char* const argv[]) } if (zygote) { - PreloadPublicNativeLibraries(); + InitializeNativeLoader(); runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java index 844063c04e83..8e31d323009f 100644 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java @@ -16,6 +16,7 @@ package android.animation; +import android.content.pm.ActivityInfo.Config; import android.content.res.ConstantState; import java.util.ArrayList; @@ -50,7 +51,7 @@ public abstract class Animator implements Cloneable { * A set of flags which identify the type of configuration changes that can affect this * Animator. Used by the Animator cache. */ - int mChangingConfigurations = 0; + @Config int mChangingConfigurations = 0; /** * If this animator is inflated from a constant state, keep a reference to it so that @@ -344,7 +345,7 @@ public abstract class Animator implements Cloneable { * @see android.content.pm.ActivityInfo * @hide */ - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations; } @@ -358,7 +359,7 @@ public abstract class Animator implements Cloneable { * @see android.content.pm.ActivityInfo * @hide */ - public void setChangingConfigurations(int configs) { + public void setChangingConfigurations(@Config int configs) { mChangingConfigurations = configs; } @@ -368,7 +369,7 @@ public abstract class Animator implements Cloneable { * This method is called while loading the animator. * @hide */ - public void appendChangingConfigurations(int configs) { + public void appendChangingConfigurations(@Config int configs) { mChangingConfigurations |= configs; } @@ -564,7 +565,7 @@ public abstract class Animator implements Cloneable { private static class AnimatorConstantState extends ConstantState<Animator> { final Animator mAnimator; - int mChangingConf; + @Config int mChangingConf; public AnimatorConstantState(Animator animator) { mAnimator = animator; @@ -574,7 +575,7 @@ public abstract class Animator implements Cloneable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConf; } diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java index 8d03b551a347..7d5931fc1cc2 100644 --- a/core/java/android/animation/AnimatorInflater.java +++ b/core/java/android/animation/AnimatorInflater.java @@ -16,7 +16,10 @@ package android.animation; import android.annotation.AnimatorRes; +import android.annotation.AnyRes; +import android.annotation.NonNull; import android.content.Context; +import android.content.pm.ActivityInfo.Config; import android.content.res.ConfigurationBoundResourceCache; import android.content.res.ConstantState; import android.content.res.Resources; @@ -1062,7 +1065,7 @@ public class AnimatorInflater { return anim; } - private static int getChangingConfigs(Resources resources, int id) { + private static @Config int getChangingConfigs(@NonNull Resources resources, @AnyRes int id) { synchronized (sTmpTypedValue) { resources.getValue(id, sTmpTypedValue, true); return sTmpTypedValue.changingConfigurations; diff --git a/core/java/android/animation/StateListAnimator.java b/core/java/android/animation/StateListAnimator.java index d49e914cf5cc..b6d6910c1dc8 100644 --- a/core/java/android/animation/StateListAnimator.java +++ b/core/java/android/animation/StateListAnimator.java @@ -16,6 +16,7 @@ package android.animation; +import android.content.pm.ActivityInfo.Config; import android.content.res.ConstantState; import android.util.StateSet; import android.view.View; @@ -53,7 +54,7 @@ public class StateListAnimator implements Cloneable { private WeakReference<View> mViewRef; private StateListAnimatorConstantState mConstantState; private AnimatorListenerAdapter mAnimatorListener; - private int mChangingConfigurations; + private @Config int mChangingConfigurations; public StateListAnimator() { initAnimatorListener(); @@ -223,7 +224,7 @@ public class StateListAnimator implements Cloneable { * @see android.content.pm.ActivityInfo * @hide */ - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations; } @@ -237,7 +238,7 @@ public class StateListAnimator implements Cloneable { * @see android.content.pm.ActivityInfo * @hide */ - public void setChangingConfigurations(int configs) { + public void setChangingConfigurations(@Config int configs) { mChangingConfigurations = configs; } @@ -247,7 +248,7 @@ public class StateListAnimator implements Cloneable { * This method is called while loading the animator. * @hide */ - public void appendChangingConfigurations(int configs) { + public void appendChangingConfigurations(@Config int configs) { mChangingConfigurations |= configs; } @@ -309,7 +310,7 @@ public class StateListAnimator implements Cloneable { final StateListAnimator mAnimator; - int mChangingConf; + @Config int mChangingConf; public StateListAnimatorConstantState(StateListAnimator animator) { mAnimator = animator; @@ -318,7 +319,7 @@ public class StateListAnimator implements Cloneable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConf; } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 6b67b959064e..cc1d68e88b6f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -744,7 +744,7 @@ public class Activity extends ContextThemeWrapper Activity mParent; boolean mCalled; /*package*/ boolean mResumed; - private boolean mStopped; + /*package*/ boolean mStopped; boolean mFinished; boolean mStartedActivity; private boolean mDestroyed; @@ -1976,15 +1976,13 @@ public class Activity extends ContextThemeWrapper * normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this * function returns null. * - * @return Returns the object previously returned by - * {@link #onRetainNonConfigurationInstance()}. - * - * @deprecated Use the new {@link Fragment} API + * <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API * {@link Fragment#setRetainInstance(boolean)} instead; this is also - * available on older platforms through the Android compatibility package. + * available on older platforms through the Android support libraries. + * + * @return the object previously returned by {@link #onRetainNonConfigurationInstance()} */ @Nullable - @Deprecated public Object getLastNonConfigurationInstance() { return mLastNonConfigurationInstances != null ? mLastNonConfigurationInstances.activity : null; @@ -2035,12 +2033,12 @@ public class Activity extends ContextThemeWrapper * guarantee for {@link android.os.AsyncTask#doInBackground} since that is * running in a separate thread.) * - * @return Return any Object holding the desired state to propagate to the - * next activity instance. - * - * @deprecated Use the new {@link Fragment} API + * <p><strong>Note:</strong> For most cases you should use the {@link Fragment} API * {@link Fragment#setRetainInstance(boolean)} instead; this is also - * available on older platforms through the Android compatibility package. + * available on older platforms through the Android support libraries. + * + * @return any Object holding the desired state to propagate to the + * next activity instance */ public Object onRetainNonConfigurationInstance() { return null; diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 8b62ef9d568f..811a05bac077 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2307,7 +2307,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case KEYGUARD_GOING_AWAY_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); - keyguardGoingAway(data.readInt() != 0, data.readInt() != 0); + keyguardGoingAway(data.readInt()); reply.writeNoException(); return true; } @@ -5924,13 +5924,12 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } - public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) throws RemoteException { + public void keyguardGoingAway(int flags) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); - data.writeInt(disableWindowAnimations ? 1 : 0); - data.writeInt(keyguardGoingToNotificationShade ? 1 : 0); + data.writeInt(flags); mRemote.transact(KEYGUARD_GOING_AWAY_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 094950bfb3fd..a6e7d67f1dd3 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -710,6 +710,10 @@ public class ActivityOptions { /** @hide */ public ActivityOptions(Bundle opts) { + // If the remote side sent us bad parcelables, they won't get the + // results they want, which is their loss. + opts.setDefusable(true); + mPackageName = opts.getString(KEY_PACKAGE_NAME); try { mUsageTimeReport = opts.getParcelable(KEY_USAGE_TIME_REPORT); @@ -777,15 +781,16 @@ public class ActivityOptions { /** * Sets the bounds (window size) that the activity should be launched in. + * Rect position should be provided in pixels and in screen coordinates. * Set to null explicitly for fullscreen. * <p> * <strong>NOTE:<strong/> This value is ignored on devices that don't have * {@link android.content.pm.PackageManager#FEATURE_FREEFORM_WINDOW_MANAGEMENT} or * {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled. - * @param launchBounds Launch bounds to use for the activity or null for fullscreen. + * @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen. */ - public ActivityOptions setLaunchBounds(@Nullable Rect launchBounds) { - mLaunchBounds = launchBounds != null ? new Rect(launchBounds) : null; + public ActivityOptions setLaunchBounds(@Nullable Rect screenSpacePixelRect) { + mLaunchBounds = screenSpacePixelRect != null ? new Rect(screenSpacePixelRect) : null; return this; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 060ac5e578e4..93c668d10f15 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -379,6 +379,33 @@ public final class ActivityThread { ? "no component name" : componentName.toShortString()) + "}"; } + + public String getStateString() { + StringBuilder sb = new StringBuilder(); + sb.append("ActivityClientRecord{"); + sb.append("paused=").append(paused); + sb.append(", stopped=").append(stopped); + sb.append(", hideForNow=").append(hideForNow); + sb.append(", startsNotResumed=").append(startsNotResumed); + sb.append(", isForward=").append(isForward); + sb.append(", pendingConfigChanges=").append(pendingConfigChanges); + sb.append(", onlyLocalRequest=").append(onlyLocalRequest); + sb.append(", preserveWindow=").append(mPreserveWindow); + if (activity != null) { + sb.append(", Activity{"); + sb.append("resumed=").append(activity.mResumed); + sb.append(", stopped=").append(activity.mStopped); + sb.append(", finished=").append(activity.isFinishing()); + sb.append(", destroyed=").append(activity.isDestroyed()); + sb.append(", startedActivity=").append(activity.mStartedActivity); + sb.append(", temporaryPause=").append(activity.mTemporaryPause); + sb.append(", changingConfigurations=").append(activity.mChangingConfigurations); + sb.append(", visibleBehind=").append(activity.mVisibleBehind); + sb.append("}"); + } + sb.append("}"); + return sb.toString(); + } } final class ProviderClientRecord { @@ -3752,9 +3779,10 @@ public final class ActivityThread { return; } RuntimeException e = new RuntimeException( - "Performing stop of activity that is not resumed: " + "Performing stop of activity that is already stopped: " + r.intent.getComponent().toShortString()); Slog.e(TAG, e.getMessage(), e); + Slog.e(TAG, r.getStateString()); } if (info != null) { diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index ca050918d83a..5ef03d1cac6f 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1147,7 +1147,7 @@ public class ApplicationPackageManager extends PackageManager { } private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) { - UserInfo userInfo = getUserIfProfile(user.getIdentifier()); + UserInfo userInfo = getUserInfo(user.getIdentifier()); if (userInfo != null && userInfo.isManagedProfile()) { return getDrawableForDensity(drawableId, density); } @@ -1156,7 +1156,7 @@ public class ApplicationPackageManager extends PackageManager { @Override public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) { - UserInfo userInfo = getUserIfProfile(user.getIdentifier()); + UserInfo userInfo = getUserInfo(user.getIdentifier()); if (userInfo != null && userInfo.isManagedProfile()) { return Resources.getSystem().getString( com.android.internal.R.string.managed_profile_label_badge, label); @@ -2025,6 +2025,15 @@ public class ApplicationPackageManager extends PackageManager { } @Override + public void flushPackageRestrictionsAsUser(int userId) { + try { + mPM.flushPackageRestrictionsAsUser(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + @Override public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, UserHandle user) { try { @@ -2252,21 +2261,15 @@ public class ApplicationPackageManager extends PackageManager { private int getBadgeResIdForUser(int userHandle) { // Return the framework-provided badge. - UserInfo userInfo = getUserIfProfile(userHandle); + UserInfo userInfo = getUserInfo(userHandle); if (userInfo != null && userInfo.isManagedProfile()) { return com.android.internal.R.drawable.ic_corp_icon_badge; } return 0; } - private UserInfo getUserIfProfile(int userHandle) { - List<UserInfo> userProfiles = getUserManager().getProfiles(mContext.getUserId()); - for (UserInfo user : userProfiles) { - if (user.id == userHandle) { - return user; - } - } - return null; + private UserInfo getUserInfo(int userHandle) { + return getUserManager().getUserInfo(userHandle); } /** {@hide} */ diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 32ace144ddd8..4fccbc9a79c2 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1332,9 +1332,14 @@ class ContextImpl extends Context { } } try { - return ActivityManagerNative.getDefault().registerReceiver( + final Intent intent = ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); + if (intent != null) { + intent.setExtrasClassLoader(getClassLoader()); + intent.prepareToEnterProcess(); + } + return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index cdbf598ebb9d..8e87e2661361 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -475,8 +475,13 @@ public interface IActivityManager extends IInterface { public void keyguardWaitingForActivityDrawn() throws RemoteException; - public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) throws RemoteException; + /** + * Notify the system that the keyguard is going away. + * + * @param flags See {@link android.view.WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE} + * etc. + */ + public void keyguardGoingAway(int flags) throws RemoteException; public boolean shouldUpRecreateTask(IBinder token, String destAffinity) throws RemoteException; diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index b8fc32308961..c68fd659a25b 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -281,7 +281,7 @@ public final class LoadedApk { addedPaths.addAll(newPaths); } synchronized (this) { - mClassLoader = createOrUpdateClassLoaderLocked(addedPaths); + createOrUpdateClassLoaderLocked(addedPaths); if (mResources != null) { mResources = mActivityThread.getTopLevelResources(mResDir, mSplitResDirs, mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, @@ -402,101 +402,99 @@ public final class LoadedApk { } } } - - final String zip = TextUtils.join(File.pathSeparator, outZipPaths); } - private ClassLoader createOrUpdateClassLoaderLocked(List<String> addedPaths) { - final ClassLoader classLoader; - if (mIncludeCode && !mPackageName.equals("android")) { - // Avoid the binder call when the package is the current application package. - // The activity manager will perform ensure that dexopt is performed before - // spinning up the process. - if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) { - VMRuntime.getRuntime().vmInstructionSet(); - try { - ActivityThread.getPackageManager().notifyPackageUse(mPackageName); - } catch (RemoteException re) { - throw re.rethrowFromSystemServer(); - } + private void createOrUpdateClassLoaderLocked(List<String> addedPaths) { + if (mPackageName.equals("android")) { + if (mClassLoader != null) { + // nothing to update + return; } - final List<String> zipPaths = new ArrayList<>(); - final List<String> libPaths = new ArrayList<>(); - - if (mRegisterPackage) { - try { - ActivityManagerNative.getDefault().addPackageDependency(mPackageName); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + if (mBaseClassLoader != null) { + mClassLoader = mBaseClassLoader; + } else { + mClassLoader = ClassLoader.getSystemClassLoader(); } - makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths); - final String zip = TextUtils.join(File.pathSeparator, zipPaths); - final boolean isBundledApp = mApplicationInfo.isSystemApp() - && !mApplicationInfo.isUpdatedSystemApp(); - String libraryPermittedPath = mDataDir; - if (isBundledApp) { - // This is necessary to grant bundled apps access to - // libraries located in subdirectories of /system/lib - libraryPermittedPath += File.pathSeparator + - System.getProperty("java.library.path"); + return; + } + + // Avoid the binder call when the package is the current application package. + // The activity manager will perform ensure that dexopt is performed before + // spinning up the process. + if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) { + VMRuntime.getRuntime().vmInstructionSet(); + try { + ActivityThread.getPackageManager().notifyPackageUse(mPackageName); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); } - // DO NOT SHIP: this is a workaround for apps loading native libraries - // provided by 3rd party apps using absolute path instead of corresponding - // classloader; see http://b/26954419 for example. - if (mApplicationInfo.targetSdkVersion <= 23) { - libraryPermittedPath += File.pathSeparator + "/data/app"; + } + + final List<String> zipPaths = new ArrayList<>(); + final List<String> libPaths = new ArrayList<>(); + + if (mRegisterPackage) { + try { + ActivityManagerNative.getDefault().addPackageDependency(mPackageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } - // ----------------------------------------------------------------------------- + } + + makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths); + final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : ""; + final boolean isBundledApp = mApplicationInfo.isSystemApp() + && !mApplicationInfo.isUpdatedSystemApp(); + String libraryPermittedPath = mDataDir; + if (isBundledApp) { + // This is necessary to grant bundled apps access to + // libraries located in subdirectories of /system/lib + libraryPermittedPath += File.pathSeparator + + System.getProperty("java.library.path"); + } + // DO NOT SHIP: this is a workaround for apps loading native libraries + // provided by 3rd party apps using absolute path instead of corresponding + // classloader; see http://b/26954419 for example. + if (mApplicationInfo.targetSdkVersion <= 23) { + libraryPermittedPath += File.pathSeparator + "/data/app"; + } + // ----------------------------------------------------------------------------- - final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); + final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); - /* - * With all the combination done (if necessary, actually - * create the class loader. - */ + /* + * With all the combination done (if necessary, actually + * create the class loader. + */ - if (ActivityThread.localLOGV) - Slog.v(ActivityThread.TAG, "Class path: " + zip + - ", JNI path: " + librarySearchPath); + if (ActivityThread.localLOGV) + Slog.v(ActivityThread.TAG, "Class path: " + zip + + ", JNI path: " + librarySearchPath); - if (mClassLoader == null) { - // Temporarily disable logging of disk reads on the Looper thread - // as this is early and necessary. - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); - - classLoader = ApplicationLoaders.getDefault().getClassLoader(zip, - mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, - libraryPermittedPath, mBaseClassLoader); - - StrictMode.setThreadPolicy(oldPolicy); - } else if (addedPaths != null && addedPaths.size() > 0) { - final String add = TextUtils.join(File.pathSeparator, addedPaths); - ApplicationLoaders.getDefault().addPath(mClassLoader, add); - classLoader = mClassLoader; - } else { - classLoader = mClassLoader; - } - } else { - if (mClassLoader == null) { - if (mBaseClassLoader == null) { - classLoader = ClassLoader.getSystemClassLoader(); - } else { - classLoader = mBaseClassLoader; - } - } else { - classLoader = mClassLoader; - } + if (mClassLoader == null) { + // Temporarily disable logging of disk reads on the Looper thread + // as this is early and necessary. + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + + mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip, + mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath, + libraryPermittedPath, mBaseClassLoader); + + StrictMode.setThreadPolicy(oldPolicy); + } + + if (addedPaths != null && addedPaths.size() > 0) { + final String add = TextUtils.join(File.pathSeparator, addedPaths); + ApplicationLoaders.getDefault().addPath(mClassLoader, add); } - return classLoader; } public ClassLoader getClassLoader() { synchronized (this) { if (mClassLoader == null) { - mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/); + createOrUpdateClassLoaderLocked(null /*addedPaths*/); } return mClassLoader; } @@ -915,6 +913,8 @@ public final class LoadedApk { mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); mStrongRef = strong ? rd : null; } + + @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { LoadedApk.ReceiverDispatcher rd = mDispatcher.get(); @@ -998,6 +998,7 @@ public final class LoadedApk { try { ClassLoader cl = mReceiver.getClass().getClassLoader(); intent.setExtrasClassLoader(cl); + intent.prepareToEnterProcess(); setExtrasClassLoader(cl); receiver.setPendingResult(this); receiver.onReceive(mContext, intent); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 88c89648f52e..e9d0846fe71c 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3173,16 +3173,9 @@ public class Notification implements Parcelable } private void bindHeaderAppName(RemoteViews contentView) { - PackageManager packageManager = mContext.getPackageManager(); - ApplicationInfo info = null; - try { - info = packageManager.getApplicationInfo(mContext.getApplicationInfo().packageName, - 0); - } catch (final NameNotFoundException e) { - return; - } - CharSequence appName = info != null ? packageManager.getApplicationLabel(info) - : null; + CharSequence appName = mContext.getPackageManager() + .getApplicationLabel(mContext.getApplicationInfo()); + if (TextUtils.isEmpty(appName)) { return; } @@ -3204,6 +3197,7 @@ public class Notification implements Parcelable } private void resetStandardTemplateWithActions(RemoteViews big) { + big.setViewVisibility(R.id.actions_container, View.GONE); big.setViewVisibility(R.id.actions, View.GONE); big.removeAllViews(R.id.actions); @@ -3225,6 +3219,7 @@ public class Notification implements Parcelable int N = mActions.size(); if (N > 0) { + big.setViewVisibility(R.id.actions_container, View.VISIBLE); big.setViewVisibility(R.id.actions, View.VISIBLE); if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS; for (int i=0; i<N; i++) { @@ -4587,13 +4582,13 @@ public class Notification implements Parcelable private void buildIntoRemoteViewContent(RemoteViews remoteViews, RemoteViews customContent) { - remoteViews.removeAllViews(R.id.notification_main_column); - // Need to clone customContent before adding, because otherwise it can no longer be - // parceled independently of remoteViews. if (customContent != null) { + // Need to clone customContent before adding, because otherwise it can no longer be + // parceled independently of remoteViews. customContent = customContent.clone(); + remoteViews.removeAllViews(R.id.notification_main_column); + remoteViews.addView(R.id.notification_main_column, customContent); } - remoteViews.addView(R.id.notification_main_column, customContent); // also update the end margin if there is an image int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( R.dimen.notification_content_margin_end); @@ -4696,13 +4691,13 @@ public class Notification implements Parcelable private RemoteViews buildIntoRemoteView(RemoteViews remoteViews, int id, RemoteViews customContent) { - remoteViews.removeAllViews(id); - // Need to clone customContent before adding, because otherwise it can no longer be - // parceled independently of remoteViews. if (customContent != null) { + // Need to clone customContent before adding, because otherwise it can no longer be + // parceled independently of remoteViews. customContent = customContent.clone(); + remoteViews.removeAllViews(id); + remoteViews.addView(id, customContent); } - remoteViews.addView(id, customContent); return remoteViews; } } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 10aa7ebc136a..0d4729d8349f 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -913,10 +913,6 @@ public class NotificationManager * (e.g. via sound & vibration) and is applied globally. * @return One of the INTERRUPTION_FILTER_ constants, or INTERRUPTION_FILTER_UNKNOWN when * unavailable. - * - * <p> - * Only available if policy access is granted to this package. - * See {@link #isNotificationPolicyAccessGranted}. */ public final @InterruptionFilter int getCurrentInterruptionFilter() { final INotificationManager service = getService(); diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 6c0b69c8afdb..9d7f7246a25d 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -51,6 +51,7 @@ import android.hardware.display.DisplayManager; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.IHdmiControlService; import android.hardware.input.InputManager; +import android.hardware.location.ContextHubManager; import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbManager; import android.hardware.radio.RadioManager; @@ -765,6 +766,14 @@ final class SystemServiceRegistry { public SystemHealthManager createService(ContextImpl ctx) { return new SystemHealthManager(); }}); + + registerService(Context.CONTEXTHUB_SERVICE, ContextHubManager.class, + new CachedServiceFetcher<ContextHubManager>() { + @Override + public ContextHubManager createService(ContextImpl ctx) { + return new ContextHubManager(ctx.getOuterContext(), + ctx.mMainThread.getHandler().getLooper()); + }}); } /** diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 2d06dcca35f6..52e52728c25a 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -919,8 +919,8 @@ public class WallpaperManager { * image for restore to a future device; {@code false} otherwise. * @param which Flags indicating which wallpaper(s) to configure with the new imagery. * - * @see #FLAG_SET_LOCK_WALLPAPER - * @see #FLAG_SET_SYSTEM_WALLPAPER + * @see #FLAG_SET_LOCK + * @see #FLAG_SET_SYSTEM * * @return An integer ID assigned to the newly active wallpaper; or zero on failure. * @@ -1038,8 +1038,8 @@ public class WallpaperManager { * image for restore to a future device; {@code false} otherwise. * @param which Flags indicating which wallpaper(s) to configure with the new imagery. * - * @see #FLAG_SET_LOCK_WALLPAPER - * @see #FLAG_SET_SYSTEM_WALLPAPER + * @see #FLAG_SET_LOCK + * @see #FLAG_SET_SYSTEM * * @throws IOException */ diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java index a34e8551ed4b..dd70b5dfd1f0 100644 --- a/core/java/android/app/admin/DeviceAdminReceiver.java +++ b/core/java/android/app/admin/DeviceAdminReceiver.java @@ -268,7 +268,7 @@ public class DeviceAdminReceiver extends BroadcastReceiver { "android.app.action.BUGREPORT_SHARE"; /** - * Broadcast action: notify that a new batch of device logs is ready to be collected. + * Broadcast action: notify that a new batch of security logs is ready to be collected. * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @@ -284,10 +284,11 @@ public class DeviceAdminReceiver extends BroadcastReceiver { public static final String EXTRA_BUGREPORT_HASH = "android.app.extra.BUGREPORT_HASH"; /** - * An {@code int} failure code representing the reason of the bugreport failure. + * An {@code int} failure code representing the reason of the bugreport failure. One of + * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING} + * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE} * * @see #ACTION_BUGREPORT_FAILED - * @see #BUGREPORT_FAILURE_FAILED_COMPLETING, #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE * @hide */ public static final String EXTRA_BUGREPORT_FAILURE_REASON = @@ -305,9 +306,24 @@ public class DeviceAdminReceiver extends BroadcastReceiver { BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE }) public @interface BugreportFailureCode {} - /** Bugreport completion process failed. */ + + /** + * Bugreport completion process failed. + * + * <p>If this error code is received, the requesting of bugreport can be retried. + * @see DevicePolicyManager#requestBugreport + */ public static final int BUGREPORT_FAILURE_FAILED_COMPLETING = 0; - /** Bugreport is no longer available for collection. */ + + /** + * Bugreport has been created, but is no longer available for collection. + * + * <p>This error likely occurs because the user of the device hasn't consented to share + * the bugreport for a long period after its creation. + * + * <p>If this error code is received, the requesting of bugreport can be retried. + * @see DevicePolicyManager#requestBugreport + */ public static final int BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE = 1; /** @hide */ @@ -598,7 +614,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver { * @param context The running context as per {@link #onReceive}. * @param intent The received intent as per {@link #onReceive}. * @param failureCode int containing failure code. One of - * #BUGREPORT_FAILURE_FAILED_COMPLETING or #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE + * {@link #BUGREPORT_FAILURE_FAILED_COMPLETING} + * or {@link #BUGREPORT_FAILURE_FILE_NO_LONGER_AVAILABLE} * @see DevicePolicyManager#requestBugreport */ public void onBugreportFailed(Context context, Intent intent, @@ -606,13 +623,13 @@ public class DeviceAdminReceiver extends BroadcastReceiver { } /** - * Called when a new batch of device logs can be retrieved. + * Called when a new batch of security logs can be retrieved. * * <p>This callback is only applicable to device owners. * * @param context The running context as per {@link #onReceive}. * @param intent The received intent as per {@link #onReceive}. - * @see DevicePolicyManager#retrieveDeviceLogs(ComponentName) + * @see DevicePolicyManager#retrieveSecurityLogs(ComponentName) */ public void onSecurityLogsAvailable(Context context, Intent intent) { } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 53a6351b36e6..b7d9b80e9a53 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -25,16 +25,13 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.UserIdInt; import android.app.Activity; -import android.auditing.SecurityLog; -import android.auditing.SecurityLog.SecurityEvent; +import android.app.admin.SecurityLog.SecurityEvent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; -import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.graphics.Bitmap; import android.net.ProxyInfo; @@ -51,13 +48,12 @@ import android.provider.ContactsContract.Directory; import android.provider.Settings; import android.security.Credentials; import android.service.restrictions.RestrictionsReceiver; +import android.telephony.TelephonyManager; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.org.conscrypt.TrustedCertificateStore; -import org.xmlpull.v1.XmlPullParserException; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.lang.annotation.Retention; @@ -80,18 +76,18 @@ import java.util.Set; /** * Public interface for managing policies enforced on a device. Most clients of this class must be - * registered with the system as a - * <a href="{@docRoot}guide/topics/admin/device-admin.html">device administrator</a>. Additionally, - * a device administrator may be registered as either a profile or device owner. A given method is - * accessible to all device administrators unless the documentation for that method specifies that - * it is restricted to either device or profile owners. - * + * registered with the system as a <a href="{@docRoot}guide/topics/admin/device-admin.html">device + * administrator</a>. Additionally, a device administrator may be registered as either a profile or + * device owner. A given method is accessible to all device administrators unless the documentation + * for that method specifies that it is restricted to either device or profile owners. Any + * application calling an api may only pass as an argument a device administrator component it + * owns. Otherwise, a {@link SecurityException} will be thrown. * <div class="special reference"> * <h3>Developer Guides</h3> - * <p>For more information about managing policies for device administration, read the - * <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a> - * developer guide. - * </div> + * <p> + * For more information about managing policies for device administration, read the <a href= + * "{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a> developer + * guide. </div> */ public class DevicePolicyManager { private static String TAG = "DevicePolicyManager"; @@ -1032,8 +1028,11 @@ public class DevicePolicyManager { public @interface UserProvisioningState {} /** - * Return true if the given administrator component is currently - * active (enabled) in the system. + * Return true if the given administrator component is currently active (enabled) in the system. + * + * @param admin The administrator component to check for. + * @return {@code true} if {@code admin} is currently enabled in the system, {@code false} + * otherwise */ public boolean isAdminActive(@NonNull ComponentName admin) { return isAdminActiveAsUser(admin, myUserId()); @@ -1127,6 +1126,9 @@ public class DevicePolicyManager { * * <p>Note that the operation is not synchronous and the admin might still be active (as * indicated by {@link #getActiveAdmins()}) by the time this method returns. + * + * @param admin The administration compononent to remove. + * @throws SecurityException if the caller is not in the owner application of {@code admin}. */ public void removeActiveAdmin(@NonNull ComponentName admin) { if (mService != null) { @@ -1139,13 +1141,14 @@ public class DevicePolicyManager { } /** - * Returns true if an administrator has been granted a particular device policy. This can - * be used to check whether the administrator was activated under an earlier set of policies, - * but requires additional policies after an upgrade. + * Returns true if an administrator has been granted a particular device policy. This can be + * used to check whether the administrator was activated under an earlier set of policies, but + * requires additional policies after an upgrade. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Must be - * an active administrator, or an exception will be thrown. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Must be an + * active administrator, or an exception will be thrown. * @param usesPolicy Which uses-policy to check, as defined in {@link DeviceAdminInfo}. + * @throws SecurityException if {@code admin} is not an active administrator. */ public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) { if (mService != null) { @@ -1252,34 +1255,32 @@ public class DevicePolicyManager { public static final int PASSWORD_QUALITY_MANAGED = 0x80000; /** - * Called by an application that is administering the device to set the - * password restrictions it is imposing. After setting this, the user - * will not be able to enter a new password that is not at least as - * restrictive as what has been set. Note that the current password - * will remain until the user has set a new one, so the change does not - * take place immediately. To prompt the user for a new password, use - * {@link #ACTION_SET_NEW_PASSWORD} or + * Called by an application that is administering the device to set the password restrictions it + * is imposing. After setting this, the user will not be able to enter a new password that is + * not at least as restrictive as what has been set. Note that the current password will remain + * until the user has set a new one, so the change does not take place immediately. To prompt + * the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after calling this method. - * - * <p>Quality constants are ordered so that higher values are more restrictive; - * thus the highest requested quality constant (between the policy set here, - * the user's preference, and any other considerations) is the one that - * is in effect. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * <p> + * Quality constants are ordered so that higher values are more restrictive; thus the highest + * requested quality constant (between the policy set here, the user's preference, and any other + * considerations) is the one that is in effect. + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param quality The new desired quality. One of - * {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING}, - * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, - * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC} - * or {@link #PASSWORD_QUALITY_COMPLEX}. + * @param quality The new desired quality. One of {@link #PASSWORD_QUALITY_UNSPECIFIED}, + * {@link #PASSWORD_QUALITY_SOMETHING}, {@link #PASSWORD_QUALITY_NUMERIC}, + * {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, {@link #PASSWORD_QUALITY_ALPHABETIC}, + * {@link #PASSWORD_QUALITY_ALPHANUMERIC} or {@link #PASSWORD_QUALITY_COMPLEX}. + * @throws SecurityException if {@code admin} is not an active administrator or if {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public void setPasswordQuality(@NonNull ComponentName admin, int quality) { if (mService != null) { @@ -1320,30 +1321,30 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to set the - * minimum allowed password length. After setting this, the user - * will not be able to enter a new password that is not at least as - * restrictive as what has been set. Note that the current password - * will remain until the user has set a new one, so the change does not - * take place immediately. To prompt the user for a new password, use - * {@link #ACTION_SET_NEW_PASSWORD} or - * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This - * constraint is only imposed if the administrator has also requested either - * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, - * {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC}, - * or {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * Called by an application that is administering the device to set the minimum allowed password + * length. After setting this, the user will not be able to enter a new password that is not at + * least as restrictive as what has been set. Note that the current password will remain until + * the user has set a new one, so the change does not take place immediately. To prompt the user + * for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or + * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is + * only imposed if the administrator has also requested either {@link #PASSWORD_QUALITY_NUMERIC} + * , {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, {@link #PASSWORD_QUALITY_ALPHABETIC}, + * {@link #PASSWORD_QUALITY_ALPHANUMERIC}, or {@link #PASSWORD_QUALITY_COMPLEX} with + * {@link #setPasswordQuality}. + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param length The new desired minimum password length. A value of 0 - * means there is no restriction. + * @param length The new desired minimum password length. A value of 0 means there is no + * restriction. + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) { if (mService != null) { @@ -1385,31 +1386,28 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to set the - * minimum number of upper case letters required in the password. After - * setting this, the user will not be able to enter a new password that is - * not at least as restrictive as what has been set. Note that the current - * password will remain until the user has set a new one, so the change does - * not take place immediately. To prompt the user for a new password, use - * {@link #ACTION_SET_NEW_PASSWORD} or - * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This - * constraint is only imposed if the administrator has also requested - * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The - * default value is 0. + * Called by an application that is administering the device to set the minimum number of upper + * case letters required in the password. After setting this, the user will not be able to enter + * a new password that is not at least as restrictive as what has been set. Note that the + * current password will remain until the user has set a new one, so the change does not take + * place immediately. To prompt the user for a new password, use + * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after + * setting this value. This constraint is only imposed if the administrator has also requested + * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0. * <p> * The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param length The new desired minimum number of upper case letters - * required in the password. A value of 0 means there is no - * restriction. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param length The new desired minimum number of upper case letters required in the password. + * A value of 0 means there is no restriction. + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) { if (mService != null) { @@ -1457,31 +1455,28 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to set the - * minimum number of lower case letters required in the password. After - * setting this, the user will not be able to enter a new password that is - * not at least as restrictive as what has been set. Note that the current - * password will remain until the user has set a new one, so the change does - * not take place immediately. To prompt the user for a new password, use - * {@link #ACTION_SET_NEW_PASSWORD} or - * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This - * constraint is only imposed if the administrator has also requested - * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The - * default value is 0. + * Called by an application that is administering the device to set the minimum number of lower + * case letters required in the password. After setting this, the user will not be able to enter + * a new password that is not at least as restrictive as what has been set. Note that the + * current password will remain until the user has set a new one, so the change does not take + * place immediately. To prompt the user for a new password, use + * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after + * setting this value. This constraint is only imposed if the administrator has also requested + * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0. * <p> * The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param length The new desired minimum number of lower case letters - * required in the password. A value of 0 means there is no - * restriction. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param length The new desired minimum number of lower case letters required in the password. + * A value of 0 means there is no restriction. + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) { if (mService != null) { @@ -1529,30 +1524,28 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to set the - * minimum number of letters required in the password. After setting this, - * the user will not be able to enter a new password that is not at least as - * restrictive as what has been set. Note that the current password will - * remain until the user has set a new one, so the change does not take - * place immediately. To prompt the user for a new password, use - * {@link #ACTION_SET_NEW_PASSWORD} or - * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This - * constraint is only imposed if the administrator has also requested - * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The - * default value is 1. + * Called by an application that is administering the device to set the minimum number of + * letters required in the password. After setting this, the user will not be able to enter a + * new password that is not at least as restrictive as what has been set. Note that the current + * password will remain until the user has set a new one, so the change does not take place + * immediately. To prompt the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or + * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is + * only imposed if the administrator has also requested {@link #PASSWORD_QUALITY_COMPLEX} with + * {@link #setPasswordQuality}. The default value is 1. * <p> * The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param length The new desired minimum number of letters required in the - * password. A value of 0 means there is no restriction. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param length The new desired minimum number of letters required in the password. A value of + * 0 means there is no restriction. + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) { if (mService != null) { @@ -1599,30 +1592,28 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to set the - * minimum number of numerical digits required in the password. After - * setting this, the user will not be able to enter a new password that is - * not at least as restrictive as what has been set. Note that the current - * password will remain until the user has set a new one, so the change does - * not take place immediately. To prompt the user for a new password, use - * {@link #ACTION_SET_NEW_PASSWORD} or - * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This - * constraint is only imposed if the administrator has also requested - * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The - * default value is 1. + * Called by an application that is administering the device to set the minimum number of + * numerical digits required in the password. After setting this, the user will not be able to + * enter a new password that is not at least as restrictive as what has been set. Note that the + * current password will remain until the user has set a new one, so the change does not take + * place immediately. To prompt the user for a new password, use + * {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after + * setting this value. This constraint is only imposed if the administrator has also requested + * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 1. * <p> * The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param length The new desired minimum number of numerical digits required - * in the password. A value of 0 means there is no restriction. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param length The new desired minimum number of numerical digits required in the password. A + * value of 0 means there is no restriction. + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) { if (mService != null) { @@ -1669,30 +1660,28 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to set the - * minimum number of symbols required in the password. After setting this, - * the user will not be able to enter a new password that is not at least as - * restrictive as what has been set. Note that the current password will - * remain until the user has set a new one, so the change does not take - * place immediately. To prompt the user for a new password, use - * {@link #ACTION_SET_NEW_PASSWORD} or - * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This - * constraint is only imposed if the administrator has also requested - * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The - * default value is 1. + * Called by an application that is administering the device to set the minimum number of + * symbols required in the password. After setting this, the user will not be able to enter a + * new password that is not at least as restrictive as what has been set. Note that the current + * password will remain until the user has set a new one, so the change does not take place + * immediately. To prompt the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or + * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is + * only imposed if the administrator has also requested {@link #PASSWORD_QUALITY_COMPLEX} with + * {@link #setPasswordQuality}. The default value is 1. * <p> * The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param length The new desired minimum number of symbols required in the - * password. A value of 0 means there is no restriction. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param length The new desired minimum number of symbols required in the password. A value of + * 0 means there is no restriction. + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) { if (mService != null) { @@ -1738,30 +1727,28 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to set the - * minimum number of non-letter characters (numerical digits or symbols) - * required in the password. After setting this, the user will not be able - * to enter a new password that is not at least as restrictive as what has - * been set. Note that the current password will remain until the user has - * set a new one, so the change does not take place immediately. To prompt - * the user for a new password, use {@link #ACTION_SET_NEW_PASSWORD} or - * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after - * setting this value. This constraint is only imposed if the administrator - * has also requested {@link #PASSWORD_QUALITY_COMPLEX} with - * {@link #setPasswordQuality}. The default value is 0. + * Called by an application that is administering the device to set the minimum number of + * non-letter characters (numerical digits or symbols) required in the password. After setting + * this, the user will not be able to enter a new password that is not at least as restrictive + * as what has been set. Note that the current password will remain until the user has set a new + * one, so the change does not take place immediately. To prompt the user for a new password, + * use {@link #ACTION_SET_NEW_PASSWORD} or {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after + * setting this value. This constraint is only imposed if the administrator has also requested + * {@link #PASSWORD_QUALITY_COMPLEX} with {@link #setPasswordQuality}. The default value is 0. * <p> * The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param length The new desired minimum number of letters required in the - * password. A value of 0 means there is no restriction. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param length The new desired minimum number of letters required in the password. A value of + * 0 means there is no restriction. + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) { if (mService != null) { @@ -1807,33 +1794,31 @@ public class DevicePolicyManager { return 0; } - /** - * Called by an application that is administering the device to set the length - * of the password history. After setting this, the user will not be able to - * enter a new password that is the same as any password in the history. Note - * that the current password will remain until the user has set a new one, so - * the change does not take place immediately. To prompt the user for a new - * password, use {@link #ACTION_SET_NEW_PASSWORD} or - * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. - * This constraint is only imposed if the administrator has also requested - * either {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX} - * {@link #PASSWORD_QUALITY_ALPHABETIC}, or {@link #PASSWORD_QUALITY_ALPHANUMERIC} - * with {@link #setPasswordQuality}. - * - * <p> - * The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this - * method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. - * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param length The new desired length of password history. A value of 0 - * means there is no restriction. - */ + /** + * Called by an application that is administering the device to set the length of the password + * history. After setting this, the user will not be able to enter a new password that is the + * same as any password in the history. Note that the current password will remain until the + * user has set a new one, so the change does not take place immediately. To prompt the user for + * a new password, use {@link #ACTION_SET_NEW_PASSWORD} or + * {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} after setting this value. This constraint is + * only imposed if the administrator has also requested either {@link #PASSWORD_QUALITY_NUMERIC} + * , {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX} {@link #PASSWORD_QUALITY_ALPHABETIC}, or + * {@link #PASSWORD_QUALITY_ALPHANUMERIC} with {@link #setPasswordQuality}. + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param length The new desired length of password history. A value of 0 means there is no + * restriction. + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} + */ public void setPasswordHistoryLength(@NonNull ComponentName admin, int length) { if (mService != null) { try { @@ -1845,30 +1830,32 @@ public class DevicePolicyManager { } /** - * Called by a device admin to set the password expiration timeout. Calling this method - * will restart the countdown for password expiration for the given admin, as will changing - * the device password (for all admins). - * - * <p>The provided timeout is the time delta in ms and will be added to the current time. - * For example, to have the password expire 5 days from now, timeout would be - * 5 * 86400 * 1000 = 432000000 ms for timeout. - * - * <p>To disable password expiration, a value of 0 may be used for timeout. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this - * method; if it has not, a security exception will be thrown. - * - * <p> Note that setting the password will automatically reset the expiration time for all - * active admins. Active admins do not need to explicitly call this method in that case. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * Called by a device admin to set the password expiration timeout. Calling this method will + * restart the countdown for password expiration for the given admin, as will changing the + * device password (for all admins). + * <p> + * The provided timeout is the time delta in ms and will be added to the current time. For + * example, to have the password expire 5 days from now, timeout would be 5 * 86400 * 1000 = + * 432000000 ms for timeout. + * <p> + * To disable password expiration, a value of 0 may be used for timeout. + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * Note that setting the password will automatically reset the expiration time for all active + * admins. Active admins do not need to explicitly call this method in that case. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param timeout The limit (in ms) that a password can remain in effect. A value of 0 - * means there is no restriction (unlimited). + * @param timeout The limit (in ms) that a password can remain in effect. A value of 0 means + * there is no restriction (unlimited). + * @throws SecurityException if {@code admin} is not an active administrator or {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} */ public void setPasswordExpirationTimeout(@NonNull ComponentName admin, long timeout) { if (mService != null) { @@ -1970,20 +1957,22 @@ public class DevicePolicyManager { } /** - * Determine whether the current password the user has set is sufficient - * to meet the policy requirements (e.g. quality, minimum length) that have been - * requested by the admins of this user and its participating profiles. - * Restrictions on profiles that have a separate challenge are not taken into account. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to determine - * if the password set on the parent profile is sufficient. + * Determine whether the current password the user has set is sufficient to meet the policy + * requirements (e.g. quality, minimum length) that have been requested by the admins of this + * user and its participating profiles. Restrictions on profiles that have a separate challenge + * are not taken into account. + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to determine if the password set on + * the parent profile is sufficient. * * @return Returns true if the password meets the current requirements, else false. + * @throws SecurityException if the calling application does not own an active administrator + * that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} */ public boolean isActivePasswordSufficient() { if (mService != null) { @@ -2003,6 +1992,7 @@ public class DevicePolicyManager { * * @param userHandle the userId of the profile to check the password for. * @return Returns true if the password would meet the current requirements, else false. + * @throws SecurityException if {@code userHandle} is not a managed profile. * @hide */ public boolean isProfileActivePasswordSufficientForParent(int userHandle) { @@ -2017,16 +2007,20 @@ public class DevicePolicyManager { } /** - * Retrieve the number of times the user has failed at entering a - * password since that last successful password entry. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve - * the number of failed password attemts for the parent user. + * Retrieve the number of times the user has failed at entering a password since that last + * successful password entry. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to retrieve the number of failed + * password attemts for the parent user. + * <p> + * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} + * to be able to call this method; if it has not, a security exception will be thrown. * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to be able to call - * this method; if it has not, a security exception will be thrown. + * @return The number of times user has entered an incorrect password since the last correct + * password entry. + * @throws SecurityException if the calling application does not own an active administrator + * that uses {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} */ public int getCurrentFailedPasswordAttempts() { return getCurrentFailedPasswordAttempts(myUserId()); @@ -2071,27 +2065,28 @@ public class DevicePolicyManager { } /** - * Setting this to a value greater than zero enables a built-in policy - * that will perform a device or profile wipe after too many incorrect - * device-unlock passwords have been entered. This built-in policy combines - * watching for failed passwords and wiping the device, and requires - * that you request both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and + * Setting this to a value greater than zero enables a built-in policy that will perform a + * device or profile wipe after too many incorrect device-unlock passwords have been entered. + * This built-in policy combines watching for failed passwords and wiping the device, and + * requires that you request both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}}. - * - * <p>To implement any other policy (e.g. wiping data for a particular - * application only, erasing or revoking credentials, or reporting the - * failure to a server), you should implement - * {@link DeviceAdminReceiver#onPasswordFailed(Context, android.content.Intent)} - * instead. Do not use this API, because if the maximum count is reached, - * the device or profile will be wiped immediately, and your callback will not be invoked. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * a value on the parent profile. + * <p> + * To implement any other policy (e.g. wiping data for a particular application only, erasing or + * revoking credentials, or reporting the failure to a server), you should implement + * {@link DeviceAdminReceiver#onPasswordFailed(Context, android.content.Intent)} instead. Do not + * use this API, because if the maximum count is reached, the device or profile will be wiped + * immediately, and your callback will not be invoked. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set a value on the parent + * profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param num The number of failed password attempts at which point the - * device or profile will be wiped. + * @param num The number of failed password attempts at which point the device or profile will + * be wiped. + * @throws SecurityException if {@code admin} is not an active administrator or does not use + * both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and + * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}. */ public void setMaximumFailedPasswordsForWipe(@NonNull ComponentName admin, int num) { if (mService != null) { @@ -2169,42 +2164,41 @@ public class DevicePolicyManager { public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002; /** - * Force a new device unlock password (the password needed to access the - * entire device, not for individual accounts) on the user. This takes - * effect immediately. - * - * <p>Calling this from a managed profile that shares the password with the owner profile - * will throw a security exception. - * - * <p><em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for + * Force a new device unlock password (the password needed to access the entire device, not for + * individual accounts) on the user. This takes effect immediately. + * <p> + * Calling this from a managed profile that shares the password with the owner profile will + * throw a security exception. + * <p> + * <em>Note: This API has been limited as of {@link android.os.Build.VERSION_CODES#N} for * device admins that are not device owner and not profile owner. * The password can now only be changed if there is currently no password set. Device owner * and profile owner can still do this.</em> - * - * <p>The given password must be sufficient for the - * current password quality and length constraints as returned by - * {@link #getPasswordQuality(ComponentName)} and - * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet - * these constraints, then it will be rejected and false returned. Note - * that the password may be a stronger quality (containing alphanumeric - * characters when the requested quality is only numeric), in which case - * the currently active quality will be increased to match. - * - * <p>Calling with a null or empty password will clear any existing PIN, - * pattern or password if the current password constraints allow it. <em>Note: This will not + * <p> + * The given password must be sufficient for the current password quality and length constraints + * as returned by {@link #getPasswordQuality(ComponentName)} and + * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet these constraints, then + * it will be rejected and false returned. Note that the password may be a stronger quality + * (containing alphanumeric characters when the requested quality is only numeric), in which + * case the currently active quality will be increased to match. + * <p> + * Calling with a null or empty password will clear any existing PIN, pattern or password if the + * current password constraints allow it. <em>Note: This will not * work in {@link android.os.Build.VERSION_CODES#N} and later for device admins that are not * device owner and not profile owner. Once set, the password cannot be changed to null or * empty, except by device owner or profile owner.</em> - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call - * this method; if it has not, a security exception will be thrown. + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call this method; if it has + * not, a security exception will be thrown. * * @param password The new password for the user. Null or empty clears the password. * @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and - * {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}. - * @return Returns true if the password was applied, or false if it is - * not acceptable for the current constraints or if the user has not been decrypted yet. + * {@link #RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT}. + * @return Returns true if the password was applied, or false if it is not acceptable for the + * current constraints or if the user has not been decrypted yet. + * @throws SecurityException if the calling application does not own an active administrator + * that uses {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} */ public boolean resetPassword(String password, int flags) { if (mParentInstance) { @@ -2221,21 +2215,22 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to set the - * maximum time for user activity until the device will lock. This limits - * the length that the user can set. It takes effect immediately. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to set - * restrictions on the parent profile. + * Called by an application that is administering the device to set the maximum time for user + * activity until the device will lock. This limits the length that the user can set. It takes + * effect immediately. + * <p> + * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} + * to be able to call this method; if it has not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param timeMs The new desired maximum time to lock in milliseconds. - * A value of 0 means there is no restriction. + * @param timeMs The new desired maximum time to lock in milliseconds. A value of 0 means there + * is no restriction. + * @throws SecurityException if {@code admin} is not an active administrator or it does not use + * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} */ public void setMaximumTimeToLock(@NonNull ComponentName admin, long timeMs) { if (mService != null) { @@ -2278,16 +2273,17 @@ public class DevicePolicyManager { } /** - * Make the device lock immediately, as if the lock screen timeout has - * expired at the point of this call. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call - * this method; if it has not, a security exception will be thrown. + * Make the device lock immediately, as if the lock screen timeout has expired at the point of + * this call. + * <p> + * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} + * to be able to call this method; if it has not, a security exception will be thrown. + * <p> + * This method can be called on the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)} in order to lock the parent profile. * - * <p>This method can be called on the {@link DevicePolicyManager} instance - * returned by {@link #getParentProfileInstance(ComponentName)} in order to lock - * the parent profile. + * @throws SecurityException if the calling application does not own an active administrator + * that uses {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} */ public void lockNow() { if (mService != null) { @@ -2315,16 +2311,16 @@ public class DevicePolicyManager { public static final int WIPE_RESET_PROTECTION_DATA = 0x0002; /** - * Ask the user data be wiped. Wiping the primary user will cause the - * device to reboot, erasing all user data while next booting up. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to be able to call - * this method; if it has not, a security exception will be thrown. + * Ask the user data be wiped. Wiping the primary user will cause the device to reboot, erasing + * all user data while next booting up. + * <p> + * The calling device admin must have requested {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to + * be able to call this method; if it has not, a security exception will be thrown. * - * @param flags Bit mask of additional options: currently supported flags - * are {@link #WIPE_EXTERNAL_STORAGE} and - * {@link #WIPE_RESET_PROTECTION_DATA}. + * @param flags Bit mask of additional options: currently supported flags are + * {@link #WIPE_EXTERNAL_STORAGE} and {@link #WIPE_RESET_PROTECTION_DATA}. + * @throws SecurityException if the calling application does not own an active administrator + * that uses {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} */ public void wipeData(int flags) { if (mService != null) { @@ -2408,20 +2404,20 @@ public class DevicePolicyManager { } /** - * Set a network-independent global HTTP proxy. This is not normally what you want - * for typical HTTP proxies - they are generally network dependent. However if you're - * doing something unusual like general internal filtering this may be useful. On - * a private network where the proxy is not accessible, you may break HTTP using this. - * - * <p>This method requires the caller to be the device owner. + * Set a network-independent global HTTP proxy. This is not normally what you want for typical + * HTTP proxies - they are generally network dependent. However if you're doing something + * unusual like general internal filtering this may be useful. On a private network where the + * proxy is not accessible, you may break HTTP using this. + * <p> + * This method requires the caller to be the device owner. + * <p> + * This proxy is only a recommendation and it is possible that some apps will ignore it. * - * <p>This proxy is only a recommendation and it is possible that some apps will ignore it. * @see ProxyInfo - * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param proxyInfo The a {@link ProxyInfo} object defining the new global - * HTTP proxy. A {@code null} value will clear the global HTTP proxy. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param proxyInfo The a {@link ProxyInfo} object defining the new global HTTP proxy. A + * {@code null} value will clear the global HTTP proxy. + * @throws SecurityException if {@code admin} is not the device owner. */ public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo proxyInfo) { @@ -2487,6 +2483,12 @@ public class DevicePolicyManager { public static final int ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY = 4; /** + * Result code for {@link #getStorageEncryptionStatus}: + * indicating that encryption is active and the encryption key is tied to the user. + */ + public static final int ENCRYPTION_STATUS_ACTIVE_PER_USER = 5; + + /** * Activity action: begin the process of encrypting data on the device. This activity should * be launched after using {@link #setStorageEncryption} to request encryption be activated. * After resuming from this activity, use {@link #getStorageEncryption} @@ -2538,36 +2540,35 @@ public class DevicePolicyManager { public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff; /** - * Called by an application that is administering the device to - * request that the storage system be encrypted. - * - * <p>When multiple device administrators attempt to control device - * encryption, the most secure, supported setting will always be - * used. If any device administrator requests device encryption, - * it will be enabled; Conversely, if a device administrator - * attempts to disable device encryption while another - * device administrator has enabled it, the call to disable will + * Called by an application that is administering the device to request that the storage system + * be encrypted. + * <p> + * When multiple device administrators attempt to control device encryption, the most secure, + * supported setting will always be used. If any device administrator requests device + * encryption, it will be enabled; Conversely, if a device administrator attempts to disable + * device encryption while another device administrator has enabled it, the call to disable will * fail (most commonly returning {@link #ENCRYPTION_STATUS_ACTIVE}). - * - * <p>This policy controls encryption of the secure (application data) storage area. Data - * written to other storage areas may or may not be encrypted, and this policy does not require - * or control the encryption of any other storage areas. - * There is one exception: If {@link android.os.Environment#isExternalStorageEmulated()} is - * {@code true}, then the directory returned by - * {@link android.os.Environment#getExternalStorageDirectory()} must be written to disk - * within the encrypted storage area. - * - * <p>Important Note: On some devices, it is possible to encrypt storage without requiring - * the user to create a device PIN or Password. In this case, the storage is encrypted, but - * the encryption key may not be fully secured. For maximum security, the administrator should - * also require (and check for) a pattern, PIN, or password. + * <p> + * This policy controls encryption of the secure (application data) storage area. Data written + * to other storage areas may or may not be encrypted, and this policy does not require or + * control the encryption of any other storage areas. There is one exception: If + * {@link android.os.Environment#isExternalStorageEmulated()} is {@code true}, then the + * directory returned by {@link android.os.Environment#getExternalStorageDirectory()} must be + * written to disk within the encrypted storage area. + * <p> + * Important Note: On some devices, it is possible to encrypt storage without requiring the user + * to create a device PIN or Password. In this case, the storage is encrypted, but the + * encryption key may not be fully secured. For maximum security, the administrator should also + * require (and check for) a pattern, PIN, or password. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param encrypt true to request encryption, false to release any previous request * @return the new request status (for all active admins) - will be one of - * {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE}, or - * {@link #ENCRYPTION_STATUS_ACTIVE}. This is the value of the requests; Use - * {@link #getStorageEncryptionStatus()} to query the actual device state. + * {@link #ENCRYPTION_STATUS_UNSUPPORTED}, {@link #ENCRYPTION_STATUS_INACTIVE}, or + * {@link #ENCRYPTION_STATUS_ACTIVE}. This is the value of the requests; Use + * {@link #getStorageEncryptionStatus()} to query the actual device state. + * @throws SecurityException if {@code admin} is not an active administrator or does not use + * {@link DeviceAdminInfo#USES_ENCRYPTED_STORAGE} */ public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) { if (mService != null) { @@ -2627,7 +2628,7 @@ public class DevicePolicyManager { public int getStorageEncryptionStatus(int userHandle) { if (mService != null) { try { - return mService.getStorageEncryptionStatus(userHandle); + return mService.getStorageEncryptionStatus(mContext.getPackageName(), userHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2644,6 +2645,8 @@ public class DevicePolicyManager { * * @return false if the certBuffer cannot be parsed or installation is * interrupted, true otherwise. + * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile + * owner. */ public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) { if (mService != null) { @@ -2662,6 +2665,8 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if calling from a delegated certificate installer. * @param certBuffer encoded form of the certificate to remove. + * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile + * owner. */ public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) { if (mService != null) { @@ -2684,6 +2689,8 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if calling from a delegated certificate installer. * @return a List of byte[] arrays, each encoding one user CA certificate. + * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile + * owner. */ public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) { List<byte[]> certs = new ArrayList<byte[]>(); @@ -2711,6 +2718,8 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if calling from a delegated certificate installer. + * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile + * owner. */ public void uninstallAllUserCaCerts(@Nullable ComponentName admin) { if (mService != null) { @@ -2729,6 +2738,8 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or * {@code null} if calling from a delegated certificate installer. * @param certBuffer encoded form of the certificate to look up. + * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile + * owner. */ public boolean hasCaCertInstalled(@Nullable ComponentName admin, byte[] certBuffer) { if (mService != null) { @@ -2763,6 +2774,8 @@ public class DevicePolicyManager { * @param alias The private key alias under which to install the certificate. If a certificate * with that alias already exists, it will be overwritten. * @return {@code true} if the keys were installed, {@code false} otherwise. + * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile + * owner. */ public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey, @NonNull Certificate cert, @NonNull String alias) { @@ -2788,6 +2801,8 @@ public class DevicePolicyManager { * credentials immediately. Otherwise, access to the credentials will be gated by user * approval. * @return {@code true} if the keys were installed, {@code false} otherwise. + * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile + * owner. */ public boolean installKeyPair(@Nullable ComponentName admin, @NonNull PrivateKey privKey, @NonNull Certificate cert, @NonNull String alias, boolean requestAccess) { @@ -2814,6 +2829,8 @@ public class DevicePolicyManager { * {@code null} if calling from a delegated certificate installer. * @param alias The private key alias under which the certificate is installed. * @return {@code true} if the private key alias no longer exists, {@code false} otherwise. + * @throws SecurityException if {@code admin} is not {@code null} and not a device or profile + * owner. */ public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) { try { @@ -2843,15 +2860,16 @@ public class DevicePolicyManager { * Delegated certificate installer is a per-user state. The delegated access is persistent until * it is later cleared by calling this method with a null value or uninstallling the certificate * installer. - *<p> + * <p> * <b>Note:</b>Starting from {@link android.os.Build.VERSION_CODES#N}, if the caller * application's target SDK version is {@link android.os.Build.VERSION_CODES#N} or newer, the - * supplied certificate installer package must be installed when calling this API, - * otherwise an {@link IllegalArgumentException} will be thrown. + * supplied certificate installer package must be installed when calling this API, otherwise an + * {@link IllegalArgumentException} will be thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param installerPackage The package name of the certificate installer which will be given - * access. If {@code null} is given the current package will be cleared. + * access. If {@code null} is given the current package will be cleared. + * @throws SecurityException if {@code admin} is not a device or a profile owner. */ public void setCertInstallerPackage(@NonNull ComponentName admin, @Nullable String installerPackage) throws SecurityException { @@ -2865,12 +2883,13 @@ public class DevicePolicyManager { } /** - * Called by a profile owner or device owner to retrieve the certificate installer for the - * user. null if none is set. + * Called by a profile owner or device owner to retrieve the certificate installer for the user. + * null if none is set. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @return The package name of the current delegated certificate installer, or {@code null} - * if none is set. + * @return The package name of the current delegated certificate installer, or {@code null} if + * none is set. + * @throws SecurityException if {@code admin} is not a device or a profile owner. */ public String getCertInstallerPackage(@NonNull ComponentName admin) throws SecurityException { if (mService != null) { @@ -2885,18 +2904,18 @@ public class DevicePolicyManager { /** * Called by a device or profile owner to configure an always-on VPN connection through a - * specific application for the current user. - * This connection is automatically granted and persisted after a reboot. - * - * <p>The designated package should declare a {@link android.net.VpnService} in its - * manifest guarded by {@link android.Manifest.permission#BIND_VPN_SERVICE}, - * otherwise the call will fail. - * - * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} - * to remove an existing always-on VPN configuration. + * specific application for the current user. This connection is automatically granted and + * persisted after a reboot. + * <p> + * The designated package should declare a {@link android.net.VpnService} in its manifest + * guarded by {@link android.Manifest.permission#BIND_VPN_SERVICE}, otherwise the call will + * fail. * - * @return {@code true} if the package is set as always-on VPN controller; - * {@code false} otherwise. + * @param vpnPackage The package name for an installed VPN app on the device, or {@code null} to + * remove an existing always-on VPN configuration. + * @return {@code true} if the package is set as always-on VPN controller; {@code false} + * otherwise. + * @throws SecurityException if {@code admin} is not a device or a profile owner. */ public boolean setAlwaysOnVpnPackage(@NonNull ComponentName admin, @Nullable String vpnPackage) { @@ -2912,12 +2931,12 @@ public class DevicePolicyManager { /** * Called by a device or profile owner to read the name of the package administering an - * always-on VPN connection for the current user. - * If there is no such package, or the always-on VPN is provided by the system instead - * of by an application, {@code null} will be returned. + * always-on VPN connection for the current user. If there is no such package, or the always-on + * VPN is provided by the system instead of by an application, {@code null} will be returned. * - * @return Package name of VPN controller responsible for always-on VPN, - * or {@code null} if none is set. + * @return Package name of VPN controller responsible for always-on VPN, or {@code null} if none + * is set. + * @throws SecurityException if {@code admin} is not a device or a profile owner. */ public String getAlwaysOnVpnPackage(@NonNull ComponentName admin) { if (mService != null) { @@ -2931,18 +2950,20 @@ public class DevicePolicyManager { } /** - * Called by an application that is administering the device to disable all cameras - * on the device, for this user. After setting this, no applications running as this user - * will be able to access any cameras on the device. - * - * <p>If the caller is device owner, then the restriction will be applied to all users. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call - * this method; if it has not, a security exception will be thrown. + * Called by an application that is administering the device to disable all cameras on the + * device, for this user. After setting this, no applications running as this user will be able + * to access any cameras on the device. + * <p> + * If the caller is device owner, then the restriction will be applied to all users. + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA} to be able to call this method; if it has + * not, a security exception will be thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled Whether or not the camera should be disabled. + * @throws SecurityException if {@code admin} is not an active administrator or does not use + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}. */ public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) { if (mService != null) { @@ -2978,14 +2999,16 @@ public class DevicePolicyManager { /** * Called by a device owner to request a bugreport. - * - * <p>There must be only one user on the device, managed by the device owner. - * Otherwise a {@link SecurityException} will be thrown. + * <p> + * There must be only one user on the device, managed by the device owner. Otherwise a + * {@link SecurityException} will be thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @return {@code true} if the bugreport collection started successfully, or {@code false} - * if it wasn't triggered because a previous bugreport operation is still active - * (either the bugreport is still running or waiting for the user to share or decline) + * @return {@code true} if the bugreport collection started successfully, or {@code false} if it + * wasn't triggered because a previous bugreport operation is still active (either the + * bugreport is still running or waiting for the user to share or decline) + * @throws SecurityException if {@code admin} is not a device owner, or if there are users other + * than the one managed by the device owner. */ public boolean requestBugreport(@NonNull ComponentName admin) { if (mService != null) { @@ -3014,15 +3037,16 @@ public class DevicePolicyManager { * screen capture also prevents the content from being shown on display devices that do not have * a secure video output. See {@link android.view.Display#FLAG_SECURE} for more details about * secure surfaces and secure displays. - * - * <p>The calling device admin must be a device or profile owner. If it is not, a - * security exception will be thrown. - * - * <p>From version {@link android.os.Build.VERSION_CODES#M} disabling screen capture also - * blocks assist requests for all activities of the relevant user. + * <p> + * The calling device admin must be a device or profile owner. If it is not, a security + * exception will be thrown. + * <p> + * From version {@link android.os.Build.VERSION_CODES#M} disabling screen capture also blocks + * assist requests for all activities of the relevant user. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled Whether screen capture is disabled or not. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) { if (mService != null) { @@ -3057,16 +3081,17 @@ public class DevicePolicyManager { } /** - * Called by a device owner to set whether auto time is required. If auto time is - * required the user cannot set the date and time, but has to use network date and time. - * - * <p>Note: if auto time is required the user can still manually set the time zone. - * - * <p>The calling device admin must be a device owner. If it is not, a security exception will - * be thrown. + * Called by a device owner to set whether auto time is required. If auto time is required the + * user cannot set the date and time, but has to use network date and time. + * <p> + * Note: if auto time is required the user can still manually set the time zone. + * <p> + * The calling device admin must be a device owner. If it is not, a security exception will be + * thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param required Whether auto time is set required or not. + * @throws SecurityException if {@code admin} is not a device owner. */ public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) { if (mService != null) { @@ -3094,15 +3119,16 @@ public class DevicePolicyManager { /** * Called by a device owner to set whether all users created on the device should be ephemeral. - * - * <p>The system user is exempt from this policy - it is never ephemeral. - * - * <p>The calling device admin must be the device owner. If it is not, a security exception will - * be thrown. + * <p> + * The system user is exempt from this policy - it is never ephemeral. + * <p> + * The calling device admin must be the device owner. If it is not, a security exception will be + * thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param forceEphemeralUsers If true, all the existing users will be deleted and all - * subsequently created users will be ephemeral. + * subsequently created users will be ephemeral. + * @throws SecurityException if {@code admin} is not a device owner. * @hide */ public void setForceEphemeralUsers( @@ -3118,6 +3144,7 @@ public class DevicePolicyManager { /** * @return true if all users are created ephemeral. + * @throws SecurityException if {@code admin} is not a device owner. * @hide */ public boolean getForceEphemeralUsers(@NonNull ComponentName admin) { @@ -3135,39 +3162,41 @@ public class DevicePolicyManager { * Called by an application that is administering the device to disable keyguard customizations, * such as widgets. After setting this, keyguard features will be disabled according to the * provided feature list. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call - * this method; if it has not, a security exception will be thrown. - * - * <p>Calling this from a managed profile before version - * {@link android.os.Build.VERSION_CODES#M} will throw a security exception. From version - * {@link android.os.Build.VERSION_CODES#M} the profile owner of a managed profile can set: + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method; + * if it has not, a security exception will be thrown. + * <p> + * Calling this from a managed profile before version {@link android.os.Build.VERSION_CODES#M} + * will throw a security exception. From version {@link android.os.Build.VERSION_CODES#M} the + * profile owner of a managed profile can set: * <ul> * <li>{@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which affects the parent user, but only if there - * is no separate challenge set on the managed profile. + * is no separate challenge set on the managed profile. * <li>{@link #KEYGUARD_DISABLE_FINGERPRINT} which affects the managed profile challenge if - * there is one, or the parent user otherwise. - * <li>{@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS} which affects notifications - * generated by applications in the managed profile. + * there is one, or the parent user otherwise. + * <li>{@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS} which affects notifications generated + * by applications in the managed profile. * </ul> - * * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} and {@link #KEYGUARD_DISABLE_FINGERPRINT} can also be * set on the {@link DevicePolicyManager} instance returned by - * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the - * parent profile. - * - * <p>Requests to disable other features on a managed profile will be ignored. - * - * <p>The admin can check which features have been disabled by calling + * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent + * profile. + * <p> + * Requests to disable other features on a managed profile will be ignored. + * <p> + * The admin can check which features have been disabled by calling * {@link #getKeyguardDisabledFeatures(ComponentName)} * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param which {@link #KEYGUARD_DISABLE_FEATURES_NONE} (default), - * {@link #KEYGUARD_DISABLE_WIDGETS_ALL}, {@link #KEYGUARD_DISABLE_SECURE_CAMERA}, - * {@link #KEYGUARD_DISABLE_SECURE_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, - * {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_FINGERPRINT}, - * {@link #KEYGUARD_DISABLE_FEATURES_ALL} + * {@link #KEYGUARD_DISABLE_WIDGETS_ALL}, {@link #KEYGUARD_DISABLE_SECURE_CAMERA}, + * {@link #KEYGUARD_DISABLE_SECURE_NOTIFICATIONS}, + * {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, + * {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, + * {@link #KEYGUARD_DISABLE_FINGERPRINT}, {@link #KEYGUARD_DISABLE_FEATURES_ALL} + * @throws SecurityException if {@code admin} is not an active administrator or does not user + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} */ public void setKeyguardDisabledFeatures(@NonNull ComponentName admin, int which) { if (mService != null) { @@ -3494,13 +3523,13 @@ public class DevicePolicyManager { } /** - * Clears the current device owner. The caller must be the device owner. - * - * This function should be used cautiously as once it is called it cannot - * be undone. The device owner can only be set as a part of device setup - * before setup completes. + * Clears the current device owner. The caller must be the device owner. This function should be + * used cautiously as once it is called it cannot be undone. The device owner can only be set as + * a part of device setup before setup completes. * * @param packageName The package name of the device owner. + * @throws SecurityException if the caller is not in {@code packageName} or {@code packageName} + * does not own the current device owner component. */ public void clearDeviceOwnerApp(String packageName) { if (mService != null) { @@ -3610,13 +3639,14 @@ public class DevicePolicyManager { } /** - * Clears the active profile owner and removes all user restrictions. The caller must - * be from the same package as the active profile owner for this user, otherwise a - * SecurityException will be thrown. - * - * <p>This doesn't work for managed profile owners. + * Clears the active profile owner and removes all user restrictions. The caller must be from + * the same package as the active profile owner for this user, otherwise a SecurityException + * will be thrown. + * <p> + * This doesn't work for managed profile owners. * * @param admin The component to remove as the profile owner. + * @throws SecurityException if {@code admin} is not an active profile owner. */ public void clearProfileOwner(@NonNull ComponentName admin) { if (mService != null) { @@ -3676,20 +3706,21 @@ public class DevicePolicyManager { /** * Sets the device owner information to be shown on the lock screen. - * - * <p>If the device owner information is {@code null} or empty then the device owner info is + * <p> + * If the device owner information is {@code null} or empty then the device owner info is * cleared and the user owner info is shown on the lock screen if it is set. - * <p>If the device owner information contains only whitespaces then the message on the lock - * screen will be blank and the user will not be allowed to change it. - * - * <p>If the device owner information needs to be localized, it is the responsibility of the + * <p> + * If the device owner information contains only whitespaces then the message on the lock screen + * will be blank and the user will not be allowed to change it. + * <p> + * If the device owner information needs to be localized, it is the responsibility of the * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast * and set a new version of this string accordingly. * * @param admin The name of the admin component to check. - * @param info Device owner information which will be displayed instead of the user - * owner info. + * @param info Device owner information which will be displayed instead of the user owner info. * @return Whether the device owner information has been set. + * @throws SecurityException if {@code admin} is not a device owner. */ public boolean setDeviceOwnerLockScreenInfo(@NonNull ComponentName admin, String info) { if (mService != null) { @@ -3718,21 +3749,22 @@ public class DevicePolicyManager { /** * Called by device or profile owners to suspend packages for this user. - * - * <p>A suspended package will not be able to start activities. Its notifications will - * be hidden, it will not show up in recents, will not be able to show toasts or dialogs - * or ring the device. - * - * <p>The package must already be installed. If the package is uninstalled while suspended - * the package will no longer be suspended. The admin can block this by using + * <p> + * A suspended package will not be able to start activities. Its notifications will be hidden, + * it will not show up in recents, will not be able to show toasts or dialogs or ring the + * device. + * <p> + * The package must already be installed. If the package is uninstalled while suspended the + * package will no longer be suspended. The admin can block this by using * {@link #setUninstallBlocked}. * * @param admin The name of the admin component to check. * @param packageNames The package names to suspend or unsuspend. * @param suspended If set to {@code true} than the packages will be suspended, if set to - * {@code false} the packages will be unsuspended. + * {@code false} the packages will be unsuspended. * @return an array of package names for which the suspended status is not set as requested in - * this method. + * this method. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public String[] setPackagesSuspended(@NonNull ComponentName admin, String[] packageNames, boolean suspended) { @@ -3752,7 +3784,8 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The name of the package to retrieve the suspended status of. * @return {@code true} if the package is suspended or {@code false} if the package is not - * suspended, could not be found or an error occurred. + * suspended, could not be found or an error occurred. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean getPackageSuspended(@NonNull ComponentName admin, String packageName) { if (mService != null) { @@ -3770,8 +3803,8 @@ public class DevicePolicyManager { * be used. Only the profile owner can call this. * * @see #isProfileOwnerApp - * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @throws SecurityException if {@code admin} is not a profile owner. */ public void setProfileEnabled(@NonNull ComponentName admin) { if (mService != null) { @@ -3784,15 +3817,15 @@ public class DevicePolicyManager { } /** - * Sets the name of the profile. In the device owner case it sets the name of the user - * which it is called from. Only a profile owner or device owner can call this. If this is - * never called by the profile or device owner, the name will be set to default values. + * Sets the name of the profile. In the device owner case it sets the name of the user which it + * is called from. Only a profile owner or device owner can call this. If this is never called + * by the profile or device owner, the name will be set to default values. * * @see #isProfileOwnerApp * @see #isDeviceOwnerApp - * * @param admin Which {@link DeviceAdminReceiver} this request is associate with. * @param profileName The name of the profile. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setProfileName(@NonNull ComponentName admin, String profileName) { if (mService != null) { @@ -3890,19 +3923,20 @@ public class DevicePolicyManager { /** * Called by a profile owner or device owner to add a default intent handler activity for * intents that match a certain intent filter. This activity will remain the default intent - * handler even if the set of potential event handlers for the intent filter changes and if - * the intent preferences are reset. - * - * <p>The default disambiguation mechanism takes over if the activity is not installed - * (anymore). When the activity is (re)installed, it is automatically reset as default - * intent handler for the filter. - * - * <p>The calling device admin must be a profile owner or device owner. If it is not, a - * security exception will be thrown. + * handler even if the set of potential event handlers for the intent filter changes and if the + * intent preferences are reset. + * <p> + * The default disambiguation mechanism takes over if the activity is not installed (anymore). + * When the activity is (re)installed, it is automatically reset as default intent handler for + * the filter. + * <p> + * The calling device admin must be a profile owner or device owner. If it is not, a security + * exception will be thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param filter The IntentFilter for which a default handler is added. * @param activity The Activity that is added as default intent handler. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter, @NonNull ComponentName activity) { @@ -3918,12 +3952,13 @@ public class DevicePolicyManager { /** * Called by a profile owner or device owner to remove all persistent intent handler preferences * associated with the given package that were set by {@link #addPersistentPreferredActivity}. - * - * <p>The calling device admin must be a profile owner. If it is not, a security - * exception will be thrown. + * <p> + * The calling device admin must be a profile owner. If it is not, a security exception will be + * thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The name of the package for which preferences are removed. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin, String packageName) { @@ -3949,7 +3984,8 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The package name which will be given access to application restrictions - * APIs. If {@code null} is given the current package will be cleared. + * APIs. If {@code null} is given the current package will be cleared. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setApplicationRestrictionsManagingPackage(@NonNull ComponentName admin, @Nullable String packageName) { @@ -3968,7 +4004,8 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return The package name allowed to manage application restrictions on the current user, or - * {@code null} if none is set. + * {@code null} if none is set. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public String getApplicationRestrictionsManagingPackage(@NonNull ComponentName admin) { if (mService != null) { @@ -3982,9 +4019,12 @@ public class DevicePolicyManager { } /** - * Returns {@code true} if the calling package has been granted permission via - * {@link #setApplicationRestrictionsManagingPackage} to manage application - * restrictions for the calling user. + * Called by any application to find out whether it has been granted permission via + * {@link #setApplicationRestrictionsManagingPackage} to manage application restrictions + * for the calling user. + * + * <p>This is done by comparing the calling Linux uid with the uid of the package specified by + * that method. */ public boolean isCallerApplicationRestrictionsManagingPackage() { if (mService != null) { @@ -3999,34 +4039,34 @@ public class DevicePolicyManager { /** * Sets the application restrictions for a given target application running in the calling user. - * - * <p>The caller must be a profile or device owner on that user, or the package allowed to - * manage application restrictions via {@link #setApplicationRestrictionsManagingPackage}; - * otherwise a security exception will be thrown. - * - * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be: + * <p> + * The caller must be a profile or device owner on that user, or the package allowed to manage + * application restrictions via {@link #setApplicationRestrictionsManagingPackage}; otherwise a + * security exception will be thrown. + * <p> + * The provided {@link Bundle} consists of key-value pairs, where the types of values may be: * <ul> * <li>{@code boolean} * <li>{@code int} * <li>{@code String} or {@code String[]} * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]} * </ul> - * - * <p>If the restrictions are not available yet, but may be applied in the near future, - * the caller can notify the target application of that by adding + * <p> + * If the restrictions are not available yet, but may be applied in the near future, the caller + * can notify the target application of that by adding * {@link UserManager#KEY_RESTRICTIONS_PENDING} to the settings parameter. - * - * <p>The application restrictions are only made visible to the target application via - * {@link UserManager#getApplicationRestrictions(String)}, in addition to the profile or - * device owner, and the application restrictions managing package via + * <p> + * The application restrictions are only made visible to the target application via + * {@link UserManager#getApplicationRestrictions(String)}, in addition to the profile or device + * owner, and the application restrictions managing package via * {@link #getApplicationRestrictions}. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or - * {@code null} if called by the application restrictions managing package. + * {@code null} if called by the application restrictions managing package. * @param packageName The name of the package to update restricted settings for. * @param settings A {@link Bundle} to be parsed by the receiving application, conveying a new - * set of active restrictions. - * + * set of active restrictions. + * @throws SecurityException if {@code admin} is not a device or profile owner. * @see #setApplicationRestrictionsManagingPackage * @see UserManager#KEY_RESTRICTIONS_PENDING */ @@ -4042,23 +4082,29 @@ public class DevicePolicyManager { } /** - * Sets a list of configuration features to enable for a TrustAgent component. This is meant - * to be used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which disables all - * trust agents but those enabled by this function call. If flag + * Sets a list of configuration features to enable for a TrustAgent component. This is meant to + * be used in conjunction with {@link #KEYGUARD_DISABLE_TRUST_AGENTS}, which disables all trust + * agents but those enabled by this function call. If flag * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is not set, then this call has no effect. - * - * <p>The calling device admin must have requested - * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call - * this method; if not, a security exception will be thrown. + * <p> + * The calling device admin must have requested + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} to be able to call this method; + * if not, a security exception will be thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param target Component name of the agent to be enabled. - * @param configuration TrustAgent-specific feature bundle. If null for any admin, agent - * will be strictly disabled according to the state of the - * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} flag. - * <p>If {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is set and options is not null for all admins, - * then it's up to the TrustAgent itself to aggregate the values from all device admins. - * <p>Consult documentation for the specific TrustAgent to determine legal options parameters. + * @param configuration TrustAgent-specific feature bundle. If null for any admin, agent will be + * strictly disabled according to the state of the + * {@link #KEYGUARD_DISABLE_TRUST_AGENTS} flag. + * <p> + * If {@link #KEYGUARD_DISABLE_TRUST_AGENTS} is set and options is not null for all + * admins, then it's up to the TrustAgent itself to aggregate the values from all + * device admins. + * <p> + * Consult documentation for the specific TrustAgent to determine legal options + * parameters. + * @throws SecurityException if {@code admin} is not an active administrator or does not use + * {@link DeviceAdminInfo#USES_POLICY_DISABLE_KEYGUARD_FEATURES} */ public void setTrustAgentConfiguration(@NonNull ComponentName admin, @NonNull ComponentName target, PersistableBundle configuration) { @@ -4104,14 +4150,15 @@ public class DevicePolicyManager { } /** - * Called by a profile owner of a managed profile to set whether caller-Id information from - * the managed profile will be shown in the parent profile, for incoming calls. - * - * <p>The calling device admin must be a profile owner. If it is not, a - * security exception will be thrown. + * Called by a profile owner of a managed profile to set whether caller-Id information from the + * managed profile will be shown in the parent profile, for incoming calls. + * <p> + * The calling device admin must be a profile owner. If it is not, a security exception will be + * thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled If true caller-Id information in the managed profile is not displayed. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) { if (mService != null) { @@ -4126,11 +4173,12 @@ public class DevicePolicyManager { /** * Called by a profile owner of a managed profile to determine whether or not caller-Id * information has been disabled. - * - * <p>The calling device admin must be a profile owner. If it is not, a - * security exception will be thrown. + * <p> + * The calling device admin must be a profile owner. If it is not, a security exception will be + * thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) { if (mService != null) { @@ -4161,14 +4209,15 @@ public class DevicePolicyManager { } /** - * Called by a profile owner of a managed profile to set whether contacts search from - * the managed profile will be shown in the parent profile, for incoming calls. - * - * <p>The calling device admin must be a profile owner. If it is not, a - * security exception will be thrown. + * Called by a profile owner of a managed profile to set whether contacts search from the + * managed profile will be shown in the parent profile, for incoming calls. + * <p> + * The calling device admin must be a profile owner. If it is not, a security exception will be + * thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled If true contacts search in the managed profile is not displayed. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setCrossProfileContactsSearchDisabled(@NonNull ComponentName admin, boolean disabled) { @@ -4184,11 +4233,12 @@ public class DevicePolicyManager { /** * Called by a profile owner of a managed profile to determine whether or not contacts search * has been disabled. - * - * <p>The calling device admin must be a profile owner. If it is not, a - * security exception will be thrown. + * <p> + * The calling device admin must be a profile owner. If it is not, a security exception will be + * thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean getCrossProfileContactsSearchDisabled(@NonNull ComponentName admin) { if (mService != null) { @@ -4248,18 +4298,17 @@ public class DevicePolicyManager { } /** - * Called by a profile owner of a managed profile to set whether bluetooth - * devices can access enterprise contacts. + * Called by a profile owner of a managed profile to set whether bluetooth devices can access + * enterprise contacts. * <p> - * The calling device admin must be a profile owner. If it is not, a - * security exception will be thrown. + * The calling device admin must be a profile owner. If it is not, a security exception will be + * thrown. * <p> * This API works on managed profile only. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param disabled If true, bluetooth devices cannot access enterprise - * contacts. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param disabled If true, bluetooth devices cannot access enterprise contacts. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) { if (mService != null) { @@ -4272,16 +4321,16 @@ public class DevicePolicyManager { } /** - * Called by a profile owner of a managed profile to determine whether or - * not Bluetooth devices cannot access enterprise contacts. + * Called by a profile owner of a managed profile to determine whether or not Bluetooth devices + * cannot access enterprise contacts. * <p> - * The calling device admin must be a profile owner. If it is not, a - * security exception will be thrown. + * The calling device admin must be a profile owner. If it is not, a security exception will be + * thrown. * <p> * This API works on managed profile only. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) { if (mService != null) { @@ -4316,14 +4365,15 @@ public class DevicePolicyManager { /** * Called by the profile owner of a managed profile so that some intents sent in the managed - * profile can also be resolved in the parent, or vice versa. - * Only activity intents are supported. + * profile can also be resolved in the parent, or vice versa. Only activity intents are + * supported. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param filter The {@link IntentFilter} the intent has to match to be also resolved in the - * other profile + * other profile * @param flags {@link DevicePolicyManager#FLAG_MANAGED_CAN_ACCESS_PARENT} and - * {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported. + * {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void addCrossProfileIntentFilter(@NonNull ComponentName admin, IntentFilter filter, int flags) { if (mService != null) { @@ -4339,7 +4389,9 @@ public class DevicePolicyManager { * Called by a profile owner of a managed profile to remove the cross-profile intent filters * that go from the managed profile to the parent, or from the parent to the managed profile. * Only removes those that have been set by the profile owner. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) { if (mService != null) { @@ -4352,25 +4404,22 @@ public class DevicePolicyManager { } /** - * Called by a profile or device owner to set the permitted accessibility services. When - * set by a device owner or profile owner the restriction applies to all profiles of the - * user the device owner or profile owner is an admin for. - * - * By default the user can use any accessiblity service. When zero or more packages have - * been added, accessiblity services that are not in the list and not part of the system - * can not be enabled by the user. - * - * <p> Calling with a null value for the list disables the restriction so that all services - * can be used, calling with an empty list only allows the builtin system's services. - * - * <p> System accesibility services are always available to the user the list can't modify - * this. + * Called by a profile or device owner to set the permitted accessibility services. When set by + * a device owner or profile owner the restriction applies to all profiles of the user the + * device owner or profile owner is an admin for. By default the user can use any accessiblity + * service. When zero or more packages have been added, accessiblity services that are not in + * the list and not part of the system can not be enabled by the user. + * <p> + * Calling with a null value for the list disables the restriction so that all services can be + * used, calling with an empty list only allows the builtin system's services. + * <p> + * System accesibility services are always available to the user the list can't modify this. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageNames List of accessibility service package names. - * - * @return true if setting the restriction succeeded. It fail if there is - * one or more non-system accessibility services enabled, that are not in the list. + * @return true if setting the restriction succeeded. It fail if there is one or more non-system + * accessibility services enabled, that are not in the list. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin, List<String> packageNames) { @@ -4386,12 +4435,13 @@ public class DevicePolicyManager { /** * Returns the list of permitted accessibility services set by this device or profile owner. - * - * <p>An empty list means no accessibility services except system services are allowed. - * Null means all accessibility services are allowed. + * <p> + * An empty list means no accessibility services except system services are allowed. Null means + * all accessibility services are allowed. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return List of accessiblity service package names. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) { if (mService != null) { @@ -4452,27 +4502,23 @@ public class DevicePolicyManager { } /** - * Called by a profile or device owner to set the permitted input methods services. When - * set by a device owner or profile owner the restriction applies to all profiles of the - * user the device owner or profile owner is an admin for. - * - * By default the user can use any input method. When zero or more packages have - * been added, input method that are not in the list and not part of the system - * can not be enabled by the user. - * - * This method will fail if it is called for a admin that is not for the foreground user - * or a profile of the foreground user. - * - * <p> Calling with a null value for the list disables the restriction so that all input methods - * can be used, calling with an empty list disables all but the system's own input methods. - * - * <p> System input methods are always available to the user this method can't modify this. + * Called by a profile or device owner to set the permitted input methods services. When set by + * a device owner or profile owner the restriction applies to all profiles of the user the + * device owner or profile owner is an admin for. By default the user can use any input method. + * When zero or more packages have been added, input method that are not in the list and not + * part of the system can not be enabled by the user. This method will fail if it is called for + * a admin that is not for the foreground user or a profile of the foreground user. + * <p> + * Calling with a null value for the list disables the restriction so that all input methods can + * be used, calling with an empty list disables all but the system's own input methods. + * <p> + * System input methods are always available to the user this method can't modify this. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageNames List of input method package names. - * @return true if setting the restriction succeeded. It will fail if there are - * one or more non-system input methods currently enabled that are not in - * the packageNames list. + * @return true if setting the restriction succeeded. It will fail if there are one or more + * non-system input methods currently enabled that are not in the packageNames list. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean setPermittedInputMethods(@NonNull ComponentName admin, List<String> packageNames) { if (mService != null) { @@ -4488,12 +4534,13 @@ public class DevicePolicyManager { /** * Returns the list of permitted input methods set by this device or profile owner. - * - * <p>An empty list means no input methods except system input methods are allowed. - * Null means all input methods are allowed. + * <p> + * An empty list means no input methods except system input methods are allowed. Null means all + * input methods are allowed. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return List of input method package names. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public List<String> getPermittedInputMethods(@NonNull ComponentName admin) { if (mService != null) { @@ -4580,6 +4627,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageNames List of package names to keep cached. + * @throws SecurityException if {@code admin} is not a device owner. * @hide */ public void setKeepUninstalledPackages(@NonNull ComponentName admin, @@ -4665,27 +4713,27 @@ public class DevicePolicyManager { * persisted as user handles are recycled as users are removed and created. If you need to * persist an identifier for this user, use {@link UserManager#getSerialNumberForUser}. The new * user will not be started in the background. - * - * <p>admin is the {@link DeviceAdminReceiver} which is the device owner. profileOwner is also - * a DeviceAdminReceiver in the same package as admin, and will become the profile owner and - * will be registered as an active admin on the new user. The profile owner package will be - * installed on the new user. - * - * <p>If the adminExtras are not null, they will be stored on the device until the user is - * started for the first time. Then the extras will be passed to the admin when - * onEnable is called. + * <p> + * admin is the {@link DeviceAdminReceiver} which is the device owner. profileOwner is also a + * DeviceAdminReceiver in the same package as admin, and will become the profile owner and will + * be registered as an active admin on the new user. The profile owner package will be installed + * on the new user. + * <p> + * If the adminExtras are not null, they will be stored on the device until the user is started + * for the first time. Then the extras will be passed to the admin when onEnable is called. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param name The user's name. * @param profileOwner Which {@link DeviceAdminReceiver} will be profile owner. Has to be in the - * same package as admin, otherwise no user is created and an IllegalArgumentException is - * thrown. + * same package as admin, otherwise no user is created and an + * IllegalArgumentException is thrown. * @param adminExtras Extras that will be passed to onEnable of the admin receiver on the new - * user. + * user. * @param flags {@link #SKIP_SETUP_WIZARD} is supported. * @see UserHandle * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the * user could not be created. + * @throws SecurityException if {@code admin} is not a device owner. */ public UserHandle createAndManageUser(@NonNull ComponentName admin, @NonNull String name, @NonNull ComponentName profileOwner, @Nullable PersistableBundle adminExtras, @@ -4698,12 +4746,13 @@ public class DevicePolicyManager { } /** - * Called by a device owner to remove a user and all associated data. The primary user can - * not be removed. + * Called by a device owner to remove a user and all associated data. The primary user can not + * be removed. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param userHandle the user to remove. * @return {@code true} if the user was removed, {@code false} otherwise. + * @throws SecurityException if {@code admin} is not a device owner. */ public boolean removeUser(@NonNull ComponentName admin, UserHandle userHandle) { try { @@ -4719,7 +4768,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param userHandle the user to switch to; null will switch to primary. * @return {@code true} if the switch was successful, {@code false} otherwise. - * + * @throws SecurityException if {@code admin} is not a device owner. * @see Intent#ACTION_USER_FOREGROUND */ public boolean switchUser(@NonNull ComponentName admin, @Nullable UserHandle userHandle) { @@ -4733,18 +4782,18 @@ public class DevicePolicyManager { /** * Retrieves the application restrictions for a given target application running in the calling * user. - * - * <p>The caller must be a profile or device owner on that user, or the package allowed to - * manage application restrictions via {@link #setApplicationRestrictionsManagingPackage}; - * otherwise a security exception will be thrown. + * <p> + * The caller must be a profile or device owner on that user, or the package allowed to manage + * application restrictions via {@link #setApplicationRestrictionsManagingPackage}; otherwise a + * security exception will be thrown. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or - * {@code null} if called by the application restrictions managing package. + * {@code null} if called by the application restrictions managing package. * @param packageName The name of the package to fetch restricted settings of. * @return {@link Bundle} of settings corresponding to what was set last time - * {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty {@link Bundle} - * if no restrictions have been set. - * + * {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty + * {@link Bundle} if no restrictions have been set. + * @throws SecurityException if {@code admin} is not a device or profile owner. * @see {@link #setApplicationRestrictionsManagingPackage} */ public Bundle getApplicationRestrictions(@Nullable ComponentName admin, String packageName) { @@ -4761,13 +4810,13 @@ public class DevicePolicyManager { /** * Called by a profile or device owner to set a user restriction specified by the key. * <p> - * The calling device admin must be a profile or device owner; if it is not, - * a security exception will be thrown. + * The calling device admin must be a profile or device owner; if it is not, a security + * exception will be thrown. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param key The key of the restriction. See the constants in - * {@link android.os.UserManager} for the list of keys. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param key The key of the restriction. See the constants in {@link android.os.UserManager} + * for the list of keys. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void addUserRestriction(@NonNull ComponentName admin, String key) { if (mService != null) { @@ -4782,13 +4831,13 @@ public class DevicePolicyManager { /** * Called by a profile or device owner to clear a user restriction specified by the key. * <p> - * The calling device admin must be a profile or device owner; if it is not, - * a security exception will be thrown. + * The calling device admin must be a profile or device owner; if it is not, a security + * exception will be thrown. * - * @param admin Which {@link DeviceAdminReceiver} this request is associated - * with. - * @param key The key of the restriction. See the constants in - * {@link android.os.UserManager} for the list of keys. + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param key The key of the restriction. See the constants in {@link android.os.UserManager} + * for the list of keys. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void clearUserRestriction(@NonNull ComponentName admin, String key) { if (mService != null) { @@ -4805,11 +4854,11 @@ public class DevicePolicyManager { * {@link #addUserRestriction(ComponentName, String)}. * <p> * The target user may have more restrictions set by the system or other device owner / profile - * owner. To get all the user restrictions currently set, use + * owner. To get all the user restrictions currently set, use * {@link UserManager#getUserRestrictions()}. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @throws SecurityException if the {@code admin} is not an active admin. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public Bundle getUserRestrictions(@NonNull ComponentName admin) { return getUserRestrictions(admin, myUserId()); @@ -4829,14 +4878,15 @@ public class DevicePolicyManager { } /** - * Called by profile or device owners to hide or unhide packages. When a package is hidden it - * is unavailable for use, but the data and actual package file remain. + * Called by profile or device owners to hide or unhide packages. When a package is hidden it is + * unavailable for use, but the data and actual package file remain. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The name of the package to hide or unhide. * @param hidden {@code true} if the package should be hidden, {@code false} if it should be - * unhidden. + * unhidden. * @return boolean Whether the hidden setting of the package was successfully updated. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName, boolean hidden) { @@ -4856,6 +4906,7 @@ public class DevicePolicyManager { * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The name of the package to retrieve the hidden status of. * @return boolean {@code true} if the package is hidden, {@code false} otherwise. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) { if (mService != null) { @@ -4874,6 +4925,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The package to be re-enabled in the calling profile. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void enableSystemApp(@NonNull ComponentName admin, String packageName) { if (mService != null) { @@ -4886,13 +4938,14 @@ public class DevicePolicyManager { } /** - * Called by profile or device owners to re-enable system apps by intent that were disabled - * by default when the user was initialized. + * Called by profile or device owners to re-enable system apps by intent that were disabled by + * default when the user was initialized. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param intent An intent matching the app(s) to be installed. All apps that resolve for this - * intent will be re-enabled in the calling profile. + * intent will be re-enabled in the calling profile. * @return int The number of activities that matched the intent and were installed. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public int enableSystemApp(@NonNull ComponentName admin, Intent intent) { if (mService != null) { @@ -4908,21 +4961,22 @@ public class DevicePolicyManager { /** * Called by a device owner or profile owner to disable account management for a specific type * of account. - * - * <p>The calling device admin must be a device owner or profile owner. If it is not, a - * security exception will be thrown. - * - * <p>When account management is disabled for an account type, adding or removing an account - * of that type will not be possible. - * - * <p>From {@link android.os.Build.VERSION_CODES#N} the profile or device owner can still use + * <p> + * The calling device admin must be a device owner or profile owner. If it is not, a security + * exception will be thrown. + * <p> + * When account management is disabled for an account type, adding or removing an account of + * that type will not be possible. + * <p> + * From {@link android.os.Build.VERSION_CODES#N} the profile or device owner can still use * {@link android.accounts.AccountManager} APIs to add or remove accounts when account * management for a specific type is disabled. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param accountType For which account management is disabled or enabled. * @param disabled The boolean indicating that account management will be disabled (true) or - * enabled (false). + * enabled (false). + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType, boolean disabled) { @@ -4967,17 +5021,15 @@ public class DevicePolicyManager { /** * Sets which packages may enter lock task mode. + * <p> + * Any packages that shares uid with an allowed package will also be allowed to activate lock + * task. From {@link android.os.Build.VERSION_CODES#M} removing packages from the lock task + * package list results in locked tasks belonging to those packages to be finished. This + * function can only be called by the device owner. * - * <p>Any packages that shares uid with an allowed package will also be allowed - * to activate lock task. - * - * From {@link android.os.Build.VERSION_CODES#M} removing packages from the lock task - * package list results in locked tasks belonging to those packages to be finished. - * - * This function can only be called by the device owner. * @param packages The list of packages allowed to enter lock task mode * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * + * @throws SecurityException if {@code admin} is not a device owner. * @see Activity#startLockTask() * @see DeviceAdminReceiver#onLockTaskModeEntering(Context, Intent, String) * @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent) @@ -5030,7 +5082,8 @@ public class DevicePolicyManager { /** * Called by device owners to update {@link Settings.Global} settings. Validation that the value * of the setting is in the correct form for the setting type should be performed by the caller. - * <p>The settings that can be updated with this method are: + * <p> + * The settings that can be updated with this method are: * <ul> * <li>{@link Settings.Global#ADB_ENABLED}</li> * <li>{@link Settings.Global#AUTO_TIME}</li> @@ -5038,30 +5091,30 @@ public class DevicePolicyManager { * <li>{@link Settings.Global#DATA_ROAMING}</li> * <li>{@link Settings.Global#USB_MASS_STORAGE_ENABLED}</li> * <li>{@link Settings.Global#WIFI_SLEEP_POLICY}</li> - * <li>{@link Settings.Global#STAY_ON_WHILE_PLUGGED_IN} - * This setting is only available from {@link android.os.Build.VERSION_CODES#M} onwards - * and can only be set if {@link #setMaximumTimeToLock} is not used to set a timeout.</li> - * <li>{@link Settings.Global#WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN}</li> - * This setting is only available from {@link android.os.Build.VERSION_CODES#M} onwards. - * </li> + * <li>{@link Settings.Global#STAY_ON_WHILE_PLUGGED_IN} This setting is only available from + * {@link android.os.Build.VERSION_CODES#M} onwards and can only be set if + * {@link #setMaximumTimeToLock} is not used to set a timeout.</li> + * <li>{@link Settings.Global#WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN}</li> This setting is only + * available from {@link android.os.Build.VERSION_CODES#M} onwards.</li> * </ul> - * <p>Changing the following settings has no effect as of - * {@link android.os.Build.VERSION_CODES#M}: + * <p> + * Changing the following settings has no effect as of {@link android.os.Build.VERSION_CODES#M}: * <ul> - * <li>{@link Settings.Global#BLUETOOTH_ON}. - * Use {@link android.bluetooth.BluetoothAdapter#enable()} and - * {@link android.bluetooth.BluetoothAdapter#disable()} instead.</li> + * <li>{@link Settings.Global#BLUETOOTH_ON}. Use + * {@link android.bluetooth.BluetoothAdapter#enable()} and + * {@link android.bluetooth.BluetoothAdapter#disable()} instead.</li> * <li>{@link Settings.Global#DEVELOPMENT_SETTINGS_ENABLED}</li> - * <li>{@link Settings.Global#MODE_RINGER}. - * Use {@link android.media.AudioManager#setRingerMode(int)} instead.</li> + * <li>{@link Settings.Global#MODE_RINGER}. Use + * {@link android.media.AudioManager#setRingerMode(int)} instead.</li> * <li>{@link Settings.Global#NETWORK_PREFERENCE}</li> - * <li>{@link Settings.Global#WIFI_ON}. - * Use {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} instead.</li> + * <li>{@link Settings.Global#WIFI_ON}. Use + * {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} instead.</li> * </ul> * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param setting The name of the setting to update. * @param value The value to update the setting to. + * @throws SecurityException if {@code admin} is not a device owner. */ public void setGlobalSetting(@NonNull ComponentName admin, String setting, String value) { if (mService != null) { @@ -5077,19 +5130,23 @@ public class DevicePolicyManager { * Called by profile or device owners to update {@link Settings.Secure} settings. Validation * that the value of the setting is in the correct form for the setting type should be performed * by the caller. - * <p>The settings that can be updated by a profile or device owner with this method are: + * <p> + * The settings that can be updated by a profile or device owner with this method are: * <ul> * <li>{@link Settings.Secure#DEFAULT_INPUT_METHOD}</li> * <li>{@link Settings.Secure#INSTALL_NON_MARKET_APPS}</li> * <li>{@link Settings.Secure#SKIP_FIRST_USE_HINTS}</li> * </ul> - * <p>A device owner can additionally update the following settings: + * <p> + * A device owner can additionally update the following settings: * <ul> * <li>{@link Settings.Secure#LOCATION_MODE}</li> * </ul> + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param setting The name of the setting to update. * @param value The value to update the setting to. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setSecureSetting(@NonNull ComponentName admin, String setting, String value) { if (mService != null) { @@ -5102,14 +5159,16 @@ public class DevicePolicyManager { } /** - * Designates a specific service component as the provider for - * making permission requests of a local or remote administrator of the user. + * Designates a specific service component as the provider for making permission requests of a + * local or remote administrator of the user. * <p/> * Only a profile owner can designate the restrictions provider. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param provider The component name of the service that implements - * {@link RestrictionsReceiver}. If this param is null, - * it removes the restrictions provider previously assigned. + * {@link RestrictionsReceiver}. If this param is null, it removes the restrictions + * provider previously assigned. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setRestrictionsProvider(@NonNull ComponentName admin, @Nullable ComponentName provider) { @@ -5127,6 +5186,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param on {@code true} to mute master volume, {@code false} to turn mute off. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setMasterVolumeMuted(@NonNull ComponentName admin, boolean on) { if (mService != null) { @@ -5143,6 +5203,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return {@code true} if master volume is muted, {@code false} if it's not. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean isMasterVolumeMuted(@NonNull ComponentName admin) { if (mService != null) { @@ -5156,12 +5217,12 @@ public class DevicePolicyManager { } /** - * Called by profile or device owners to change whether a user can uninstall - * a package. + * Called by profile or device owners to change whether a user can uninstall a package. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName package to change. * @param uninstallBlocked true if the user shouldn't be able to uninstall the package. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setUninstallBlocked(@NonNull ComponentName admin, String packageName, boolean uninstallBlocked) { @@ -5179,14 +5240,15 @@ public class DevicePolicyManager { * Requires the caller to be the profile owner if checking a specific admin's policy. * <p> * <strong>Note:</strong> Starting from {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}, the - * behavior of this API is changed such that passing {@code null} as the {@code admin} - * parameter will return if any admin has blocked the uninstallation. Before L MR1, passing - * {@code null} will cause a NullPointerException to be raised. + * behavior of this API is changed such that passing {@code null} as the {@code admin} parameter + * will return if any admin has blocked the uninstallation. Before L MR1, passing {@code null} + * will cause a NullPointerException to be raised. * * @param admin The name of the admin component whose blocking policy will be checked, or - * {@code null} to check whether any admin has blocked the uninstallation. + * {@code null} to check whether any admin has blocked the uninstallation. * @param packageName package to check. * @return true if uninstallation is blocked. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) { if (mService != null) { @@ -5200,19 +5262,18 @@ public class DevicePolicyManager { } /** - * Called by the profile owner of a managed profile to enable widget providers from a - * given package to be available in the parent profile. As a result the user will be able to - * add widgets from the white-listed package running under the profile to a widget - * host which runs under the parent profile, for example the home screen. Note that - * a package may have zero or more provider components, where each component - * provides a different widget type. + * Called by the profile owner of a managed profile to enable widget providers from a given + * package to be available in the parent profile. As a result the user will be able to add + * widgets from the white-listed package running under the profile to a widget host which runs + * under the parent profile, for example the home screen. Note that a package may have zero or + * more provider components, where each component provides a different widget type. * <p> * <strong>Note:</strong> By default no widget provider package is white-listed. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param packageName The package from which widget providers are white-listed. * @return Whether the package was added. - * + * @throws SecurityException if {@code admin} is not a profile owner. * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String) * @see #getCrossProfileWidgetProviders(android.content.ComponentName) */ @@ -5229,17 +5290,16 @@ public class DevicePolicyManager { /** * Called by the profile owner of a managed profile to disable widget providers from a given - * package to be available in the parent profile. For this method to take effect the - * package should have been added via {@link #addCrossProfileWidgetProvider( - * android.content.ComponentName, String)}. + * package to be available in the parent profile. For this method to take effect the package + * should have been added via + * {@link #addCrossProfileWidgetProvider( android.content.ComponentName, String)}. * <p> * <strong>Note:</strong> By default no widget provider package is white-listed. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param packageName The package from which widget providers are no longer - * white-listed. + * @param packageName The package from which widget providers are no longer white-listed. * @return Whether the package was removed. - * + * @throws SecurityException if {@code admin} is not a profile owner. * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String) * @see #getCrossProfileWidgetProviders(android.content.ComponentName) */ @@ -5261,9 +5321,9 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return The white-listed package list. - * * @see #addCrossProfileWidgetProvider(android.content.ComponentName, String) * @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String) + * @throws SecurityException if {@code admin} is not a profile owner. */ public List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) { if (mService != null) { @@ -5284,6 +5344,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param icon the bitmap to set as the photo. + * @throws SecurityException if {@code admin} is not a device or profile owner. */ public void setUserIcon(@NonNull ComponentName admin, Bitmap icon) { try { @@ -5298,10 +5359,10 @@ public class DevicePolicyManager { * {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. All - * components in the device owner package can set system update policies and the - * most recent policy takes - * effect. + * components in the device owner package can set system update policies and the most + * recent policy takes effect. * @param policy the new policy, or {@code null} to clear the current policy. + * @throws SecurityException if {@code admin} is not a device owner. * @see SystemUpdatePolicy */ public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) { @@ -5332,17 +5393,17 @@ public class DevicePolicyManager { /** * Called by a device owner to disable the keyguard altogether. - * - * <p>Setting the keyguard to disabled has the same effect as choosing "None" as the screen - * lock type. However, this call has no effect if a password, pin or pattern is currently set. - * If a password, pin or pattern is set after the keyguard was disabled, the keyguard stops - * being disabled. + * <p> + * Setting the keyguard to disabled has the same effect as choosing "None" as the screen lock + * type. However, this call has no effect if a password, pin or pattern is currently set. If a + * password, pin or pattern is set after the keyguard was disabled, the keyguard stops being + * disabled. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled {@code true} disables the keyguard, {@code false} reenables it. - * * @return {@code false} if attempting to disable the keyguard while a lock password was in - * place. {@code true} otherwise. + * place. {@code true} otherwise. + * @throws SecurityException if {@code admin} is not a device owner. */ public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) { try { @@ -5354,14 +5415,13 @@ public class DevicePolicyManager { /** * Called by device owner to disable the status bar. Disabling the status bar blocks - * notifications, quick settings and other screen overlays that allow escaping from - * a single use device. + * notifications, quick settings and other screen overlays that allow escaping from a single use + * device. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param disabled {@code true} disables the status bar, {@code false} reenables it. - * - * @return {@code false} if attempting to disable the status bar failed. - * {@code true} otherwise. + * @return {@code false} if attempting to disable the status bar failed. {@code true} otherwise. + * @throws SecurityException if {@code admin} is not a device owner. */ public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) { try { @@ -5393,19 +5453,19 @@ public class DevicePolicyManager { /** * Called by profile or device owners to set the default response for future runtime permission - * requests by applications. The policy can allow for normal operation which prompts the - * user to grant a permission, or can allow automatic granting or denying of runtime - * permission requests by an application. This also applies to new permissions declared by app - * updates. When a permission is denied or granted this way, the effect is equivalent to setting - * the permission grant state via {@link #setPermissionGrantState}. - * - * <p/>As this policy only acts on runtime permission requests, it only applies to applications + * requests by applications. The policy can allow for normal operation which prompts the user to + * grant a permission, or can allow automatic granting or denying of runtime permission requests + * by an application. This also applies to new permissions declared by app updates. When a + * permission is denied or granted this way, the effect is equivalent to setting the permission + * grant state via {@link #setPermissionGrantState}. + * <p/> + * As this policy only acts on runtime permission requests, it only applies to applications * built with a {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later. * * @param admin Which profile or device owner this request is associated with. * @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT}, - * {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}. - * + * {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}. + * @throws SecurityException if {@code admin} is not a device or profile owner. * @see #setPermissionGrantState */ public void setPermissionPolicy(@NonNull ComponentName admin, int policy) { @@ -5431,29 +5491,28 @@ public class DevicePolicyManager { } /** - * Sets the grant state of a runtime permission for a specific application. The state - * can be {@link #PERMISSION_GRANT_STATE_DEFAULT default} in which a user can manage it - * through the UI, {@link #PERMISSION_GRANT_STATE_DENIED denied}, in which the permission - * is denied and the user cannot manage it through the UI, and {@link - * #PERMISSION_GRANT_STATE_GRANTED granted} in which the permission is granted and the - * user cannot manage it through the UI. This might affect all permissions in a - * group that the runtime permission belongs to. This method can only be called + * Sets the grant state of a runtime permission for a specific application. The state can be + * {@link #PERMISSION_GRANT_STATE_DEFAULT default} in which a user can manage it through the UI, + * {@link #PERMISSION_GRANT_STATE_DENIED denied}, in which the permission is denied and the user + * cannot manage it through the UI, and {@link #PERMISSION_GRANT_STATE_GRANTED granted} in which + * the permission is granted and the user cannot manage it through the UI. This might affect all + * permissions in a group that the runtime permission belongs to. This method can only be called * by a profile or device owner. - * - * <p/>Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not - * revoke the permission. It retains the previous grant, if any. - * - * <p/>Permissions can be granted or revoked only for applications built with a + * <p/> + * Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not revoke + * the permission. It retains the previous grant, if any. + * <p/> + * Permissions can be granted or revoked only for applications built with a * {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later. * * @param admin Which profile or device owner this request is associated with. * @param packageName The application to grant or revoke a permission to. * @param permission The permission to grant or revoke. - * @param grantState The permission grant state which is one of {@link - * #PERMISSION_GRANT_STATE_DENIED}, {@link #PERMISSION_GRANT_STATE_DEFAULT}, - * {@link #PERMISSION_GRANT_STATE_GRANTED}, + * @param grantState The permission grant state which is one of + * {@link #PERMISSION_GRANT_STATE_DENIED}, {@link #PERMISSION_GRANT_STATE_DEFAULT}, + * {@link #PERMISSION_GRANT_STATE_GRANTED}, * @return whether the permission was successfully granted or revoked. - * + * @throws SecurityException if {@code admin} is not a device or profile owner. * @see #PERMISSION_GRANT_STATE_DENIED * @see #PERMISSION_GRANT_STATE_DEFAULT * @see #PERMISSION_GRANT_STATE_GRANTED @@ -5474,13 +5533,15 @@ public class DevicePolicyManager { * @param packageName The application to check the grant state for. * @param permission The permission to check for. * @return the current grant state specified by device policy. If the profile or device owner - * has not set a grant state, the return value is {@link #PERMISSION_GRANT_STATE_DEFAULT}. - * This does not indicate whether or not the permission is currently granted for the package. - * - * <p/>If a grant state was set by the profile or device owner, then the return value will - * be one of {@link #PERMISSION_GRANT_STATE_DENIED} or {@link #PERMISSION_GRANT_STATE_GRANTED}, - * which indicates if the permission is currently denied or granted. - * + * has not set a grant state, the return value is + * {@link #PERMISSION_GRANT_STATE_DEFAULT}. This does not indicate whether or not the + * permission is currently granted for the package. + * <p/> + * If a grant state was set by the profile or device owner, then the return value will + * be one of {@link #PERMISSION_GRANT_STATE_DENIED} or + * {@link #PERMISSION_GRANT_STATE_GRANTED}, which indicates if the permission is + * currently denied or granted. + * @throws SecurityException if {@code admin} is not a device or profile owner. * @see #setPermissionGrantState(ComponentName, String, String, int) * @see PackageManager#checkPermission(String, String) */ @@ -5497,9 +5558,6 @@ public class DevicePolicyManager { * Returns if provisioning a managed profile or device is possible or not. * @param action One of {@link #ACTION_PROVISION_MANAGED_DEVICE}, * {@link #ACTION_PROVISION_MANAGED_PROFILE}. - * Note that even if this method returns true, there is a slight possibility that the - * provisioning will not be allowed when it is actually initiated because some event has - * happened in between. * @return if provisioning a managed profile or device is possible or not. * @throws IllegalArgumentException if the supplied action is not valid. */ @@ -5546,10 +5604,11 @@ public class DevicePolicyManager { * Called by device owner to get the MAC address of the Wi-Fi device. * * @param admin Which device owner this request is associated with. - * @return the MAC address of the Wi-Fi device, or null when the information is not - * available. (For example, Wi-Fi hasn't been enabled, or the device doesn't support Wi-Fi.) - * - * <p>The address will be in the {@code XX:XX:XX:XX:XX:XX} format. + * @return the MAC address of the Wi-Fi device, or null when the information is not available. + * (For example, Wi-Fi hasn't been enabled, or the device doesn't support Wi-Fi.) + * <p> + * The address will be in the {@code XX:XX:XX:XX:XX:XX} format. + * @throws SecurityException if {@code admin} is not a device owner. */ public String getWifiMacAddress(@NonNull ComponentName admin) { try { @@ -5560,7 +5619,12 @@ public class DevicePolicyManager { } /** - * Called by device owner to reboot the device. + * Called by device owner to reboot the device. If there is an ongoing call on the device, + * throws an {@link IllegalStateException}. + * @param admin Which device owner the request is associated with. + * @throws IllegalStateException if device has an ongoing call. + * @throws SecurityException if {@code admin} is not a device owner. + * @see TelephonyManager#CALL_STATE_IDLE */ public void reboot(@NonNull ComponentName admin) { try { @@ -5571,24 +5635,21 @@ public class DevicePolicyManager { } /** - * Called by a device admin to set the short support message. This will - * be displayed to the user in settings screens where funtionality has - * been disabled by the admin. - * - * The message should be limited to a short statement such as - * "This setting is disabled by your administrator. Contact someone@example.com - * for support." - * If the message is longer than 200 characters it may be truncated. - * - * <p>If the short support message needs to be localized, it is the responsibility of the + * Called by a device admin to set the short support message. This will be displayed to the user + * in settings screens where funtionality has been disabled by the admin. The message should be + * limited to a short statement such as "This setting is disabled by your administrator. Contact + * someone@example.com for support." If the message is longer than 200 characters it may be + * truncated. + * <p> + * If the short support message needs to be localized, it is the responsibility of the * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast * and set a new version of this string accordingly. * * @see #setLongSupportMessage - * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param message Short message to be displayed to the user in settings or null to - * clear the existing message. + * @param message Short message to be displayed to the user in settings or null to clear the + * existing message. + * @throws SecurityException if {@code admin} is not an active administrator. */ public void setShortSupportMessage(@NonNull ComponentName admin, @Nullable String message) { @@ -5605,8 +5666,9 @@ public class DevicePolicyManager { * Called by a device admin to get the short support message. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @return The message set by {@link #setShortSupportMessage(ComponentName, String)} - * or null if no message has been set. + * @return The message set by {@link #setShortSupportMessage(ComponentName, String)} or null if + * no message has been set. + * @throws SecurityException if {@code admin} is not an active administrator. */ public String getShortSupportMessage(@NonNull ComponentName admin) { if (mService != null) { @@ -5620,18 +5682,18 @@ public class DevicePolicyManager { } /** - * Called by a device admin to set the long support message. This will - * be displayed to the user in the device administators settings screen. - * - * <p>If the long support message needs to be localized, it is the responsibility of the + * Called by a device admin to set the long support message. This will be displayed to the user + * in the device administators settings screen. + * <p> + * If the long support message needs to be localized, it is the responsibility of the * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast * and set a new version of this string accordingly. * * @see #setShortSupportMessage - * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @param message Long message to be displayed to the user in settings or null to - * clear the existing message. + * @param message Long message to be displayed to the user in settings or null to clear the + * existing message. + * @throws SecurityException if {@code admin} is not an active administrator. */ public void setLongSupportMessage(@NonNull ComponentName admin, @Nullable String message) { @@ -5648,8 +5710,9 @@ public class DevicePolicyManager { * Called by a device admin to get the long support message. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. - * @return The message set by {@link #setLongSupportMessage(ComponentName, String)} - * or null if no message has been set. + * @return The message set by {@link #setLongSupportMessage(ComponentName, String)} or null if + * no message has been set. + * @throws SecurityException if {@code admin} is not an active administrator. */ public String getLongSupportMessage(@NonNull ComponentName admin) { if (mService != null) { @@ -5706,10 +5769,11 @@ public class DevicePolicyManager { /** * Called by the profile owner of a managed profile to obtain a {@link DevicePolicyManager} * whose calls act on the parent profile. - * - * <p> Note only some methods will work on the parent Manager. + * <p> + * Note only some methods will work on the parent Manager. * * @return a new instance of {@link DevicePolicyManager} that acts on the parent profile. + * @throws SecurityException if {@code admin} is not a profile owner. */ public DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) { try { @@ -5723,46 +5787,64 @@ public class DevicePolicyManager { } /** - * Called by device owner to control the device logging feature. Logging can only be + * Called by device owner to control the security logging feature. Logging can only be * enabled on single user devices where the sole user is managed by the device owner. * - * <p> Device logs contain various information intended for security auditing purposes. + * <p> Security logs contain various information intended for security auditing purposes. * See {@link SecurityEvent} for details. * * <p>There must be only one user on the device, managed by the device owner. * Otherwise a {@link SecurityException} will be thrown. * * @param admin Which device owner this request is associated with. - * @param enabled whether device logging should be enabled or not. - * @see #retrieveDeviceLogs + * @param enabled whether security logging should be enabled or not. + * @throws SecurityException if {@code admin} is not a device owner. + * @see #retrieveSecurityLogs */ - public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) { + public void setSecurityLoggingEnabled(@NonNull ComponentName admin, boolean enabled) { try { - mService.setDeviceLoggingEnabled(admin, enabled); + mService.setSecurityLoggingEnabled(admin, enabled); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } } /** - * Return whether device logging is enabled or not by the device owner. + * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed + * @hide + */ + public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) { + setSecurityLoggingEnabled(admin, enabled); + } + + /** + * Return whether security logging is enabled or not by the device owner. * * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be * thrown. * * @param admin Which device owner this request is associated with. - * @return {@code true} if device logging is enabled by device owner, {@code false} otherwise. + * @return {@code true} if security logging is enabled by device owner, {@code false} otherwise. + * @throws SecurityException if {@code admin} is not a device owner. */ - public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) { + public boolean isSecurityLoggingEnabled(@NonNull ComponentName admin) { try { - return mService.getDeviceLoggingEnabled(admin); + return mService.isSecurityLoggingEnabled(admin); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } } /** - * Called by device owner to retrieve all new device logging entries since the last call to + * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed + * @hide + */ + public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) { + return isSecurityLoggingEnabled(admin); + } + + /** + * Called by device owner to retrieve all new security logging entries since the last call to * this API after device boots. * * <p> Access to the logs is rate limited and it will only return new logs after the device @@ -5772,12 +5854,13 @@ public class DevicePolicyManager { * Otherwise a {@link SecurityException} will be thrown. * * @param admin Which device owner this request is associated with. - * @return the new batch of device logs which is a list of {@link SecurityEvent}, + * @return the new batch of security logs which is a list of {@link SecurityEvent}, * or {@code null} if rate limitation is exceeded or if logging is currently disabled. + * @throws SecurityException if {@code admin} is not a device owner. */ - public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) { + public List<SecurityEvent> retrieveSecurityLogs(@NonNull ComponentName admin) { try { - ParceledListSlice<SecurityEvent> list = mService.retrieveDeviceLogs(admin); + ParceledListSlice<SecurityEvent> list = mService.retrieveSecurityLogs(admin); if (list != null) { return list.getList(); } else { @@ -5790,6 +5873,14 @@ public class DevicePolicyManager { } /** + * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed + * @hide + */ + public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) { + return retrieveSecurityLogs(admin); + } + + /** * Called by the system to obtain a {@link DevicePolicyManager} whose calls act on the parent * profile. * @@ -5807,22 +5898,22 @@ public class DevicePolicyManager { /** * Called by device owners to retrieve device logs from before the device's last reboot. - * * <p> * <strong> The device logs are retrieved from a RAM region which is not guaranteed to be - * corruption-free during power cycles, due to hardware variations and limitations. As a - * result, this API is provided as best-effort and the returned logs may contain corrupted data. - * </strong> - * - * <p>There must be only one user on the device, managed by the device owner. - * Otherwise a {@link SecurityException} will be thrown. + * corruption-free during power cycles, due to hardware variations and limitations. As a result, + * this API is provided as best-effort and the returned logs may contain corrupted + * data. </strong> + * <p> + * There must be only one user on the device, managed by the device owner. Otherwise a + * {@link SecurityException} will be thrown. * * @param admin Which device owner this request is associated with. * @return Device logs from before the latest reboot of the system. + * @throws SecurityException if {@code admin} is not a device owner. */ - public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) { + public List<SecurityEvent> retrievePreRebootSecurityLogs(@NonNull ComponentName admin) { try { - ParceledListSlice<SecurityEvent> list = mService.retrievePreviousDeviceLogs(admin); + ParceledListSlice<SecurityEvent> list = mService.retrievePreRebootSecurityLogs(admin); return list.getList(); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); @@ -5830,15 +5921,24 @@ public class DevicePolicyManager { } /** - * Called by a profile owner of a managed profile to set the color used for customization. - * This color is used as background color of the confirm credentials screen for that user. - * The default color is {@link android.graphics.Color#GRAY}. - * - * <p>The confirm credentials screen can be created using + * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed + * @hide + */ + public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) { + return retrievePreRebootSecurityLogs(admin); + } + + /** + * Called by a profile owner of a managed profile to set the color used for customization. This + * color is used as background color of the confirm credentials screen for that user. The + * default color is {@link android.graphics.Color#GRAY}. + * <p> + * The confirm credentials screen can be created using * {@link android.app.KeyguardManager#createConfirmDeviceCredentialIntent}. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param color The 32bit representation of the color to be used. + * @throws SecurityException if {@code admin} is not a profile owner. */ public void setOrganizationColor(@NonNull ComponentName admin, int color) { try { @@ -5873,6 +5973,7 @@ public class DevicePolicyManager { * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return The 32bit representation of the color to be used. + * @throws SecurityException if {@code admin} is not a profile owner. */ public int getOrganizationColor(@NonNull ComponentName admin) { try { @@ -5900,13 +6001,14 @@ public class DevicePolicyManager { /** * Called by a profile owner of a managed profile to set the name of the organization under * management. - * - * <p>If the organization name needs to be localized, it is the responsibility of the + * <p> + * If the organization name needs to be localized, it is the responsibility of the * {@link DeviceAdminReceiver} to listen to the {@link Intent#ACTION_LOCALE_CHANGED} broadcast * and set a new version of this string accordingly. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param title The organization name or {@code null} to clear a previously set name. + * @throws SecurityException if {@code admin} is not a profile owner. */ public void setOrganizationName(@NonNull ComponentName admin, @Nullable String title) { try { @@ -5917,11 +6019,12 @@ public class DevicePolicyManager { } /** - * Called by a profile owner of a managed profile to retrieve the name of the organization - * under management. + * Called by a profile owner of a managed profile to retrieve the name of the organization under + * management. * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @return The organization name or {@code null} if none is set. + * @throws SecurityException if {@code admin} is not a profile owner. */ public String getOrganizationName(@NonNull ComponentName admin) { try { diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java index 61b40d437514..54a2f7aff7d6 100644 --- a/core/java/android/app/admin/DevicePolicyManagerInternal.java +++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java @@ -16,6 +16,7 @@ package android.app.admin; +import android.content.Intent; import android.os.UserHandle; import java.util.List; @@ -74,10 +75,23 @@ public abstract class DevicePolicyManagerInternal { /** * Checks if a given package has a device or a profile owner for the given user. - * </br><em>Does <b>not</b> support negative userIds like {@link UserHandle#USER_ALL}</em> + * <p> + * <em>Note: does <b>not</b> support negative userIds like {@link UserHandle#USER_ALL}</em> + * * @param packageName The package to check * @param userId the userId to check for. * @return true if package has a device or profile owner, false otherwise. */ public abstract boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId); + + /** + * Creates an intent to show the admin support dialog to let the user know that the package is + * suspended by the admin. This assumes that {@param packageName} is suspended by the + * device/profile owner. The caller should check if the package is suspended or not. + * + * @param packageName The package that is suspended + * @param userId The user having the suspended package. + * @return The intent to trigger the admin support dialog. + */ + public abstract Intent createPackageSuspendedDialogIntent(String packageName, int userId); } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index dc73e2613f18..3ba5bd839d2d 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -91,7 +91,7 @@ interface IDevicePolicyManager { int setStorageEncryption(in ComponentName who, boolean encrypt); boolean getStorageEncryption(in ComponentName who, int userHandle); - int getStorageEncryptionStatus(int userHandle); + int getStorageEncryptionStatus(in String callerPackage, int userHandle); boolean requestBugreport(in ComponentName who); @@ -290,10 +290,10 @@ interface IDevicePolicyManager { void setAffiliationIds(in ComponentName admin, in List<String> ids); boolean isAffiliatedUser(); - void setDeviceLoggingEnabled(in ComponentName admin, boolean enabled); - boolean getDeviceLoggingEnabled(in ComponentName admin); - ParceledListSlice retrieveDeviceLogs(in ComponentName admin); - ParceledListSlice retrievePreviousDeviceLogs(in ComponentName admin); + void setSecurityLoggingEnabled(in ComponentName admin, boolean enabled); + boolean isSecurityLoggingEnabled(in ComponentName admin); + ParceledListSlice retrieveSecurityLogs(in ComponentName admin); + ParceledListSlice retrievePreRebootSecurityLogs(in ComponentName admin); boolean isUninstallInQueue(String packageName); void uninstallPackageWithActiveAdmins(String packageName); diff --git a/core/java/android/auditing/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java index 13823a23f43b..001a81de7d80 100644 --- a/core/java/android/auditing/SecurityLog.java +++ b/core/java/android/app/admin/SecurityLog.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package android.auditing; +package android.app.admin; import android.annotation.IntDef; import android.os.Parcel; @@ -92,7 +92,7 @@ public class SecurityLog { public static final int TAG_KEYGUARD_SECURED = SecurityLogTags.SECURITY_KEYGUARD_SECURED; /** - * Returns if device logging is enabled. Log producers should only write new logs if this is + * Returns if security logging is enabled. Log producers should only write new logs if this is * true. Under the hood this is the logical AND of whether device owner exists and whether * it enables logging by setting the system property {@link #PROPERTY_LOGGING_ENABLED}. * @hide diff --git a/core/java/android/auditing/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags index ccc37995972c..39371c7923e0 100644 --- a/core/java/android/auditing/SecurityLogTags.logtags +++ b/core/java/android/app/admin/SecurityLogTags.logtags @@ -1,6 +1,6 @@ # See system/core/logcat/event.logtags for a description of the format of this file. -option java_package android.auditing +option java_package android.app.admin 210001 security_adb_shell_interactive 210002 security_adb_shell_command (command|3) diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index bbfec41a5015..828ac385b62d 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -73,9 +73,32 @@ public class JobInfo implements Parcelable { public static final int BACKOFF_POLICY_EXPONENTIAL = 1; /* Minimum interval for a periodic job, in milliseconds. */ - public static final long MIN_PERIOD_MILLIS = 60 * 60 * 1000L; // 60 minutes + private static final long MIN_PERIOD_MILLIS = 15 * 60 * 1000L; // 15 minutes + /* Minimum flex for a periodic job, in milliseconds. */ - public static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes + private static final long MIN_FLEX_MILLIS = 5 * 60 * 1000L; // 5 minutes + + /** + * Query the minimum interval allowed for periodic scheduled jobs. Attempting + * to declare a smaller period that this when scheduling a job will result in a + * job that is still periodic, but will run with this effective period. + * + * @return The minimum available interval for scheduling periodic jobs, in milliseconds. + */ + public static final long getMinimumPeriod() { + return MIN_PERIOD_MILLIS; + } + + /** + * Query the minimum flex time allowed for periodic scheduled jobs. Attempting + * to declare a shorter flex time than this when scheduling such a job will + * result in this amount as the effective flex time for the job. + * + * @return The minimum available flex time for scheduling periodic jobs, in milliseconds. + */ + public static final long getMinimumFlex() { + return MIN_FLEX_MILLIS; + } /** * Default type of backoff. @@ -227,7 +250,7 @@ public class JobInfo implements Parcelable { * job does not recur periodically. */ public long getIntervalMillis() { - return intervalMillis >= MIN_PERIOD_MILLIS ? intervalMillis : MIN_PERIOD_MILLIS; + return intervalMillis >= getMinimumPeriod() ? intervalMillis : getMinimumPeriod(); } /** @@ -236,7 +259,7 @@ public class JobInfo implements Parcelable { public long getFlexMillis() { long interval = getIntervalMillis(); long percentClamp = 5 * interval / 100; - long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, MIN_FLEX_MILLIS)); + long clampedFlex = Math.max(flexMillis, Math.max(percentClamp, getMinimumFlex())); return clampedFlex <= interval ? clampedFlex : interval; } @@ -565,9 +588,9 @@ public class JobInfo implements Parcelable { * Specify that this job should recur with the provided interval and flex. The job can * execute at any time in a window of flex length at the end of the period. * @param intervalMillis Millisecond interval for which this job will repeat. A minimum - * value of {@link #MIN_PERIOD_MILLIS} is enforced. + * value of {@link #getMinimumPeriod()} is enforced. * @param flexMillis Millisecond flex for this job. Flex is clamped to be at least - * {@link #MIN_FLEX_MILLIS} or 5 percent of the period, whichever is + * {@link #getMinimumFlex()} or 5 percent of the period, whichever is * higher. */ public Builder setPeriodic(long intervalMillis, long flexMillis) { diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 9f1a9cf01eca..6d5c81b142d1 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -16,6 +16,7 @@ package android.app.usage; +import android.annotation.IntDef; import android.content.Context; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; @@ -29,6 +30,9 @@ import android.util.Log; import dalvik.system.CloseGuard; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects * are returned as results to various queries in {@link NetworkStatsManager}. @@ -119,6 +123,11 @@ public final class NetworkStats implements AutoCloseable { * aggregated (e.g. time or state) some values may be equal across all buckets. */ public static class Bucket { + /** @hide */ + @IntDef({STATE_ALL, STATE_DEFAULT, STATE_FOREGROUND}) + @Retention(RetentionPolicy.SOURCE) + public @interface State {} + /** * Combined usage across all states. */ @@ -149,20 +158,34 @@ public final class NetworkStats implements AutoCloseable { */ public static final int UID_TETHERING = TrafficStats.UID_TETHERING; + /** @hide */ + @IntDef({ROAMING_ALL, ROAMING_NO, ROAMING_YES}) + @Retention(RetentionPolicy.SOURCE) + public @interface Roaming {} + /** - * Combined usage across all roaming states. + * Combined usage across all roaming states. Covers both roaming and non-roaming usage. */ public static final int ROAMING_ALL = -1; /** - * Usage not accounted for in any other roaming state. + * Usage that occurs on a home, non-roaming network. + * + * <p>Any cellular usage in this bucket was incurred while the device was connected to a + * tower owned or operated by the user's wireless carrier, or a tower that the user's + * wireless carrier has indicated should be treated as a home network regardless. + * + * <p>This is also the default value for network types that do not support roaming. */ - public static final int ROAMING_DEFAULT = 0x1; + public static final int ROAMING_NO = 0x1; /** - * Roaming usage. + * Usage that occurs on a roaming network. + * + * <p>Any cellular usage in this bucket as incurred while the device was roaming on another + * carrier's network, for which additional charges may apply. */ - public static final int ROAMING_ROAMING = 0x2; + public static final int ROAMING_YES = 0x2; /** * Special TAG value matching any tag. @@ -185,7 +208,7 @@ public final class NetworkStats implements AutoCloseable { private long mTxBytes; private long mTxPackets; - private static int convertState(int networkStatsSet) { + private static @State int convertState(int networkStatsSet) { switch (networkStatsSet) { case android.net.NetworkStats.SET_ALL : return STATE_ALL; case android.net.NetworkStats.SET_DEFAULT : return STATE_DEFAULT; @@ -210,11 +233,11 @@ public final class NetworkStats implements AutoCloseable { return tag; } - private static int convertRoaming(int roaming) { + private static @Roaming int convertRoaming(int roaming) { switch (roaming) { case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL; - case android.net.NetworkStats.ROAMING_DEFAULT : return ROAMING_DEFAULT; - case android.net.NetworkStats.ROAMING_ROAMING : return ROAMING_ROAMING; + case android.net.NetworkStats.ROAMING_NO: return ROAMING_NO; + case android.net.NetworkStats.ROAMING_YES: return ROAMING_YES; } return 0; } @@ -252,7 +275,7 @@ public final class NetworkStats implements AutoCloseable { * </ul> * @return Usage state. */ - public int getState() { + public @State int getState() { return mState; } @@ -260,11 +283,11 @@ public final class NetworkStats implements AutoCloseable { * Roaming state. One of the following values:<p/> * <ul> * <li>{@link #ROAMING_ALL}</li> - * <li>{@link #ROAMING_DEFAULT}</li> - * <li>{@link #ROAMING_ROAMING}</li> + * <li>{@link #ROAMING_NO}</li> + * <li>{@link #ROAMING_YES}</li> * </ul> */ - public int getRoaming() { + public @Roaming int getRoaming() { return mRoaming; } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index eb4cb919ce1b..d762a1727272 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2015 The Android Open Source Project + * Copyright (C) 2009-2016 The Android Open Source Project * Copyright (C) 2015 Samsung LSI * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -1837,6 +1837,9 @@ public final class BluetoothAdapter { } else if (profile == BluetoothProfile.SAP) { BluetoothSap sap = new BluetoothSap(context, listener); return true; + } else if (profile == BluetoothProfile.PBAP_CLIENT) { + BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener); + return true; } else { return false; } @@ -1905,6 +1908,10 @@ public final class BluetoothAdapter { BluetoothSap sap = (BluetoothSap)proxy; sap.close(); break; + case BluetoothProfile.PBAP_CLIENT: + BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy; + pbapClient.close(); + break; } } diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java new file mode 100644 index 000000000000..736e55d17d8a --- /dev/null +++ b/core/java/android/bluetooth/BluetoothPbapClient.java @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import java.util.List; +import java.util.ArrayList; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.RemoteException; +import android.os.IBinder; +import android.util.Log; + +/** + * This class provides the APIs to control the Bluetooth PBAP Client Profile. + *@hide + */ +public final class BluetoothPbapClient implements BluetoothProfile { + + private static final String TAG = "BluetoothPbapClient"; + private static final boolean DBG = false; + private static final boolean VDBG = false; + + public static final String ACTION_CONNECTION_STATE_CHANGED = + "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED"; + + private IBluetoothPbapClient mService; + private BluetoothDevice mDevice; + private final Context mContext; + private ServiceListener mServiceListener; + private BluetoothAdapter mAdapter; + + /** There was an error trying to obtain the state */ + public static final int STATE_ERROR = -1; + + public static final int RESULT_FAILURE = 0; + public static final int RESULT_SUCCESS = 1; + /** Connection canceled before completion. */ + public static final int RESULT_CANCELED = 2; + + final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = + new IBluetoothStateChangeCallback.Stub() { + public void onBluetoothStateChange(boolean up) { + if (DBG) { + Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up); + } + if (!up) { + if (VDBG) { + Log.d(TAG,"Unbinding service..."); + } + synchronized (mConnection) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } else { + synchronized (mConnection) { + try { + if (mService == null) { + if (VDBG) { + Log.d(TAG,"Binding service..."); + } + doBind(); + } + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + } + }; + + /** + * Create a BluetoothPbapClient proxy object. + */ + BluetoothPbapClient(Context context, ServiceListener l) { + if (DBG) { + Log.d(TAG, "Create BluetoothPbapClient proxy object"); + } + mContext = context; + mServiceListener = l; + mAdapter = BluetoothAdapter.getDefaultAdapter(); + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); + } catch (RemoteException e) { + Log.e(TAG,"",e); + } + } + doBind(); + } + + private boolean doBind() { + Intent intent = new Intent(IBluetoothPbapClient.class.getName()); + ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); + intent.setComponent(comp); + if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, + android.os.Process.myUserHandle())) { + Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent); + return false; + } + return true; + } + + protected void finalize() throws Throwable { + try { + close(); + } finally { + super.finalize(); + } + } + + /** + * Close the connection to the backing service. + * Other public functions of BluetoothPbapClient will return default error + * results once close() has been called. Multiple invocations of close() + * are ok. + */ + public synchronized void close() { + IBluetoothManager mgr = mAdapter.getBluetoothManager(); + if (mgr != null) { + try { + mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); + } catch (Exception e) { + Log.e(TAG,"",e); + } + } + + synchronized (mConnection) { + if (mService != null) { + try { + mService = null; + mContext.unbindService(mConnection); + } catch (Exception re) { + Log.e(TAG,"",re); + } + } + } + mServiceListener = null; + } + + /** + * Initiate connection. + * Upon successful connection to remote PBAP server the Client will + * attempt to automatically download the users phonebook and call log. + * + * @param device a remote device we want connect to + * @return <code>true</code> if command has been issued successfully; + * <code>false</code> otherwise; + */ + public boolean connect(BluetoothDevice device) { + if (DBG) { + log("connect(" + device + ") for PBAP Client."); + } + if (mService != null && isEnabled() && isValidDevice(device)) { + try { + mDevice = device; + return mService.connect(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + } + return false; + } + + /** + * Initiate disconnect. + * + * @param device Remote Bluetooth Device + * @return false on error, + * true otherwise + */ + public boolean disconnect() { + if (DBG) { + log("disconnect(" + mDevice + ")"); + } + if (mService != null && isEnabled() && isValidDevice(mDevice)) { + try { + mService.disconnect(mDevice); + return true; + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return false; + } + } + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + } + return false; + } + + /** + * Get the list of connected devices. + * Currently at most one. + * + * @return list of connected devices + */ + @Override + public List<BluetoothDevice> getConnectedDevices() { + if (DBG) { + log("getConnectedDevices()"); + } + if (mService != null && isEnabled()) { + try { + return mService.getConnectedDevices(); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + } + return new ArrayList<BluetoothDevice>(); + } + + /** + * Get the list of devices matching specified states. Currently at most one. + * + * @return list of matching devices + */ + @Override + public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { + if (DBG) { + log("getDevicesMatchingStates()"); + } + if (mService != null && isEnabled()) { + try { + return mService.getDevicesMatchingConnectionStates(states); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return new ArrayList<BluetoothDevice>(); + } + } + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + } + return new ArrayList<BluetoothDevice>(); + } + + /** + * Get connection state of device + * + * @return device connection state + */ + @Override + public int getConnectionState(BluetoothDevice device) { + if (DBG) { + log("getConnectionState(" + device + ")"); + } + if (mService != null && isEnabled() && isValidDevice(device)) { + try { + return mService.getConnectionState(device); + } catch (RemoteException e) { + Log.e(TAG, Log.getStackTraceString(new Throwable())); + return BluetoothProfile.STATE_DISCONNECTED; + } + } + if (mService == null) { + Log.w(TAG, "Proxy not attached to service"); + } + return BluetoothProfile.STATE_DISCONNECTED; + } + + private final ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + if (DBG) { + log("Proxy object connected"); + } + mService = IBluetoothPbapClient.Stub.asInterface(service); + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, BluetoothPbapClient.this); + } + } + public void onServiceDisconnected(ComponentName className) { + if (DBG) { + log("Proxy object disconnected"); + } + mService = null; + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT); + } + } + }; + + private static void log(String msg) { + Log.d(TAG, msg); + } + + private boolean isEnabled() { + BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); + if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) { + return true; + } + log("Bluetooth is Not enabled"); + return false; + } + + private boolean isValidDevice(BluetoothDevice device) { + if (device == null) { + return false; + } + if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + return true; + } + return false; + } +} diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java index cbce22cdea60..eee66d193fe4 100644 --- a/core/java/android/bluetooth/BluetoothProfile.java +++ b/core/java/android/bluetooth/BluetoothProfile.java @@ -131,6 +131,12 @@ public interface BluetoothProfile { public static final int HEADSET_CLIENT = 16; /** + * PBAP Client + * @hide + */ + public static final int PBAP_CLIENT = 17; + + /** * Default priority for devices that we try to auto-connect to and * and allow incoming connections for the profile * @hide diff --git a/core/java/android/bluetooth/IBluetoothPbapClient.aidl b/core/java/android/bluetooth/IBluetoothPbapClient.aidl new file mode 100644 index 000000000000..b26ea2957142 --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothPbapClient.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016 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.bluetooth; + +import android.bluetooth.BluetoothDevice; + +/** + * API for Bluetooth Phone Book Access Provile Client Side + * + * {@hide} + */ +interface IBluetoothPbapClient { + boolean connect(in BluetoothDevice device); + boolean disconnect(in BluetoothDevice device); + List<BluetoothDevice> getConnectedDevices(); + List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states); + int getConnectionState(in BluetoothDevice device); +} diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java index 0ec58ea40fe4..58630b020491 100644 --- a/core/java/android/content/ClipData.java +++ b/core/java/android/content/ClipData.java @@ -836,6 +836,17 @@ public class ClipData implements Parcelable { } } + /** {@hide} */ + public void prepareToEnterProcess() { + final int size = mItems.size(); + for (int i = 0; i < size; i++) { + final Item item = mItems.get(i); + if (item.mIntent != null) { + item.mIntent.prepareToEnterProcess(); + } + } + } + /** @hide */ public void fixUris(int contentUserHint) { final int size = mItems.size(); diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 4e1b6e019b48..441f188f91e6 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -2440,6 +2440,28 @@ public abstract class ContentResolver { } } + /** {@hide} */ + public void putCache(Uri key, Bundle value) { + try { + getContentService().putCache(mContext.getPackageName(), key, value, + mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** {@hide} */ + public Bundle getCache(Uri key) { + try { + final Bundle bundle = getContentService().getCache(mContext.getPackageName(), key, + mContext.getUserId()); + if (bundle != null) bundle.setClassLoader(mContext.getClassLoader()); + return bundle; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Returns sampling percentage for a given duration. * diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 825dd5bc6613..c4dfdcf10405 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2681,6 +2681,7 @@ public abstract class Context { HARDWARE_PROPERTIES_SERVICE, //@hide: SOUND_TRIGGER_SERVICE, SHORTCUT_SERVICE, + //@hide: CONTEXTHUB_SERVICE, }) @Retention(RetentionPolicy.SOURCE) public @interface ServiceName {} @@ -2742,7 +2743,7 @@ public abstract class Context { * <dt> {@link #NETWORK_STATS_SERVICE} ("netstats") * <dd> A {@link android.app.usage.NetworkStatsManager NetworkStatsManager} for querying network * usage statistics. - * <dt> {@link #HARDWARE_PROPERTIES_SERVICE} ("hardwareproperties") + * <dt> {@link #HARDWARE_PROPERTIES_SERVICE} ("hardware_properties") * <dd> A {@link android.os.HardwarePropertiesManager} for accessing hardware properties. * </dl> * @@ -3574,7 +3575,7 @@ public abstract class Context { * * @see #getSystemService */ - public static final String HARDWARE_PROPERTIES_SERVICE = "hardwareproperties"; + public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; /** * TODO Javadoc @@ -3585,6 +3586,18 @@ public abstract class Context { public static final String SHORTCUT_SERVICE = "shortcut"; /** + * Use with {@link #getSystemService} to retrieve a {@link + * android.hardware.location.ContextHubManager} for accessing context hubs. + * + * @see #getSystemService + * @see android.hardware.location.ContextHubManager + * + * @hide + */ + @SystemApi + public static final String CONTEXTHUB_SERVICE = "contexthub"; + + /** * Use with {@link #getSystemService} to retrieve a * {@link android.os.health.SystemHealthManager} for accessing system health (battery, power, * memory, etc) metrics. diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl index 8b471a04f25b..d47e780fa4d2 100644 --- a/core/java/android/content/IContentService.aidl +++ b/core/java/android/content/IContentService.aidl @@ -179,6 +179,8 @@ interface IContentService { int userId); void addStatusChangeListener(int mask, ISyncStatusObserver callback); - void removeStatusChangeListener(ISyncStatusObserver callback); + + void putCache(in String packageName, in Uri key, in Bundle value, int userId); + Bundle getCache(in String packageName, in Uri key, int userId); } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 09fa5e11829b..09aad3b66428 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -660,6 +660,8 @@ public class Intent implements Parcelable, Cloneable { /** * Activity Action: Quick view the data. Launches a quick viewer for * a URI or a list of URIs. + * <p>Activities handling this intent action should handle the vast majority of + * MIME types rather than only specific ones. * <p>Input: {@link #getData} is a mandatory content URI of the item to * preview. {@link #getClipData} contains an optional list of content URIs * if there is more than one item to preview. {@link #EXTRA_INDEX} is an @@ -4142,7 +4144,8 @@ public class Intent implements Parcelable, Cloneable { /** * Optional index with semantics depending on the intent action. - * @see #ACTION_QUICK_VIEW + * + * <p>The value must be an integer greater or equal to 0. */ public static final String EXTRA_INDEX = "android.intent.extra.INDEX"; @@ -4560,7 +4563,8 @@ public class Intent implements Parcelable, Cloneable { /** * This flag is only used in split-screen multi-window mode. The new activity will be displayed * adjacent to the one launching it. This can only be used in conjunction with - * {@link #FLAG_ACTIVITY_NEW_TASK}. + * {@link #FLAG_ACTIVITY_NEW_TASK}. Also, setting {@link #FLAG_ACTIVITY_MULTIPLE_TASK} is + * required if you want a new instance of an existing activity to be created. */ public static final int FLAG_ACTIVITY_LAUNCH_ADJACENT = 0x00001000; @@ -6033,13 +6037,20 @@ public class Intent implements Parcelable, Cloneable { return mExtras != null && mExtras.hasFileDescriptors(); } - /** @hide */ + /** {@hide} */ public void setAllowFds(boolean allowFds) { if (mExtras != null) { mExtras.setAllowFds(allowFds); } } + /** {@hide} */ + public void setDefusable(boolean defusable) { + if (mExtras != null) { + mExtras.setDefusable(defusable); + } + } + /** * Retrieve extended data from the intent. * @@ -8934,6 +8945,17 @@ public class Intent implements Parcelable, Cloneable { * @hide */ public void prepareToEnterProcess() { + // We just entered destination process, so we should be able to read all + // parcelables inside. + setDefusable(true); + + if (mSelector != null) { + mSelector.prepareToEnterProcess(); + } + if (mClipData != null) { + mClipData.prepareToEnterProcess(); + } + if (mContentUserHint != UserHandle.USER_CURRENT) { if (UserHandle.getAppId(Process.myUid()) != Process.SYSTEM_UID) { fixUris(mContentUserHint); diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 14ef61ce63d4..5da3c866077a 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -18,6 +18,7 @@ package android.content.pm; import android.annotation.IntDef; import android.content.res.Configuration; +import android.content.res.Configuration.NativeConfig; import android.os.Parcel; import android.os.Parcelable; import android.util.Printer; @@ -495,6 +496,28 @@ public class ActivityInfo extends ComponentInfo @ScreenOrientation public int screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED; + /** @hide */ + @IntDef(flag = true, + value = { + CONFIG_MCC, + CONFIG_MNC, + CONFIG_LOCALE, + CONFIG_TOUCHSCREEN, + CONFIG_KEYBOARD, + CONFIG_KEYBOARD_HIDDEN, + CONFIG_NAVIGATION, + CONFIG_ORIENTATION, + CONFIG_SCREEN_LAYOUT, + CONFIG_UI_MODE, + CONFIG_SCREEN_SIZE, + CONFIG_SMALLEST_SCREEN_SIZE, + CONFIG_DENSITY, + CONFIG_LAYOUT_DIRECTION, + CONFIG_FONT_SCALE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Config {} + /** * Bit in {@link #configChanges} that indicates that the activity * can itself handle changes to the IMSI MCC. Set from the @@ -629,7 +652,7 @@ public class ActivityInfo extends ComponentInfo * * @hide */ - public static int activityInfoConfigToNative(int input) { + public static @NativeConfig int activityInfoConfigJavaToNative(@Config int input) { int output = 0; for (int i = 0; i < CONFIG_NATIVE_BITS.length; i++) { if ((input & (1 << i)) != 0) { @@ -644,7 +667,7 @@ public class ActivityInfo extends ComponentInfo * * @hide */ - public static int activityInfoConfigNativeToJava(int input) { + public static @Config int activityInfoConfigNativeToJava(@NativeConfig int input) { int output = 0; for (int i = 0; i < CONFIG_NATIVE_BITS.length; i++) { if ((input & CONFIG_NATIVE_BITS[i]) != 0) { diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl index b1d3f207f82f..6b3d4f1326ea 100644 --- a/core/java/android/content/pm/ILauncherApps.aidl +++ b/core/java/android/content/pm/ILauncherApps.aidl @@ -34,7 +34,7 @@ import java.util.List; * {@hide} */ interface ILauncherApps { - void addOnAppsChangedListener(in IOnAppsChangedListener listener); + void addOnAppsChangedListener(String callingPackage, in IOnAppsChangedListener listener); void removeOnAppsChangedListener(in IOnAppsChangedListener listener); ParceledListSlice getLauncherActivities(String packageName, in UserHandle user); ResolveInfo resolveActivity(in Intent intent, in UserHandle user); @@ -58,4 +58,6 @@ interface ILauncherApps { int getShortcutIconResId(String callingPackage, in ShortcutInfo shortcut, in UserHandle user); ParcelFileDescriptor getShortcutIconFd(String callingPackage, in ShortcutInfo shortcut, in UserHandle user); + + boolean hasShortcutHostPermission(String callingPackage); } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index c6844471d71e..dabc6524b20f 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -291,6 +291,8 @@ interface IPackageManager { */ ComponentName getHomeActivities(out List<ResolveInfo> outHomeCandidates); + void setHomeActivity(in ComponentName className, int userId); + /** * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}. */ @@ -314,6 +316,11 @@ interface IPackageManager { int getApplicationEnabledSetting(in String packageName, int userId); /** + * As per {@link android.content.pm.PackageManager#flushPackageRestrictionsAsUser}. + */ + void flushPackageRestrictionsAsUser(in int userId); + + /** * Set whether the given package should be considered stopped, making * it not visible to implicit intents that filter out stopped packages. */ @@ -535,5 +542,4 @@ interface IPackageManager { boolean isPackageDeviceAdminOnAnyUser(String packageName); List<String> getPreviousCodePaths(in String packageName); - } diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index a6a732ea9513..8724d5ece5ca 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -16,11 +16,9 @@ package android.content.pm; -import android.Manifest.permission; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.RequiresPermission; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -30,7 +28,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.UserHandle; @@ -159,6 +156,9 @@ public class LauncherApps { * Indicates that one or more shortcuts (which may be dynamic and/or pinned) * have been added, updated or removed. * + * <p>Only the applications that are allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}, will receive it. + * * @param packageName The name of the package that has the shortcuts. * @param shortcuts all shortcuts from the package (dynamic and/or pinned). * @param user The UserHandle of the profile that generated the change. @@ -395,16 +395,34 @@ public class LauncherApps { } /** + * Returns whether the caller can access the shortcut information. + * + * <p>Only the default launcher can access the shortcut information. + * + * <p>Note when this method returns {@code false}, that may be a temporary situation because + * the user is trying a new launcher application. The user may decide to change the default + * launcher to the calling application again, so even if a launcher application loses + * this permission, it does <b>not</b> have to purge pinned shortcut information. + */ + public boolean hasShortcutHostPermission() { + try { + return mService.hasShortcutHostPermission(mContext.getPackageName()); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** * Returns the IDs of {@link ShortcutInfo}s that match {@code query}. * - * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission. + * <p>Callers must be allowed to access the shortcut information, as defined in {@link + * #hasShortcutHostPermission()}. * * @param query result includes shortcuts matching this query. * @param user The UserHandle of the profile. * * @return the IDs of {@link ShortcutInfo}s that match the query. */ - @RequiresPermission(permission.BIND_APPWIDGET) @Nullable public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query, @NonNull UserHandle user) { @@ -420,7 +438,8 @@ public class LauncherApps { /** * Returns {@link ShortcutInfo}s with the given IDs from a package. * - * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission. + * <p>Callers must be allowed to access the shortcut information, as defined in {@link + * #hasShortcutHostPermission()}. * * @param packageName The target package. * @param ids IDs of the shortcuts to retrieve. @@ -428,7 +447,6 @@ public class LauncherApps { * * @return list of {@link ShortcutInfo} associated with the package. */ - @RequiresPermission(permission.BIND_APPWIDGET) @Nullable public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName, @NonNull List<String> ids, @NonNull UserHandle user) { @@ -447,13 +465,13 @@ public class LauncherApps { * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package. * However, different launchers may have different set of pinned shortcuts. * - * <p>Callers must have the {@link permission#BIND_APPWIDGET} permission. + * <p>Callers must be allowed to access the shortcut information, as defined in {@link + * #hasShortcutHostPermission()}. * * @param packageName The target package name. * @param shortcutIds The IDs of the shortcut to be pinned. * @param user The UserHandle of the profile. */ - @RequiresPermission(permission.BIND_APPWIDGET) public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds, @NonNull UserHandle user) { try { @@ -467,12 +485,12 @@ public class LauncherApps { * Return the icon resource ID, if {@code shortcut} has one * (i.e. when {@link ShortcutInfo#hasIconResource()} returns {@code true}). * - * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission. + * <p>Callers must be allowed to access the shortcut information, as defined in {@link + * #hasShortcutHostPermission()}. * * @param shortcut The target shortcut. * @param user The UserHandle of the profile. */ - @RequiresPermission(permission.BIND_APPWIDGET) public int getShortcutIconResId(@NonNull ShortcutInfo shortcut, @NonNull UserHandle user) { try { return mService.getShortcutIconResId(mContext.getPackageName(), shortcut, user); @@ -485,12 +503,12 @@ public class LauncherApps { * Return the icon as {@link ParcelFileDescriptor}, when it's stored as a file * (i.e. when {@link ShortcutInfo#hasIconFile()} returns {@code true}). * - * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission. + * <p>Callers must be allowed to access the shortcut information, as defined in {@link + * #hasShortcutHostPermission()}. * * @param shortcut The target shortcut. * @param user The UserHandle of the profile. */ - @RequiresPermission(permission.BIND_APPWIDGET) public ParcelFileDescriptor getShortcutIconFd( @NonNull ShortcutInfo shortcut, @NonNull UserHandle user) { try { @@ -503,7 +521,8 @@ public class LauncherApps { /** * Launches a shortcut. * - * <p>Callers mut have the {@link permission#BIND_APPWIDGET} permission. + * <p>Callers must be allowed to access the shortcut information, as defined in {@link + * #hasShortcutHostPermission()}. * * @param packageName The target shortcut package name. * @param shortcutId The target shortcut ID. @@ -513,7 +532,6 @@ public class LauncherApps { * @return {@code false} when the shortcut is no longer valid (e.g. the creator application * has been uninstalled). {@code true} when the shortcut is still valid. */ - @RequiresPermission(permission.BIND_APPWIDGET) public boolean startShortcut(@NonNull String packageName, @NonNull String shortcutId, @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions, @NonNull UserHandle user) { @@ -547,7 +565,8 @@ public class LauncherApps { addCallbackLocked(callback, handler); if (addedFirstCallback) { try { - mService.addOnAppsChangedListener(mAppsChangedListener); + mService.addOnAppsChangedListener(mContext.getPackageName(), + mAppsChangedListener); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 0f5ec919710e..ed8143e36f03 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -37,7 +37,6 @@ import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.RemoteException; import android.util.ExceptionUtils; -import android.util.Log; import com.android.internal.util.IndentingPrintWriter; @@ -47,7 +46,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.security.MessageDigest; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -393,13 +391,6 @@ public class PackageInstaller { * Return list of all known install sessions, regardless of the installer. */ public @NonNull List<SessionInfo> getAllSessions() { - final ApplicationInfo info = mContext.getApplicationInfo(); - if ("com.google.android.googlequicksearchbox".equals(info.packageName) - && info.versionCode <= 300400110) { - Log.d(TAG, "Ignoring callback request from old prebuilt"); - return Collections.EMPTY_LIST; - } - try { return mInstaller.getAllSessions(mUserId).getList(); } catch (RemoteException e) { @@ -597,14 +588,6 @@ public class PackageInstaller { * calling thread. */ public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) { - // TODO: remove this temporary guard once we have new prebuilts - final ApplicationInfo info = mContext.getApplicationInfo(); - if ("com.google.android.googlequicksearchbox".equals(info.packageName) - && info.versionCode <= 300400110) { - Log.d(TAG, "Ignoring callback request from old prebuilt"); - return; - } - synchronized (mDelegates) { final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback, handler.getLooper()); @@ -1054,8 +1037,12 @@ public class PackageInstaller { /** {@hide} */ @SystemApi - public void setInstallFlagsDowngrade() { - installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; + public void setAllowDowngrade(boolean allowDowngrade) { + if (allowDowngrade) { + installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; + } else { + installFlags &= ~PackageManager.INSTALL_ALLOW_DOWNGRADE; + } } /** {@hide} */ @@ -1070,8 +1057,13 @@ public class PackageInstaller { } /** {@hide} */ - public void setInstallFlagsDontKillApp() { - installFlags |= PackageManager.INSTALL_DONT_KILL_APP; + @SystemApi + public void setDontKillApp(boolean dontKillApp) { + if (dontKillApp) { + installFlags |= PackageManager.INSTALL_DONT_KILL_APP; + } else { + installFlags &= ~PackageManager.INSTALL_DONT_KILL_APP; + } } /** {@hide} */ diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e1e8a07310ac..c179596a13b0 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -4387,10 +4387,8 @@ public abstract class PackageManager { int badgeDensity); /** - * If the target user is a managed profile of the calling user or if the - * target user is the caller and is itself a managed profile, then this - * returns a badged copy of the given icon to be able to distinguish it from - * the original icon. For badging an arbitrary drawable use + * If the target user is a managed profile, then this returns a badged copy of the given icon + * to be able to distinguish it from the original icon. For badging an arbitrary drawable use * {@link #getUserBadgedDrawableForDensity( * android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}. * <p> @@ -5227,7 +5225,6 @@ public abstract class PackageManager { public abstract void setComponentEnabledSetting(ComponentName componentName, int newState, int flags); - /** * Return the enabled setting for a package component (activity, * receiver, service, provider). This returns the last value set by @@ -5285,6 +5282,16 @@ public abstract class PackageManager { public abstract int getApplicationEnabledSetting(String packageName); /** + * Flush the package restrictions for a given user to disk. This forces the package restrictions + * like component and package enabled settings to be written to disk and avoids the delay that + * is otherwise present when changing those settings. + * + * @param userId Ther userId of the user whose restrictions are to be flushed. + * @hide + */ + public abstract void flushPackageRestrictionsAsUser(int userId); + + /** * Puts the package in a hidden state, which is almost like an uninstalled state, * making the package unavailable, but it doesn't remove the data or the actual * package file. Application can be unhidden by either resetting the hidden state diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 89f2fc4334a4..13ebb823bd78 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -16,6 +16,7 @@ package android.content.pm; +import android.content.ComponentName; import android.content.pm.PackageManager.NameNotFoundException; import java.util.List; @@ -140,4 +141,10 @@ public abstract class PackageManagerInternal { * found on the system. */ public abstract ApplicationInfo getApplicationInfo(String packageName, int userId); + + /** + * Interface to {@link com.android.server.pm.PackageManagerService#getHomeActivitiesAsUser}. + */ + public abstract ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, + int userId); } diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index e41136c0038a..b5c1f30f02ec 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -524,7 +524,7 @@ public class ShortcutInfo implements Parcelable { } /** @hide*/ - public void setFlags(@ShortcutFlags int flags) { + public void replaceFlags(@ShortcutFlags int flags) { mFlags = flags; } diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java index 918c763545fa..4255582f7976 100644 --- a/core/java/android/content/pm/ShortcutServiceInternal.java +++ b/core/java/android/content/pm/ShortcutServiceInternal.java @@ -36,8 +36,7 @@ import java.util.List; */ public abstract class ShortcutServiceInternal { public interface ShortcutChangeListener { - void onShortcutChanged(@NonNull String packageName, - @NonNull List<ShortcutInfo> shortcuts, @UserIdInt int userId); + void onShortcutChanged(@NonNull String packageName, @UserIdInt int userId); } public abstract List<ShortcutInfo> @@ -63,4 +62,6 @@ public abstract class ShortcutServiceInternal { public abstract ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage, @NonNull ShortcutInfo shortcut, int userId); + + public abstract boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId); } diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 7b0b98d4389c..4ad86f7c7019 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -21,6 +21,7 @@ import android.annotation.ArrayRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringRes; +import android.content.res.Configuration.NativeConfig; import android.os.ParcelFileDescriptor; import android.util.Log; import android.util.SparseArray; @@ -796,7 +797,10 @@ public final class AssetManager implements AutoCloseable { /*package*/ static final int STYLE_DATA = 1; /*package*/ static final int STYLE_ASSET_COOKIE = 2; /*package*/ static final int STYLE_RESOURCE_ID = 3; - /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4; + + /* Offset within typed data array for native changingConfigurations. */ + static final int STYLE_CHANGING_CONFIGURATIONS = 4; + /*package*/ static final int STYLE_DENSITY = 5; /*package*/ native static final boolean applyStyle(long theme, int defStyleAttr, int defStyleRes, long xmlParser, @@ -845,7 +849,7 @@ public final class AssetManager implements AutoCloseable { TypedValue outValue, boolean resolve); /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix); - /*package*/ native static final int getThemeChangingConfigurations(long theme); + /*package*/ native static final @NativeConfig int getThemeChangingConfigurations(long theme); private native final long openXmlAssetNative(int cookie, String fileName); diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java index 9e1b312c8372..fb5bfd363ce2 100644 --- a/core/java/android/content/res/ColorStateList.java +++ b/core/java/android/content/res/ColorStateList.java @@ -19,6 +19,7 @@ package android.content.res; import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.Resources.Theme; import android.graphics.Color; @@ -82,7 +83,7 @@ public class ColorStateList extends ComplexColor implements Parcelable { private ColorStateListFactory mFactory; private int[][] mThemeAttrs; - private int mChangingConfigurations; + private @Config int mChangingConfigurations; private int[][] mStateSpecs; private int[] mColors; @@ -251,7 +252,7 @@ public class ColorStateList extends ComplexColor implements Parcelable { int depth; int type; - int changingConfigurations = 0; + @Config int changingConfigurations = 0; int defaultColor = DEFAULT_COLOR; boolean hasUnresolvedAttrs = false; @@ -440,8 +441,8 @@ public class ColorStateList extends ComplexColor implements Parcelable { * * @see android.content.pm.ActivityInfo */ - public int getChangingConfigurations() { - return mChangingConfigurations; + public @Config int getChangingConfigurations() { + return super.getChangingConfigurations() | mChangingConfigurations; } private int modulateColorAlpha(int baseColor, float alphaMod) { @@ -620,7 +621,7 @@ public class ColorStateList extends ComplexColor implements Parcelable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mSrc.mChangingConfigurations; } diff --git a/core/java/android/content/res/ComplexColor.java b/core/java/android/content/res/ComplexColor.java index d96ec62749f0..b297764629cf 100644 --- a/core/java/android/content/res/ComplexColor.java +++ b/core/java/android/content/res/ComplexColor.java @@ -25,6 +25,8 @@ import android.graphics.Color; * {@link android.content.res.ColorStateList} or {@link android.content.res.GradientColor} */ public abstract class ComplexColor { + private int mChangingConfigurations; + /** * @return {@code true} if this ComplexColor changes color based on state, {@code false} * otherwise. @@ -52,4 +54,24 @@ public abstract class ComplexColor { * @hide only for resource preloading */ public abstract ComplexColor obtainForTheme(Theme t); + + /** + * @hide only for resource preloading + */ + final void setBaseChangingConfigurations(int changingConfigurations) { + mChangingConfigurations = changingConfigurations; + } + + /** + * Returns a mask of the configuration parameters for which this color + * may change, requiring that it be re-created. + * + * @return a mask of the changing configuration parameters, as defined by + * {@link android.content.pm.ActivityInfo} + * + * @see android.content.pm.ActivityInfo + */ + public int getChangingConfigurations() { + return mChangingConfigurations; + } } diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index be4f89567f51..9b1d4627807c 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -22,8 +22,11 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.ActivityInfo; +import android.content.pm.ActivityInfo.Config; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -32,6 +35,8 @@ import android.util.LocaleList; import android.view.View; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Locale; @@ -663,6 +668,28 @@ public final class Configuration implements Parcelable, Comparable<Configuration */ public int seq; + /** @hide */ + @IntDef(flag = true, + value = { + NATIVE_CONFIG_MCC, + NATIVE_CONFIG_MNC, + NATIVE_CONFIG_LOCALE, + NATIVE_CONFIG_TOUCHSCREEN, + NATIVE_CONFIG_KEYBOARD, + NATIVE_CONFIG_KEYBOARD_HIDDEN, + NATIVE_CONFIG_NAVIGATION, + NATIVE_CONFIG_ORIENTATION, + NATIVE_CONFIG_DENSITY, + NATIVE_CONFIG_SCREEN_SIZE, + NATIVE_CONFIG_VERSION, + NATIVE_CONFIG_SCREEN_LAYOUT, + NATIVE_CONFIG_UI_MODE, + NATIVE_CONFIG_SMALLEST_SCREEN_SIZE, + NATIVE_CONFIG_LAYOUTDIR, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface NativeConfig {} + /** @hide Native-specific bit mask for MCC config; DO NOT USE UNLESS YOU ARE SURE. */ public static final int NATIVE_CONFIG_MCC = 0x0001; /** @hide Native-specific bit mask for MNC config; DO NOT USE UNLESS YOU ARE SURE. */ @@ -917,14 +944,13 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** - * Copy the fields from delta into this Configuration object, keeping - * track of which ones have changed. Any undefined fields in - * <var>delta</var> are ignored and not copied in to the current - * Configuration. - * @return Returns a bit mask of the changed fields, as per - * {@link #diff}. + * Copies the fields from delta into this Configuration object, keeping + * track of which ones have changed. Any undefined fields in {@code delta} + * are ignored and not copied in to the current Configuration. + * + * @return a bit mask of the changed fields, as per {@link #diff} */ - public int updateFrom(Configuration delta) { + public @Config int updateFrom(@NonNull Configuration delta) { int changed = 0; if (delta.fontScale > 0 && fontScale != delta.fontScale) { changed |= ActivityInfo.CONFIG_FONT_SCALE; @@ -1171,17 +1197,19 @@ public final class Configuration implements Parcelable, Comparable<Configuration } /** - * Determine if a new resource needs to be loaded from the bit set of + * Determines if a new resource needs to be loaded from the bit set of * configuration changes returned by {@link #updateFrom(Configuration)}. * - * @param configChanges The mask of changes configurations as returned by - * {@link #updateFrom(Configuration)}. - * @param interestingChanges The configuration changes that the resource - * can handled, as given in {@link android.util.TypedValue#changingConfigurations}. - * - * @return Return true if the resource needs to be loaded, else false. + * @param configChanges the mask of changes configurations as returned by + * {@link #updateFrom(Configuration)} + * @param interestingChanges the configuration changes that the resource + * can handle as given in + * {@link android.util.TypedValue#changingConfigurations} + * @return {@code true} if the resource needs to be loaded, {@code false} + * otherwise */ - public static boolean needNewResources(int configChanges, int interestingChanges) { + public static boolean needNewResources(@Config int configChanges, + @Config int interestingChanges) { return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0; } diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java index 40d2a82b7b83..70290c4b0595 100644 --- a/core/java/android/content/res/ConfigurationBoundResourceCache.java +++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java @@ -16,6 +16,8 @@ package android.content.res; +import android.content.pm.ActivityInfo.Config; + /** * A Cache class which can be used to cache resource objects that are easy to clone but more * expensive to inflate. @@ -42,7 +44,7 @@ public class ConfigurationBoundResourceCache<T> extends ThemedResourceCache<Cons } @Override - public boolean shouldInvalidateEntry(ConstantState<T> entry, int configChanges) { + public boolean shouldInvalidateEntry(ConstantState<T> entry, @Config int configChanges) { return Configuration.needNewResources(configChanges, entry.getChangingConfigurations()); } } diff --git a/core/java/android/content/res/ConstantState.java b/core/java/android/content/res/ConstantState.java index ee609df2e232..09d4a59d1418 100644 --- a/core/java/android/content/res/ConstantState.java +++ b/core/java/android/content/res/ConstantState.java @@ -15,6 +15,8 @@ */ package android.content.res; +import android.content.pm.ActivityInfo.Config; + /** * A cache class that can provide new instances of a particular resource which may change * depending on the current {@link Resources.Theme} or {@link Configuration}. @@ -33,7 +35,7 @@ abstract public class ConstantState<T> { * Return a bit mask of configuration changes that will impact * this resource (and thus require completely reloading it). */ - abstract public int getChangingConfigurations(); + abstract public @Config int getChangingConfigurations(); /** * Create a new instance without supplying resources the caller diff --git a/core/java/android/content/res/GradientColor.java b/core/java/android/content/res/GradientColor.java index cc46cbd43258..f29656abe6c3 100644 --- a/core/java/android/content/res/GradientColor.java +++ b/core/java/android/content/res/GradientColor.java @@ -20,6 +20,7 @@ import android.annotation.ColorInt; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.Resources.Theme; import com.android.internal.R; @@ -83,7 +84,7 @@ public class GradientColor extends ComplexColor { /** Lazily-created factory for this GradientColor. */ private GradientColorFactory mFactory; - private int mChangingConfigurations; + private @Config int mChangingConfigurations; private int mDefaultColor; // After parsing all the attributes from XML, this shader is the ultimate result containing @@ -506,7 +507,7 @@ public class GradientColor extends ComplexColor { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mSrc.mChangingConfigurations; } @@ -541,6 +542,19 @@ public class GradientColor extends ComplexColor { return clone; } + /** + * Returns a mask of the configuration parameters for which this gradient + * may change, requiring that it be re-created. + * + * @return a mask of the changing configuration parameters, as defined by + * {@link android.content.pm.ActivityInfo} + * + * @see android.content.pm.ActivityInfo + */ + public int getChangingConfigurations() { + return super.getChangingConfigurations() | mChangingConfigurations; + } + private void applyTheme(Theme t) { if (mThemeAttrs != null) { applyRootAttrsTheme(t); diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 0858cb8b9305..a36401098e27 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -15,6 +15,9 @@ */ package android.content.res; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import android.animation.Animator; import android.animation.StateListAnimator; import android.annotation.AnyRes; @@ -26,6 +29,7 @@ import android.annotation.RawRes; import android.annotation.StyleRes; import android.annotation.StyleableRes; import android.content.pm.ActivityInfo; +import android.content.pm.ActivityInfo.Config; import android.content.res.Resources.NotFoundException; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -40,8 +44,6 @@ import android.util.LongSparseArray; import android.util.Slog; import android.util.TypedValue; import android.util.Xml; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; import java.io.InputStream; import java.util.Arrays; @@ -65,7 +67,7 @@ public class ResourcesImpl { private static final boolean TRACE_FOR_PRELOAD = false; private static final boolean TRACE_FOR_MISS_PRELOAD = false; - private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigToNative( + private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigJavaToNative( ActivityInfo.CONFIG_LAYOUT_DIRECTION); private static final int ID_OTHER = 0x01000004; @@ -331,7 +333,7 @@ public class ResourcesImpl { // the framework. mCompatibilityInfo.applyToDisplayMetrics(mMetrics); - final int configChanges = calcConfigChanges(config); + final @Config int configChanges = calcConfigChanges(config); LocaleList locales = mConfiguration.getLocales(); if (locales.isEmpty()) { @@ -395,26 +397,30 @@ public class ResourcesImpl { } /** - * Called by ConfigurationBoundResourceCacheTest. + * Applies the new configuration, returning a bitmask of the changes + * between the old and new configurations. + * + * @param config the new configuration + * @return bitmask of config changes */ - public int calcConfigChanges(Configuration config) { - int configChanges = 0xfffffff; - if (config != null) { - mTmpConfig.setTo(config); - int density = config.densityDpi; - if (density == Configuration.DENSITY_DPI_UNDEFINED) { - density = mMetrics.noncompatDensityDpi; - } + public @Config int calcConfigChanges(@Nullable Configuration config) { + if (config == null) { + // If there is no configuration, assume all flags have changed. + return 0xFFFFFFFF; + } + + mTmpConfig.setTo(config); + int density = config.densityDpi; + if (density == Configuration.DENSITY_DPI_UNDEFINED) { + density = mMetrics.noncompatDensityDpi; + } - mCompatibilityInfo.applyToConfiguration(density, mTmpConfig); + mCompatibilityInfo.applyToConfiguration(density, mTmpConfig); - if (mTmpConfig.getLocales().isEmpty()) { - mTmpConfig.setLocales(LocaleList.getDefault()); - } - configChanges = mConfiguration.updateFrom(mTmpConfig); - configChanges = ActivityInfo.activityInfoConfigToNative(configChanges); + if (mTmpConfig.getLocales().isEmpty()) { + mTmpConfig.setLocales(LocaleList.getDefault()); } - return configChanges; + return mConfiguration.updateFrom(mTmpConfig); } /** @@ -593,8 +599,8 @@ public class ResourcesImpl { } } - private boolean verifyPreloadConfig(int changingConfigurations, int allowVarying, - int resourceId, String name) { + private boolean verifyPreloadConfig(@Config int changingConfigurations, + @Config int allowVarying, @AnyRes int resourceId, @Nullable String name) { // We allow preloading of resources even if they vary by font scale (which // doesn't impact resource selection) or density (which we handle specially by // simply turning off all preloading), as well as any other configs specified @@ -707,9 +713,11 @@ public class ResourcesImpl { } if (complexColor != null) { + complexColor.setBaseChangingConfigurations(value.changingConfigurations); + if (mPreloading) { - if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId, - "color")) { + if (verifyPreloadConfig(complexColor.getChangingConfigurations(), + 0, value.resourceId, "color")) { sPreloadedComplexColors.put(key, complexColor.getConstantState()); } } else { @@ -1104,7 +1112,7 @@ public class ResourcesImpl { return mAssets.getStyleAttributes(getAppliedStyleResId()); } - int getChangingConfigurations() { + @Config int getChangingConfigurations() { synchronized (mKey) { final int nativeChangingConfig = AssetManager.getThemeChangingConfigurations(mTheme); diff --git a/core/java/android/content/res/ThemedResourceCache.java b/core/java/android/content/res/ThemedResourceCache.java index 9a2d061474e6..f1b1e74a697e 100644 --- a/core/java/android/content/res/ThemedResourceCache.java +++ b/core/java/android/content/res/ThemedResourceCache.java @@ -18,6 +18,7 @@ package android.content.res; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.Resources.Theme; import android.content.res.Resources.ThemeKey; import android.util.LongSparseArray; @@ -115,7 +116,7 @@ abstract class ThemedResourceCache<T> { * * @param configChanges a bitmask of configuration changes */ - public void onConfigurationChange(int configChanges) { + public void onConfigurationChange(@Config int configChanges) { prune(configChanges); } @@ -192,7 +193,7 @@ abstract class ThemedResourceCache<T> { * simply prune missing weak references * @return {@code true} if the cache is completely empty after pruning */ - private boolean prune(int configChanges) { + private boolean prune(@Config int configChanges) { synchronized (this) { if (mThemedEntries != null) { for (int i = mThemedEntries.size() - 1; i >= 0; i--) { @@ -211,7 +212,7 @@ abstract class ThemedResourceCache<T> { } private boolean pruneEntriesLocked(@Nullable LongSparseArray<WeakReference<T>> entries, - int configChanges) { + @Config int configChanges) { if (entries == null) { return true; } @@ -226,7 +227,7 @@ abstract class ThemedResourceCache<T> { return entries.size() == 0; } - private boolean pruneEntryLocked(@Nullable T entry, int configChanges) { + private boolean pruneEntryLocked(@Nullable T entry, @Config int configChanges) { return entry == null || (configChanges != 0 && shouldInvalidateEntry(entry, configChanges)); } diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index 022bdfb9309e..f6ac0bac125a 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -20,6 +20,8 @@ import android.annotation.AnyRes; import android.annotation.ColorInt; import android.annotation.Nullable; import android.annotation.StyleableRes; +import android.content.pm.ActivityInfo; +import android.content.pm.ActivityInfo.Config; import android.graphics.drawable.Drawable; import android.os.StrictMode; import android.util.AttributeSet; @@ -252,7 +254,8 @@ public class TypedArray { * @throws RuntimeException if the TypedArray has already been recycled. * @hide */ - public String getNonConfigurationString(@StyleableRes int index, int allowedChangingConfigs) { + public String getNonConfigurationString(@StyleableRes int index, + @Config int allowedChangingConfigs) { if (mRecycled) { throw new RuntimeException("Cannot make calls to a recycled instance!"); } @@ -260,7 +263,9 @@ public class TypedArray { index *= AssetManager.STYLE_NUM_ENTRIES; final int[] data = mData; final int type = data[index+AssetManager.STYLE_TYPE]; - if ((data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS]&~allowedChangingConfigs) != 0) { + final @Config int changingConfigs = ActivityInfo.activityInfoConfigNativeToJava( + data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]); + if ((changingConfigs & ~allowedChangingConfigs) != 0) { return null; } if (type == TypedValue.TYPE_NULL) { @@ -1155,12 +1160,12 @@ public class TypedArray { * @throws RuntimeException if the TypedArray has already been recycled. * @see android.content.pm.ActivityInfo */ - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { if (mRecycled) { throw new RuntimeException("Cannot make calls to a recycled instance!"); } - int changingConfig = 0; + @Config int changingConfig = 0; final int[] data = mData; final int N = length(); @@ -1170,7 +1175,8 @@ public class TypedArray { if (type == TypedValue.TYPE_NULL) { continue; } - changingConfig |= data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]; + changingConfig |= ActivityInfo.activityInfoConfigNativeToJava( + data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]); } return changingConfig; } @@ -1185,7 +1191,8 @@ public class TypedArray { outValue.data = data[index+AssetManager.STYLE_DATA]; outValue.assetCookie = data[index+AssetManager.STYLE_ASSET_COOKIE]; outValue.resourceId = data[index+AssetManager.STYLE_RESOURCE_ID]; - outValue.changingConfigurations = data[index+AssetManager.STYLE_CHANGING_CONFIGURATIONS]; + outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava( + data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]); outValue.density = data[index+AssetManager.STYLE_DENSITY]; outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null; return true; diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index c4afbfb4f2fc..b75e65391c5e 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -54,10 +54,9 @@ public class SystemSensorManager extends SensorManager { private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list); private static native boolean nativeIsDataInjectionEnabled(long nativeInstance); + private static final Object sLock = new Object(); private static boolean sSensorModuleInitialized = false; - private static InjectEventQueue mInjectEventQueue = null; - - private final Object mLock = new Object(); + private static InjectEventQueue sInjectEventQueue = null; private final ArrayList<Sensor> mFullSensorsList = new ArrayList<>(); private List<Sensor> mFullDynamicSensorsList = new ArrayList<>(); @@ -84,24 +83,24 @@ public class SystemSensorManager extends SensorManager { /** {@hide} */ public SystemSensorManager(Context context, Looper mainLooper) { - mMainLooper = mainLooper; - mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion; - mContext = context; - mNativeInstance = nativeCreate(context.getOpPackageName()); - - synchronized(mLock) { + synchronized(sLock) { if (!sSensorModuleInitialized) { sSensorModuleInitialized = true; nativeClassInit(); } + } - // initialize the sensor list - for (int index = 0;;++index) { - Sensor sensor = new Sensor(); - if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break; - mFullSensorsList.add(sensor); - mHandleToSensor.put(sensor.getHandle(), sensor); - } + mMainLooper = mainLooper; + mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion; + mContext = context; + mNativeInstance = nativeCreate(context.getOpPackageName()); + + // initialize the sensor list + for (int index = 0;;++index) { + Sensor sensor = new Sensor(); + if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break; + mFullSensorsList.add(sensor); + mHandleToSensor.put(sensor.getHandle(), sensor); } } @@ -257,7 +256,7 @@ public class SystemSensorManager extends SensorManager { } protected boolean initDataInjectionImpl(boolean enable) { - synchronized (mLock) { + synchronized (sLock) { if (enable) { boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance); // The HAL does not support injection OR SensorService hasn't been set in DI mode. @@ -266,15 +265,15 @@ public class SystemSensorManager extends SensorManager { return false; } // Initialize a client for data_injection. - if (mInjectEventQueue == null) { - mInjectEventQueue = new InjectEventQueue(mMainLooper, this, + if (sInjectEventQueue == null) { + sInjectEventQueue = new InjectEventQueue(mMainLooper, this, mContext.getPackageName()); } } else { // If data injection is being disabled clean up the native resources. - if (mInjectEventQueue != null) { - mInjectEventQueue.dispose(); - mInjectEventQueue = null; + if (sInjectEventQueue != null) { + sInjectEventQueue.dispose(); + sInjectEventQueue = null; } } return true; @@ -283,17 +282,17 @@ public class SystemSensorManager extends SensorManager { protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy, long timestamp) { - synchronized (mLock) { - if (mInjectEventQueue == null) { + synchronized (sLock) { + if (sInjectEventQueue == null) { Log.e(TAG, "Data injection mode not activated before calling injectSensorData"); return false; } - int ret = mInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy, + int ret = sInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy, timestamp); // If there are any errors in data injection clean up the native resources. if (ret != 0) { - mInjectEventQueue.dispose(); - mInjectEventQueue = null; + sInjectEventQueue.dispose(); + sInjectEventQueue = null; } return ret == 0; } diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java index 6cc7fece2898..dfa19b07040d 100644 --- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java +++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java @@ -1196,7 +1196,7 @@ public final class StreamConfigurationMap { * * <p>In particular these formats are converted: * <ul> - * <li>ImageFormat.JPEG => HAL_DATASPACE_JFIF + * <li>ImageFormat.JPEG => HAL_DATASPACE_V0_JFIF * <li>ImageFormat.DEPTH_POINT_CLOUD => HAL_DATASPACE_DEPTH * <li>ImageFormat.DEPTH16 => HAL_DATASPACE_DEPTH * <li>others => HAL_DATASPACE_UNKNOWN @@ -1223,7 +1223,7 @@ public final class StreamConfigurationMap { static int imageFormatToDataspace(int format) { switch (format) { case ImageFormat.JPEG: - return HAL_DATASPACE_JFIF; + return HAL_DATASPACE_V0_JFIF; case ImageFormat.DEPTH_POINT_CLOUD: case ImageFormat.DEPTH16: return HAL_DATASPACE_DEPTH; @@ -1633,8 +1633,16 @@ public final class StreamConfigurationMap { private static final int HAL_PIXEL_FORMAT_Y16 = 0x20363159; + private static final int HAL_DATASPACE_STANDARD_SHIFT = 16; + private static final int HAL_DATASPACE_TRANSFER_SHIFT = 22; + private static final int HAL_DATASPACE_RANGE_SHIFT = 27; + private static final int HAL_DATASPACE_UNKNOWN = 0x0; - private static final int HAL_DATASPACE_JFIF = 0x101; + private static final int HAL_DATASPACE_V0_JFIF = + (2 << HAL_DATASPACE_STANDARD_SHIFT) | + (3 << HAL_DATASPACE_TRANSFER_SHIFT) | + (1 << HAL_DATASPACE_RANGE_SHIFT); + private static final int HAL_DATASPACE_DEPTH = 0x1000; private static final long DURATION_20FPS_NS = 50000000L; diff --git a/core/java/android/hardware/location/ContextHubInfo.aidl b/core/java/android/hardware/location/ContextHubInfo.aidl index 1a9221a02cc3..8de03daf203d 100644 --- a/core/java/android/hardware/location/ContextHubInfo.aidl +++ b/core/java/android/hardware/location/ContextHubInfo.aidl @@ -15,7 +15,7 @@ */ package android.hardware.location; -/* -@hide -*/ +/** + * @hide + */ parcelable ContextHubInfo; diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java index e47c541ee62b..644e29fcaedf 100644 --- a/core/java/android/hardware/location/ContextHubInfo.java +++ b/core/java/android/hardware/location/ContextHubInfo.java @@ -23,7 +23,7 @@ import java.util.Arrays; /** * @hide - */ + */ @SystemApi public class ContextHubInfo { private int mId; @@ -58,6 +58,8 @@ public class ContextHubInfo { * set the context hub unique identifer * * @param id - unique system wide identifier for the hub + * + * @hide */ public void setId(int id) { mId = id; @@ -75,7 +77,9 @@ public class ContextHubInfo { /** * set a string as the hub name * - * @param String - the name for the hub + * @param name - the name for the hub + * + * @hide */ public void setName(String name) { mName = name; @@ -93,7 +97,9 @@ public class ContextHubInfo { /** * set a string as the vendor name * - * @param String - a name for the vendor + * @param vendor - a name for the vendor + * + * @hide */ public void setVendor(String vendor) { mVendor = vendor; @@ -111,7 +117,9 @@ public class ContextHubInfo { /** * set tool chain string * - * @param String - description of the tool chain + * @param toolchain - description of the tool chain + * + * @hide */ public void setToolchain(String toolchain) { mToolchain = toolchain; @@ -130,6 +138,8 @@ public class ContextHubInfo { * set platform version * * @param platformVersion - platform version number + * + * @hide */ public void setPlatformVersion(int platformVersion) { mPlatformVersion = platformVersion; @@ -148,6 +158,8 @@ public class ContextHubInfo { * set platform software version * * @param staticSwVersion - platform static s/w version number + * + * @hide */ public void setStaticSwVersion(int staticSwVersion) { mStaticSwVersion = staticSwVersion; @@ -166,6 +178,8 @@ public class ContextHubInfo { * set the tool chain version number * * @param toolchainVersion - tool chain version number + * + * @hide */ public void setToolchainVersion(int toolchainVersion) { mToolchainVersion = toolchainVersion; @@ -184,6 +198,8 @@ public class ContextHubInfo { * set the peak mips that this hub can support * * @param peakMips - peak mips this hub can deliver + * + * @hide */ public void setPeakMips(float peakMips) { mPeakMips = peakMips; @@ -206,6 +222,8 @@ public class ContextHubInfo { * Set the power consumed by the hub in stopped state * * @param stoppedPowerDrawMw - stopped power in milli watts + * + * @hide */ public void setStoppedPowerDrawMw(float stoppedPowerDrawMw) { mStoppedPowerDrawMw = stoppedPowerDrawMw; @@ -230,6 +248,8 @@ public class ContextHubInfo { * Set the sleep power draw in milliwatts * * @param sleepPowerDrawMw - sleep power draw in milliwatts. + * + * @hide */ public void setSleepPowerDrawMw(float sleepPowerDrawMw) { mSleepPowerDrawMw = sleepPowerDrawMw; @@ -250,6 +270,8 @@ public class ContextHubInfo { * * @param peakPowerDrawMw - peak power draw of the hub in * milliwatts. + * + * @hide */ public void setPeakPowerDrawMw(float peakPowerDrawMw) { mPeakPowerDrawMw = peakPowerDrawMw; @@ -281,6 +303,8 @@ public class ContextHubInfo { * set the supported sensors on this hub * * @param supportedSensors - supported sensors on this hub + * + * @hide */ public void setSupportedSensors(int[] supportedSensors) { mSupportedSensors = Arrays.copyOf(supportedSensors, supportedSensors.length); @@ -292,6 +316,8 @@ public class ContextHubInfo { * @param memoryRegions - memory regions information * * @see MemoryRegion + * + * @hide */ public void setMemoryRegions(MemoryRegion[] memoryRegions) { mMemoryRegions = Arrays.copyOf(memoryRegions, memoryRegions.length); diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index 301b2e49a19c..8deded259194 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -16,26 +16,19 @@ package android.hardware.location; import android.annotation.SystemApi; -import android.hardware.location.NanoAppInstanceInfo; -import android.content.ComponentName; import android.content.Context; -import android.content.ServiceConnection; -import android.Manifest; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; -import java.util.ArrayList; -import java.util.HashMap; - /** - * A class that exposes the Context hubs on a device to - * applicaions. + * A class that exposes the Context hubs on a device to applications. * - * Please not that this class is not expected to be used by - * unbundled applications. Also, calling applications are - * expected to have LOCTION_HARDWARE premissions to use this - * class. + * Please note that this class is not expected to be used by unbundled applications. Also, calling + * applications are expected to have LOCATION_HARDWARE permissions to use this class. * * @hide */ @@ -43,18 +36,14 @@ import java.util.HashMap; public final class ContextHubManager { private static final String TAG = "ContextHubManager"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE; - private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '" - + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware"; - private Context mContext; + private final Looper mMainLooper; private IContextHubService mContextHubService; - private boolean mContextHubConnected; + private ContextHubCallback mCallback; + private Handler mCallbackHandler; /** - * A special context hub identifer meaning any possible hub on - * the system. + * A special context hub identifier meaning any possible hub on the system. */ public static final int ANY_HUB = -1; /** @@ -70,19 +59,37 @@ public final class ContextHubManager { */ public static final int MSG_DATA_SEND = 3; + /** + * An interface to receive asynchronous communication from the context hub. + */ + public abstract static class ContextHubCallback { + protected ContextHubCallback() {} + + /** + * Callback function called on message receipt from context hub. + * + * @param hubHandle Handle (system-wide unique identifier) of the hub of the message. + * @param nanoAppHandle Handle (unique identifier) for the app that sent the message. + * @param message The context hub message. + * + * @see ContextHubMessage + */ + public abstract void onMessageReceipt( + int hubHandle, + int nanoAppHandle, + ContextHubMessage message); + } /** * Get a handle to all the context hubs in the system * @return array of context hub handles */ - public int[] getContexthubHandles() { + public int[] getContextHubHandles() { int[] retVal = null; - if(mContextHubConnected) { - try { - retVal = mContextHubService.getContextHubHandles(); - }catch (RemoteException e) { - Log.e (TAG, "Could not fetch context hub handles :" + e.toString()); - } + try { + retVal = getBinder().getContextHubHandles(); + } catch (RemoteException e) { + Log.e(TAG, "Could not fetch context hub handles : " + e); } return retVal; } @@ -90,27 +97,24 @@ public final class ContextHubManager { /** * Get more information about a specific hub. * - * @param contexthubHandle Handle of context hub - * - * @return ContextHubInfo returned information about the hub + * @param hubHandle Handle (system-wide unique identifier) of a context hub. + * @return ContextHubInfo Information about the requested context hub. * * @see ContextHubInfo */ - public ContextHubInfo getContexthubInfo(int contexthubHandle) { + public ContextHubInfo getContextHubInfo(int hubHandle) { ContextHubInfo retVal = null; - if(mContextHubConnected) { - try { - retVal = mContextHubService.getContextHubInfo(contexthubHandle); - }catch (RemoteException e) { - Log.e (TAG, "Could not fetch context hub info :" + e.toString()); - } + try { + retVal = getBinder().getContextHubInfo(hubHandle); + } catch (RemoteException e) { + Log.e(TAG, "Could not fetch context hub info :" + e); } - return(retVal); + return retVal; } /** - * Load a nanoapp on a specified context hub + * Load a nano app on a specified context hub. * * @param hubHandle handle of context hub to load the app on. * @param app the nanoApp to load on the hub @@ -122,13 +126,14 @@ public final class ContextHubManager { */ public int loadNanoApp(int hubHandle, NanoApp app) { int retVal = -1; + if (app == null) { + return retVal; + } - if(mContextHubConnected) { - try { - retVal = mContextHubService.loadNanoApp(hubHandle, app); - }catch (RemoteException e) { - Log.e (TAG, "Could not fetch load nanoApp :" + e.toString()); - } + try { + retVal = getBinder().loadNanoApp(hubHandle, app); + } catch (RemoteException e) { + Log.e(TAG, "Could not fetch load nanoApp :" + e); } return retVal; @@ -137,19 +142,17 @@ public final class ContextHubManager { /** * Unload a specified nanoApp * - * @param nanoAppInstanceHandle handle of the nanoApp to load + * @param nanoAppHandle handle of the nanoApp to load * - * @return int 0 on success, -1 otherewise + * @return int 0 on success, -1 otherwise */ - public int unloadNanoApp(int nanoAppInstanceHandle) { + public int unloadNanoApp(int nanoAppHandle) { int retVal = -1; - if(mContextHubConnected) { - try { - retVal = mContextHubService.unloadNanoApp(nanoAppInstanceHandle); - }catch (RemoteException e) { - Log.e (TAG, "Could not fetch unload nanoApp :" + e.toString()); - } + try { + retVal = getBinder().unloadNanoApp(nanoAppHandle); + } catch (RemoteException e) { + Log.e(TAG, "Could not fetch unload nanoApp :" + e); } return retVal; @@ -158,22 +161,18 @@ public final class ContextHubManager { /** * get information about the nano app instance * - * @param nanoAppInstanceHandle handle of the nanoAppInstance - * - * @return NanoAppInstanceInfo Inforamtion about the nano app - * instance. + * @param nanoAppHandle handle of the nanoAppInstance + * @return NanoAppInstanceInfo Information about the nano app instance. * * @see NanoAppInstanceInfo */ - public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) { + public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) { NanoAppInstanceInfo retVal = null; - if(mContextHubConnected) { - try { - retVal = mContextHubService.getNanoAppInstanceInfo(nanoAppInstanceHandle); - }catch (RemoteException e) { - Log.e (TAG, "Could not fetch nanoApp info :" + e.toString()); - } + try { + retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle); + } catch (RemoteException e) { + Log.e(TAG, "Could not fetch nanoApp info :" + e); } return retVal; @@ -187,92 +186,143 @@ public final class ContextHubManager { * * @see NanoAppFilter * - * @return Integer[] Array of handles to any found nano apps + * @return int[] Array of handles to any found nano apps */ - public Integer[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) { - int[] temp; - Integer[] retVal = null; - - if(mContextHubConnected) { - try { - temp = mContextHubService.findNanoAppOnHub(hubHandle, filter); - retVal = new Integer[temp.length]; - for (int i = 0; i < temp.length; i++) { - retVal[i] = temp[i]; - } - }catch (RemoteException e) { - Log.e (TAG, "Could not query nanoApp instance :" + e.toString()); - } + public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) { + int[] retVal = null; + try { + retVal = getBinder().findNanoAppOnHub(hubHandle, filter); + } catch (RemoteException e) { + Log.e(TAG, "Could not query nanoApp instance :" + e); } - return retVal; } /** - * Send a message to a spcific nano app instance on a context - * hub - * + * Send a message to a specific nano app instance on a context hub. * * @param hubHandle handle of the hub to send the message to * @param nanoAppHandle handle of the nano app to send to - * @param msg Message to be sent + * @param message Message to be sent * * @see ContextHubMessage * * @return int 0 on success, -1 otherwise */ - public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) { + public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) { int retVal = -1; - if(mContextHubConnected) { - try { - retVal = mContextHubService.sendMessage(hubHandle, nanoAppHandle, msg); - }catch (RemoteException e) { - Log.e (TAG, "Could not fetch send message :" + e.toString()); - } + try { + retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message); + } catch (RemoteException e) { + Log.e(TAG, "Could not fetch send message :" + e.toString()); } return retVal; } - private void checkPermissions() { - mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE); + /** + * Set a callback to receive messages from the context hub + * + * @param callback Callback object + * + * @see ContextHubCallback + * + * @return int 0 on success, -1 otherwise + */ + public int registerContextHubCallback(ContextHubCallback callback) { + return registerContextHubCallback(callback, null); + } + + /** + * Set a callback to receive messages from the context hub + * + * @param callback Callback object + * @param handler Handler object + * + * @see ContextHubCallback + * + * @return int 0 on success, -1 otherwise + */ + public int registerContextHubCallback(ContextHubCallback callback, Handler handler) { + synchronized(this) { + if (mCallback != null) { + Log.e(TAG, "Max number of callbacks reached!"); + return -1; + } + mCallback = callback; + mCallbackHandler = handler; + } + return 0; + } + + /** + * Unregister a callback for receive messages from the context hub. + * + * @see ContextHubCallback + * + * @param callback method to deregister + * + * @return int 0 on success, -1 otherwise + */ + public int unregisterContextHubCallback(ContextHubCallback callback) { + synchronized(this) { + if (callback != mCallback) { + Log.e(TAG, "Cannot recognize callback!"); + return -1; + } + + mCallback = null; + mCallbackHandler = null; + } + return 0; } private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() { @Override - public void onMessageReceipt(int hubId, int nanoAppId, ContextHubMessage msg) throws RemoteException { - + public void onMessageReceipt(final int hubId, final int nanoAppId, + final ContextHubMessage message) { + if (mCallback != null) { + synchronized(this) { + final ContextHubCallback callback = mCallback; + Handler handler = mCallbackHandler == null ? + new Handler(mMainLooper) : mCallbackHandler; + handler.post(new Runnable() { + @Override + public void run() { + callback.onMessageReceipt(hubId, nanoAppId, message); + } + }); + } + } else { + Log.d(TAG, "Context hub manager client callback is NULL"); + } } }; - private ContextHubManager(Context context) { - checkPermissions(); - mContext = context; - mContextHubConnected = false; - } + /** @hide */ + public ContextHubManager(Context context, Looper mainLooper) { + mMainLooper = mainLooper; - private ServiceConnection mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - mContextHubService = IContextHubService.Stub.asInterface(service); - mContextHubConnected = true; + IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE); + if (b != null) { + mContextHubService = IContextHubService.Stub.asInterface(b); - // Register our Callback try { - mContextHubService.registerCallBack(mClientCallback); + getBinder().registerCallback(mClientCallback); } catch (RemoteException e) { - Log.e(TAG, "Could not register callback with context hub service :" + e.toString()); + Log.e(TAG, "Could not register callback:" + e); } - Log.d(TAG, "contexthub manager connected to " + name.toString()); - } - @Override - public void onServiceDisconnected(ComponentName name) { - mContextHubService = null; - mContextHubConnected = false; - Log.d(TAG, "contexthub manager disconnected from " + name.toString()); + } else { + Log.d(TAG, "failed to getService"); } - }; + } + private IContextHubService getBinder() throws RemoteException { + if (mContextHubService == null) { + throw new RemoteException("Service not connected."); + } + return mContextHubService; + } } diff --git a/core/java/android/hardware/location/ContextHubMessage.aidl b/core/java/android/hardware/location/ContextHubMessage.aidl index 915f1ec683c9..56704e70ba5f 100644 --- a/core/java/android/hardware/location/ContextHubMessage.aidl +++ b/core/java/android/hardware/location/ContextHubMessage.aidl @@ -15,8 +15,8 @@ */ package android.hardware.location; -/* -@hide -*/ +/** + * @hide + */ parcelable ContextHubMessage; diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java index a2a13c6f8289..274babe6a930 100644 --- a/core/java/android/hardware/location/ContextHubService.java +++ b/core/java/android/hardware/location/ContextHubService.java @@ -16,10 +16,8 @@ package android.hardware.location; -import android.app.Service; +import android.Manifest; import android.content.Context; -import android.content.Intent; -import android.os.IBinder; import android.os.RemoteException; import android.util.Log; @@ -29,175 +27,174 @@ import java.util.HashMap; /** * @hide */ -public class ContextHubService extends Service { +public class ContextHubService extends IContextHubService.Stub { private static final String TAG = "ContextHubService"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE; + private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '" + + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware"; - private static ContextHubService sSingletonInstance; - private static final Object sSingletonInstanceLock = new Object(); + public static final String CONTEXTHUB_SERVICE = "contexthub_service"; + + private final Context mContext; - private HashMap<Integer, ContextHubInfo> mHubHash; private HashMap<Integer, NanoAppInstanceInfo> mNanoAppHash; - private ContextHubInfo[] mContexthubInfo; + private ContextHubInfo[] mContextHubInfo; + private IContextHubCallback mCallback; + + public ContextHubService(Context context) { + mContext = context; + mContextHubInfo = nativeInitialize(); + for (int i = 0; i < mContextHubInfo.length; i++) { + Log.v(TAG, "ContextHub[" + i + "] id: " + mContextHubInfo[i].getId() + + ", name: " + mContextHubInfo[i].getName()); + } + } private native int nativeSendMessage(int[] header, byte[] data); private native ContextHubInfo[] nativeInitialize(); - private int onMessageReceipt(int[] header, byte[] data) { + @Override + public int registerCallback(IContextHubCallback callback) throws RemoteException{ + checkPermissions(); + mCallback = callback; return 0; } - private void initialize() { - mContexthubInfo = nativeInitialize(); - mHubHash = new HashMap<Integer, ContextHubInfo>(); - for (int i = 0; i < mContexthubInfo.length; i++) { - mHubHash.put(i + 1, mContexthubInfo[i]); // Avoiding zero + private int onMessageReceipt(int[] header, byte[] data) { + if (mCallback != null) { + // TODO : Defend against unexpected header sizes + // Add abstraction for magic numbers + // onMessageRecipt should pass the right arguments + ContextHubMessage msg = new ContextHubMessage(header[0], header[1], data); + + try { + mCallback.onMessageReceipt(0, 0, msg); + } catch (Exception e) { + Log.e(TAG, "Exception " + e + " when calling remote callback"); + return -1; + } + } else { + Log.d(TAG, "Message Callback is NULL"); } - } - private ContextHubService(Context context) { - initialize(); - Log.d(TAG, "Created from " + context.toString()); + return 0; } - public static ContextHubService getInstance(Context context) { - synchronized (sSingletonInstanceLock) { - if (sSingletonInstance == null) { - sSingletonInstance = new ContextHubService(context); - } - return sSingletonInstance; + @Override + public int[] getContextHubHandles() throws RemoteException { + checkPermissions(); + int [] returnArray = new int[mContextHubInfo.length]; + + for (int i = 0; i < returnArray.length; ++i) { + returnArray[i] = i + 1; //valid handles from 1...n + Log.d(TAG, String.format("Hub %s is mapped to %d", + mContextHubInfo[i].getName(), returnArray[i])); } + + return returnArray; } @Override - public void onCreate() { - super.onCreate(); + public ContextHubInfo getContextHubInfo(int contextHubHandle) throws RemoteException { + checkPermissions(); + contextHubHandle -= 1; + if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) { + return null; // null means fail + } + + return mContextHubInfo[contextHubHandle]; } @Override - public IBinder onBind(Intent intent) { - return null; - } + public int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException { + checkPermissions(); + contextHubHandle -= 1; - private final IContextHubService.Stub mBinder = new IContextHubService.Stub() { + if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) { + return -1; // negative handle are invalid, means failed + } - private IContextHubCallback callback; + // Call Native interface here + int[] msgHeader = new int[8]; + msgHeader[0] = contextHubHandle; + msgHeader[1] = app.getAppId(); + msgHeader[2] = app.getAppVersion(); + msgHeader[3] = ContextHubManager.MSG_LOAD_NANO_APP; + msgHeader[4] = 0; // Loading hints - @Override - public int registerCallBack(IContextHubCallback callback) throws RemoteException{ - this.callback = callback; - return 0; - } + return nativeSendMessage(msgHeader, app.getAppBinary()); + } - @Override - public int[] getContextHubHandles() throws RemoteException { - int [] returnArray = new int[mHubHash.size()]; - int i = 0; - for (int key : mHubHash.keySet()) { - // Add any filtering here - returnArray[i] = key; - i++; - } - return returnArray; + @Override + public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException { + checkPermissions(); + NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle); + if (info == null) { + return -1; //means failed } - @Override - public ContextHubInfo getContextHubInfo(int contexthubHandle) throws RemoteException { - return mHubHash.get(contexthubHandle); - } + // Call Native interface here + int[] msgHeader = new int[8]; + msgHeader[0] = info.getContexthubId(); + msgHeader[1] = ContextHubManager.MSG_UNLOAD_NANO_APP; + msgHeader[2] = info.getHandle(); - @Override - public int loadNanoApp(int hubHandle, NanoApp app) throws RemoteException { - if (!mHubHash.containsKey(hubHandle)) { - return -1; - } else { - // Call Native interface here - int[] msgHeader = new int[8]; - msgHeader[0] = ContextHubManager.MSG_LOAD_NANO_APP; - msgHeader[1] = app.getAppId(); - msgHeader[2] = app.getAppVersion(); - msgHeader[3] = 0; // LOADING_HINTS - msgHeader[4] = hubHandle; - - int handle = nativeSendMessage(msgHeader, app.getAppBinary()); + return nativeSendMessage(msgHeader, null); + } - // if successful, add an entry to mNanoAppHash + @Override + public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) + throws RemoteException { + checkPermissions(); + // This assumes that all the nanoAppInfo is current. This is reasonable + // for the use cases for tightly controlled nanoApps. + if (mNanoAppHash.containsKey(nanoAppInstanceHandle)) { + return mNanoAppHash.get(nanoAppInstanceHandle); + } else { + return null; + } + } - if(handle > 0) { - return 0; - } else { + @Override + public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException { + checkPermissions(); + ArrayList<Integer> foundInstances = new ArrayList<Integer>(); - return -1; - } - } - } + for(Integer nanoAppInstance : mNanoAppHash.keySet()) { + NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance); - @Override - public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException { - if(!mNanoAppHash.containsKey(nanoAppInstanceHandle)) { - return -1; - } else { - NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle); - // Call Native interface here - int[] msgHeader = new int[8]; - msgHeader[0] = ContextHubManager.MSG_UNLOAD_NANO_APP; - msgHeader[1] = info.getContexthubId(); - msgHeader[2] = info.getHandle(); - - int result = nativeSendMessage(msgHeader, null); - // if successful, remove the entry in mNanoAppHash - if(result == 0) { - mNanoAppHash.remove(nanoAppInstanceHandle); - } - return(result); + if(filter.testMatch(info)){ + foundInstances.add(nanoAppInstance); } } - @Override - public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) throws RemoteException { - // This assumes that all the nanoAppInfo is current. This is reasonable - // for the use cases for tightly controlled nanoApps. - // - if(!mNanoAppHash.containsKey(nanoAppInstanceHandle)) { - return(mNanoAppHash.get(nanoAppInstanceHandle)); - } else { - return null; - } + int[] retArray = new int[foundInstances.size()]; + for (int i = 0; i < foundInstances.size(); i++) { + retArray[i] = foundInstances.get(i).intValue(); } - @Override - public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException { - ArrayList<Integer> foundInstances = new ArrayList<Integer>(); - - for(Integer nanoAppInstance : mNanoAppHash.keySet()) { - NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance); - - if(filter.testMatch(info)){ - foundInstances.add(nanoAppInstance); - } - } - - int[] retArray = new int[foundInstances.size()]; - for (int i = 0; i < foundInstances.size(); i++) { - retArray[i] = foundInstances.get(i).intValue(); - } - - return retArray; - } + return retArray; + } - @Override - public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException { - int[] msgHeader = new int[8]; - msgHeader[0] = ContextHubManager.MSG_DATA_SEND; - msgHeader[1] = hubHandle; - msgHeader[2] = nanoAppHandle; - msgHeader[3] = msg.getMsgType(); - msgHeader[4] = msg.getVersion(); + @Override + public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) + throws RemoteException { + checkPermissions(); + int[] msgHeader = new int[8]; + msgHeader[0] = ContextHubManager.MSG_DATA_SEND; + msgHeader[1] = hubHandle; + msgHeader[2] = nanoAppHandle; + msgHeader[3] = msg.getMsgType(); + msgHeader[4] = msg.getVersion(); + + return nativeSendMessage(msgHeader, msg.getData()); + } - return (nativeSendMessage(msgHeader, msg.getData())); - } - }; + private void checkPermissions() { + mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE); + } } + diff --git a/core/java/android/hardware/location/IContextHubCallback.aidl b/core/java/android/hardware/location/IContextHubCallback.aidl index 45b1ef494ac2..141fcf6a598b 100644 --- a/core/java/android/hardware/location/IContextHubCallback.aidl +++ b/core/java/android/hardware/location/IContextHubCallback.aidl @@ -18,7 +18,9 @@ package android.hardware.location; import android.hardware.location.ContextHubMessage; -/** @hide */ +/** + * @hide + */ oneway interface IContextHubCallback { void onMessageReceipt(int hubId, int nanoAppId, in ContextHubMessage msg); } diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl index b2db0b2cdd23..ff8c1d07ce2c 100644 --- a/core/java/android/hardware/location/IContextHubService.aidl +++ b/core/java/android/hardware/location/IContextHubService.aidl @@ -24,11 +24,13 @@ import android.hardware.location.NanoAppInstanceInfo; import android.hardware.location.NanoAppFilter; import android.hardware.location.IContextHubCallback; -/** @hide */ +/** + * @hide + */ interface IContextHubService { // register a callback to receive messages - int registerCallBack(in IContextHubCallback callback); + int registerCallback(in IContextHubCallback callback); // Gets a list of available context hub handles int[] getContextHubHandles(); diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java index e8c761527c2c..d100de257549 100644 --- a/core/java/android/hardware/location/MemoryRegion.java +++ b/core/java/android/hardware/location/MemoryRegion.java @@ -23,7 +23,6 @@ import android.os.Parcelable; /** * @hide */ - @SystemApi public class MemoryRegion implements Parcelable{ diff --git a/core/java/android/hardware/location/NanoApp.aidl b/core/java/android/hardware/location/NanoApp.aidl index d32c44a5c44a..9df9a087afdc 100644 --- a/core/java/android/hardware/location/NanoApp.aidl +++ b/core/java/android/hardware/location/NanoApp.aidl @@ -15,7 +15,7 @@ */ package android.hardware.location; -/* -@hide -*/ +/** + * @hide + */ parcelable NanoApp; diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java index 36d181f91fba..b447b6245712 100644 --- a/core/java/android/hardware/location/NanoApp.java +++ b/core/java/android/hardware/location/NanoApp.java @@ -13,16 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package android.hardware.location; - import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -/** - * A class describing nano apps. +/** A class describing nano apps. * A nano app is a piece of executable code that can be * downloaded onto a specific architecture. These are targtted * for low power compute domains on a device. diff --git a/core/java/android/hardware/location/NanoAppFilter.aidl b/core/java/android/hardware/location/NanoAppFilter.aidl index cc6d4755997a..5f1020111613 100644 --- a/core/java/android/hardware/location/NanoAppFilter.aidl +++ b/core/java/android/hardware/location/NanoAppFilter.aidl @@ -15,7 +15,7 @@ */ package android.hardware.location; -/* -@hide -*/ +/** + * @hide + */ parcelable NanoAppFilter; diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java index ac341e417b64..369f9e44e8d9 100644 --- a/core/java/android/hardware/location/NanoAppFilter.java +++ b/core/java/android/hardware/location/NanoAppFilter.java @@ -110,8 +110,9 @@ public class NanoAppFilter { return true; } /** + * Test match method. * - * @param nano app instance info + * @param info nano app instance info * * @return true if this is a match, false otherwise */ diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.aidl b/core/java/android/hardware/location/NanoAppInstanceInfo.aidl index c8c40d7be233..2db5566a590d 100644 --- a/core/java/android/hardware/location/NanoAppInstanceInfo.aidl +++ b/core/java/android/hardware/location/NanoAppInstanceInfo.aidl @@ -15,7 +15,7 @@ */ package android.hardware.location; -/* -@hide -*/ -parcelable NanoAppInstanceInfo;
\ No newline at end of file +/** + * @hide + */ +parcelable NanoAppInstanceInfo; diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 282688295fee..6b79a8ac438a 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -2269,8 +2269,9 @@ public class InputMethodService extends AbstractInputMethodService { public void onExtractedDeleteText(int start, int end) { InputConnection conn = getCurrentInputConnection(); if (conn != null) { + conn.finishComposingText(); conn.setSelection(start, start); - conn.deleteSurroundingText(0, end-start); + conn.deleteSurroundingText(0, end - start); } } diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 3d8b0917a326..25806fa77674 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -71,9 +71,9 @@ public class NetworkStats implements Parcelable { /** {@link #set} value for all roaming values. */ public static final int ROAMING_ALL = -1; /** {@link #set} value where native, non-roaming data is accounted. */ - public static final int ROAMING_DEFAULT = 0; + public static final int ROAMING_NO = 0; /** {@link #set} value where roaming data is accounted. */ - public static final int ROAMING_ROAMING = 1; + public static final int ROAMING_YES = 1; // TODO: move fields to "mVariable" notation @@ -123,7 +123,7 @@ public class NetworkStats implements Parcelable { public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - this(iface, uid, set, tag, ROAMING_DEFAULT, rxBytes, rxPackets, txBytes, txPackets, + this(iface, uid, set, tag, ROAMING_NO, rxBytes, rxPackets, txBytes, txPackets, operations); } @@ -836,10 +836,10 @@ public class NetworkStats implements Parcelable { switch (roaming) { case ROAMING_ALL: return "ALL"; - case ROAMING_DEFAULT: - return "DEFAULT"; - case ROAMING_ROAMING: - return "ROAMING"; + case ROAMING_NO: + return "NO"; + case ROAMING_YES: + return "YES"; default: return "UNKNOWN"; } @@ -1019,18 +1019,18 @@ public class NetworkStats implements Parcelable { // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than // the TAG_NONE traffic. // - // Relies on the fact that the underlying traffic only has state ROAMING_DEFAULT, which + // Relies on the fact that the underlying traffic only has state ROAMING_NO, which // should be the case as it comes directly from the /proc file. We only blend in the // roaming data after applying these adjustments, by checking the NetworkIdentity of the // underlying iface. int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - ROAMING_DEFAULT); + ROAMING_NO); if (idxVpnBackground != -1) { tunSubtract(idxVpnBackground, this, moved); } int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - ROAMING_DEFAULT); + ROAMING_NO); if (idxVpnForeground != -1) { tunSubtract(idxVpnForeground, this, moved); } diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java index 2dfb06109661..85821506fa3e 100644 --- a/core/java/android/net/ScoredNetwork.java +++ b/core/java/android/net/ScoredNetwork.java @@ -43,6 +43,16 @@ public class ScoredNetwork implements Parcelable { public final RssiCurve rssiCurve; /** + * A boolean value that indicates whether or not the network is believed to be metered. + * + * <p>A network can be classified as metered if the user would be + * sensitive to heavy data usage on that connection due to monetary costs, + * data limitations or battery/performance issues. A typical example would + * be a wifi connection where the user would be charged for usage. + */ + public final boolean meteredHint; + + /** * Construct a new {@link ScoredNetwork}. * * @param networkKey the {@link NetworkKey} uniquely identifying this network. @@ -54,8 +64,26 @@ public class ScoredNetwork implements Parcelable { * the scorer may choose to issue an out-of-band update at any time. */ public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve) { + this(networkKey, rssiCurve, false /* meteredHint */); + } + + /** + * Construct a new {@link ScoredNetwork}. + * + * @param networkKey the {@link NetworkKey} uniquely identifying this network. + * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the + * RSSI. This field is optional, and may be skipped to represent a network which the scorer + * has opted not to score at this time. Passing a null value here is strongly preferred to + * not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it + * indicates to the system not to request scores for this network in the future, although + * the scorer may choose to issue an out-of-band update at any time. + * @param meteredHint A boolean value indicating whether or not the network is believed to be + * metered. + */ + public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve, boolean meteredHint) { this.networkKey = networkKey; this.rssiCurve = rssiCurve; + this.meteredHint = meteredHint; } private ScoredNetwork(Parcel in) { @@ -65,6 +93,7 @@ public class ScoredNetwork implements Parcelable { } else { rssiCurve = null; } + meteredHint = in.readByte() != 0; } @Override @@ -81,6 +110,7 @@ public class ScoredNetwork implements Parcelable { } else { out.writeByte((byte) 0); } + out.writeByte((byte) (meteredHint ? 1 : 0)); } @Override @@ -90,18 +120,20 @@ public class ScoredNetwork implements Parcelable { ScoredNetwork that = (ScoredNetwork) o; - return Objects.equals(networkKey, that.networkKey) && - Objects.equals(rssiCurve, that.rssiCurve); + return Objects.equals(networkKey, that.networkKey) + && Objects.equals(rssiCurve, that.rssiCurve) + && Objects.equals(meteredHint, that.meteredHint); } @Override public int hashCode() { - return Objects.hash(networkKey, rssiCurve); + return Objects.hash(networkKey, rssiCurve, meteredHint); } @Override public String toString() { - return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]"; + return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + + ",meteredHint=" + meteredHint + "]"; } public static final Parcelable.Creator<ScoredNetwork> CREATOR = diff --git a/core/java/android/os/BadParcelableException.java b/core/java/android/os/BadParcelableException.java index a1c5bb251197..7e0b1a591d0a 100644 --- a/core/java/android/os/BadParcelableException.java +++ b/core/java/android/os/BadParcelableException.java @@ -15,11 +15,15 @@ */ package android.os; + import android.util.AndroidRuntimeException; /** - * The object you are calling has died, because its hosting process - * no longer exists. + * Exception thrown when a {@link Parcelable} is malformed or otherwise invalid. + * <p> + * This is typically encountered when a custom {@link Parcelable} object is + * passed to another process that doesn't have the same {@link Parcelable} class + * in its {@link ClassLoader}. */ public class BadParcelableException extends AndroidRuntimeException { public BadParcelableException(String msg) { diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java index 5c7137341cd3..6e50155313ca 100644 --- a/core/java/android/os/BaseBundle.java +++ b/core/java/android/os/BaseBundle.java @@ -26,7 +26,9 @@ import java.util.ArrayList; import java.util.Set; /** - * A mapping from String values to various types. + * A mapping from String keys to values of various types. In most cases, you + * should work directly with either the {@link Bundle} or + * {@link PersistableBundle} subclass. */ public class BaseBundle { private static final String TAG = "Bundle"; @@ -35,6 +37,32 @@ public class BaseBundle { // Keep in sync with frameworks/native/libs/binder/PersistableBundle.cpp. static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L' + /** + * Flag indicating that this Bundle is okay to "defuse." That is, it's okay + * for system processes to ignore any {@link BadParcelableException} + * encountered when unparceling it, leaving an empty bundle in its place. + * <p> + * This should <em>only</em> be set when the Bundle reaches its final + * destination, otherwise a system process may clobber contents that were + * destined for an app that could have unparceled them. + */ + static final int FLAG_DEFUSABLE = 1 << 0; + + private static volatile boolean sShouldDefuse = false; + + /** + * Set global variable indicating that any Bundles parsed in this process + * should be "defused." That is, any {@link BadParcelableException} + * encountered will be suppressed and logged, leaving an empty Bundle + * instead of crashing. + * + * @hide + */ + public static void setShouldDefuse(boolean shouldDefuse) { + sShouldDefuse = shouldDefuse; + } + + /** {@hide} */ static final Parcel EMPTY_PARCEL; static { @@ -58,6 +86,9 @@ public class BaseBundle { */ private ClassLoader mClassLoader; + /** {@hide} */ + int mFlags; + /** * Constructs a new, empty Bundle that uses a specific ClassLoader for * instantiating Parcelable and Serializable objects. @@ -197,6 +228,11 @@ public class BaseBundle { return; } + if (sShouldDefuse && (mFlags & FLAG_DEFUSABLE) == 0) { + Log.wtf(TAG, "Attempting to unparcel a Bundle while in transit; this may " + + "clobber all data inside!", new Throwable()); + } + if (mParcelledData == EMPTY_PARCEL) { if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this)) + ": empty"); @@ -221,9 +257,19 @@ public class BaseBundle { mMap.erase(); mMap.ensureCapacity(N); } - mParcelledData.readArrayMapInternal(mMap, N, mClassLoader); - mParcelledData.recycle(); - mParcelledData = null; + try { + mParcelledData.readArrayMapInternal(mMap, N, mClassLoader); + } catch (BadParcelableException e) { + if (sShouldDefuse) { + Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e); + mMap.erase(); + } else { + throw e; + } + } finally { + mParcelledData.recycle(); + mParcelledData = null; + } if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this)) + " final map: " + mMap); } @@ -1371,9 +1417,8 @@ public class BaseBundle { return; } - int magic = parcel.readInt(); + final int magic = parcel.readInt(); if (magic != BUNDLE_MAGIC) { - //noinspection ThrowableInstanceNeverThrown throw new IllegalStateException("Bad magic number for Bundle: 0x" + Integer.toHexString(magic)); } diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java index 74699fd8c0ad..1097cadd55dc 100644 --- a/core/java/android/os/Bundle.java +++ b/core/java/android/os/Bundle.java @@ -27,11 +27,17 @@ import java.util.ArrayList; import java.util.List; /** - * A mapping from String values to various Parcelable types. + * A mapping from String keys to various {@link Parcelable} values. * + * @see PersistableBundle */ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { + private static final int FLAG_HAS_FDS = 1 << 8; + private static final int FLAG_HAS_FDS_KNOWN = 1 << 9; + private static final int FLAG_ALLOW_FDS = 1 << 10; + public static final Bundle EMPTY; + static final Parcel EMPTY_PARCEL; static { @@ -40,15 +46,12 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { EMPTY_PARCEL = BaseBundle.EMPTY_PARCEL; } - private boolean mHasFds = false; - private boolean mFdsKnown = true; - private boolean mAllowFds = true; - /** * Constructs a new, empty Bundle. */ public Bundle() { super(); + mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; } /** @@ -59,16 +62,18 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { */ Bundle(Parcel parcelledData) { super(parcelledData); - - mHasFds = mParcelledData.hasFileDescriptors(); - mFdsKnown = true; + mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; + if (mParcelledData.hasFileDescriptors()) { + mFlags |= FLAG_HAS_FDS; + } } /* package */ Bundle(Parcel parcelledData, int length) { super(parcelledData, length); - - mHasFds = mParcelledData.hasFileDescriptors(); - mFdsKnown = true; + mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; + if (mParcelledData.hasFileDescriptors()) { + mFlags |= FLAG_HAS_FDS; + } } /** @@ -80,6 +85,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { */ public Bundle(ClassLoader loader) { super(loader); + mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; } /** @@ -90,6 +96,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { */ public Bundle(int capacity) { super(capacity); + mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; } /** @@ -100,9 +107,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { */ public Bundle(Bundle b) { super(b); - - mHasFds = b.mHasFds; - mFdsKnown = b.mFdsKnown; + mFlags = b.mFlags; } /** @@ -113,6 +118,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { */ public Bundle(PersistableBundle b) { super(b); + mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; } /** @@ -145,14 +151,37 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { return super.getClassLoader(); } - /** @hide */ + /** {@hide} */ public boolean setAllowFds(boolean allowFds) { - boolean orig = mAllowFds; - mAllowFds = allowFds; + final boolean orig = (mFlags & FLAG_ALLOW_FDS) != 0; + if (allowFds) { + mFlags |= FLAG_ALLOW_FDS; + } else { + mFlags &= ~FLAG_ALLOW_FDS; + } return orig; } /** + * Mark if this Bundle is okay to "defuse." That is, it's okay for system + * processes to ignore any {@link BadParcelableException} encountered when + * unparceling it, leaving an empty bundle in its place. + * <p> + * This should <em>only</em> be set when the Bundle reaches its final + * destination, otherwise a system process may clobber contents that were + * destined for an app that could have unparceled them. + * + * @hide + */ + public void setDefusable(boolean defusable) { + if (defusable) { + mFlags |= FLAG_DEFUSABLE; + } else { + mFlags &= ~FLAG_DEFUSABLE; + } + } + + /** * Clones the current Bundle. The internal map is cloned, but the keys and * values to which it refers are copied by reference. */ @@ -167,9 +196,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { @Override public void clear() { super.clear(); - - mHasFds = false; - mFdsKnown = true; + mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; } /** @@ -182,16 +209,20 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { bundle.unparcel(); mMap.putAll(bundle.mMap); - // fd state is now known if and only if both bundles already knew - mHasFds |= bundle.mHasFds; - mFdsKnown = mFdsKnown && bundle.mFdsKnown; + // FD state is now known if and only if both bundles already knew + if ((bundle.mFlags & FLAG_HAS_FDS) != 0) { + mFlags |= FLAG_HAS_FDS; + } + if ((bundle.mFlags & FLAG_HAS_FDS_KNOWN) == 0) { + mFlags &= ~FLAG_HAS_FDS_KNOWN; + } } /** * Reports whether the bundle contains any parcelled file descriptors. */ public boolean hasFileDescriptors() { - if (!mFdsKnown) { + if ((mFlags & FLAG_HAS_FDS_KNOWN) == 0) { boolean fdFound = false; // keep going until we find one or run out of data if (mParcelledData != null) { @@ -247,10 +278,12 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { } } - mHasFds = fdFound; - mFdsKnown = true; + if (fdFound) { + mFlags |= FLAG_HAS_FDS; + } + mFlags |= FLAG_HAS_FDS_KNOWN; } - return mHasFds; + return (mFlags & FLAG_HAS_FDS) != 0; } /** @@ -346,7 +379,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { public void putParcelable(@Nullable String key, @Nullable Parcelable value) { unparcel(); mMap.put(key, value); - mFdsKnown = false; + mFlags &= ~FLAG_HAS_FDS_KNOWN; } /** @@ -384,7 +417,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { public void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) { unparcel(); mMap.put(key, value); - mFdsKnown = false; + mFlags &= ~FLAG_HAS_FDS_KNOWN; } /** @@ -399,14 +432,14 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { @Nullable ArrayList<? extends Parcelable> value) { unparcel(); mMap.put(key, value); - mFdsKnown = false; + mFlags &= ~FLAG_HAS_FDS_KNOWN; } /** {@hide} */ public void putParcelableList(String key, List<? extends Parcelable> value) { unparcel(); mMap.put(key, value); - mFdsKnown = false; + mFlags &= ~FLAG_HAS_FDS_KNOWN; } /** @@ -421,7 +454,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { @Nullable SparseArray<? extends Parcelable> value) { unparcel(); mMap.put(key, value); - mFdsKnown = false; + mFlags &= ~FLAG_HAS_FDS_KNOWN; } /** @@ -1074,7 +1107,7 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { */ @Override public void writeToParcel(Parcel parcel, int flags) { - final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds); + final boolean oldAllowFds = parcel.pushAllowFds((mFlags & FLAG_ALLOW_FDS) != 0); try { super.writeToParcelInner(parcel, flags); } finally { @@ -1089,8 +1122,10 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { */ public void readFromParcel(Parcel parcel) { super.readFromParcelInner(parcel); - mHasFds = mParcelledData.hasFileDescriptors(); - mFdsKnown = true; + mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS; + if (mParcelledData.hasFileDescriptors()) { + mFlags |= FLAG_HAS_FDS; + } } @Override @@ -1105,5 +1140,4 @@ public final class Bundle extends BaseBundle implements Cloneable, Parcelable { } return "Bundle[" + mMap.toString() + "]"; } - } diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 1b79497b1870..dd73e53f65e6 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -605,6 +605,30 @@ public class FileUtils { */ public static File buildUniqueFile(File parent, String mimeType, String displayName) throws FileNotFoundException { + final String[] parts = splitFileName(mimeType, displayName); + final String name = parts[0]; + final String ext = parts[1]; + File file = buildFile(parent, name, ext); + + // If conflicting file, try adding counter suffix + int n = 0; + while (file.exists()) { + if (n++ >= 32) { + throw new FileNotFoundException("Failed to create unique file"); + } + file = buildFile(parent, name + " (" + n + ")", ext); + } + + return file; + } + + /** + * Splits file name into base name and extension. + * If the display name doesn't have an extension that matches the requested MIME type, the + * extension is regarded as a part of filename and default extension for that MIME type is + * appended. + */ + public static String[] splitFileName(String mimeType, String displayName) { String name; String ext; @@ -642,18 +666,11 @@ public class FileUtils { } } - File file = buildFile(parent, name, ext); - - // If conflicting file, try adding counter suffix - int n = 0; - while (file.exists()) { - if (n++ >= 32) { - throw new FileNotFoundException("Failed to create unique file"); - } - file = buildFile(parent, name + " (" + n + ")", ext); + if (ext == null) { + ext = ""; } - return file; + return new String[] { name, ext }; } private static File buildFile(File parent, String name, String ext) { diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java index 5872f7438904..b947c97dffc7 100644 --- a/core/java/android/os/PersistableBundle.java +++ b/core/java/android/os/PersistableBundle.java @@ -18,7 +18,9 @@ package android.os; import android.annotation.Nullable; import android.util.ArrayMap; + import com.android.internal.util.XmlUtils; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -26,9 +28,11 @@ import org.xmlpull.v1.XmlSerializer; import java.io.IOException; /** - * A mapping from String values to various types that can be saved to persistent and later - * restored. + * A mapping from String keys to values of various types. The set of types + * supported by this class is purposefully restricted to simple objects that can + * safely be persisted to and restored from disk. * + * @see Bundle */ public final class PersistableBundle extends BaseBundle implements Cloneable, Parcelable, XmlUtils.WriteMapCallback { @@ -57,6 +61,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa */ public PersistableBundle() { super(); + mFlags = FLAG_DEFUSABLE; } /** @@ -67,6 +72,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa */ public PersistableBundle(int capacity) { super(capacity); + mFlags = FLAG_DEFUSABLE; } /** @@ -77,6 +83,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa */ public PersistableBundle(PersistableBundle b) { super(b); + mFlags = b.mFlags; } @@ -101,6 +108,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa */ private PersistableBundle(ArrayMap<String, Object> map) { super(); + mFlags = FLAG_DEFUSABLE; // First stuff everything in. putAll(map); @@ -123,6 +131,7 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa /* package */ PersistableBundle(Parcel parcelledData, int length) { super(parcelledData, length); + mFlags = FLAG_DEFUSABLE; } /** @@ -278,5 +287,4 @@ public final class PersistableBundle extends BaseBundle implements Cloneable, Pa } return "PersistableBundle[" + mMap.toString() + "]"; } - } diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index ddcd63520549..b25b33d00aa8 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -434,25 +434,35 @@ public class RecoverySystem { String filename = packageFile.getCanonicalPath(); Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!"); - if (!processed && filename.startsWith("/data/")) { - FileWriter uncryptFile = new FileWriter(UNCRYPT_PACKAGE_FILE); - try { - uncryptFile.write(filename + "\n"); - } finally { - uncryptFile.close(); - } - // UNCRYPT_PACKAGE_FILE needs to be readable and writable by system server. - if (!UNCRYPT_PACKAGE_FILE.setReadable(true, false) - || !UNCRYPT_PACKAGE_FILE.setWritable(true, false)) { - Log.e(TAG, "Error setting permission for " + UNCRYPT_PACKAGE_FILE); - } + // If the package is on the /data partition, the package needs to + // be processed (i.e. uncrypt'd). The caller specifies if that has + // been done in 'processed' parameter. + if (filename.startsWith("/data/")) { + if (processed) { + if (!BLOCK_MAP_FILE.exists()) { + Log.e(TAG, "Package claimed to have been processed but failed to find " + + "the block map file."); + throw new IOException("Failed to find block map file"); + } + } else { + FileWriter uncryptFile = new FileWriter(UNCRYPT_PACKAGE_FILE); + try { + uncryptFile.write(filename + "\n"); + } finally { + uncryptFile.close(); + } + // UNCRYPT_PACKAGE_FILE needs to be readable and writable + // by system server. + if (!UNCRYPT_PACKAGE_FILE.setReadable(true, false) + || !UNCRYPT_PACKAGE_FILE.setWritable(true, false)) { + Log.e(TAG, "Error setting permission for " + UNCRYPT_PACKAGE_FILE); + } - BLOCK_MAP_FILE.delete(); - } + BLOCK_MAP_FILE.delete(); + } - // If the package is on the /data partition, use the block map file as - // the package name instead. - if (filename.startsWith("/data/")) { + // If the package is on the /data partition, use the block map + // file as the package name instead. filename = "@/cache/recovery/block.map"; } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 7223dfbdccdb..e2675b1b1863 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -972,7 +972,8 @@ public class UserManager { /** * Returns the UserInfo object describing a specific user. - * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. + * Requires {@link android.Manifest.permission#MANAGE_USERS} permission or the caller is + * in the same profile group of target user. * @param userHandle the user handle of the user whose information is being requested. * @return the UserInfo object for a specific user. * @hide diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index e7c4a075cf72..e2ae133cf6e9 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -179,6 +179,7 @@ public class CallLog { * <li>{@link #VOICEMAIL_TYPE}</li> * <li>{@link #REJECTED_TYPE}</li> * <li>{@link #BLOCKED_TYPE}</li> + * <li>{@link #ANSWERED_EXTERNALLY_TYPE}</li> * </ul> * </p> */ @@ -196,6 +197,12 @@ public class CallLog { public static final int REJECTED_TYPE = 5; /** Call log type for calls blocked automatically. */ public static final int BLOCKED_TYPE = 6; + /** + * Call log type for a call which was answered on another device. Used in situations where + * a call rings on multiple devices simultaneously and it ended up being answered on a + * device other than the current one. + */ + public static final int ANSWERED_EXTERNALLY_TYPE = 7; /** * Bit-mask describing features of the call (e.g. video). @@ -207,6 +214,9 @@ public class CallLog { /** Call had video. */ public static final int FEATURES_VIDEO = 0x1; + /** Call was pulled externally. */ + public static final int FEATURES_PULLED_EXTERNALLY = 0x2; + /** * The phone number as the user entered it. * <P>Type: TEXT</P> diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java index e7a9b7d87fdd..4ad7969d1911 100644 --- a/core/java/android/provider/DocumentsContract.java +++ b/core/java/android/provider/DocumentsContract.java @@ -379,8 +379,18 @@ public final class DocumentsContract { * @see DocumentsProvider#queryChildDocuments(String, String[], String) * @hide */ - public static final int FLAG_ARCHIVE = 1 << 15; + + /** + * Flag indicating that a document is not complete, likely its + * contents are being downloaded. Partial files cannot be opened, + * copied, moved in the UI. But they can be deleted and retried + * if they represent a failed download. + * + * @see #COLUMN_FLAGS + * @hide + */ + public static final int FLAG_PARTIAL = 1 << 16; } /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d4ff766c6063..5fc2899877f4 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -217,21 +217,6 @@ public final class Settings { "android.settings.ACCESSIBILITY_SETTINGS"; /** - * Activity Action: Launch the screen reader tutorial. - * <p> - * In some cases, a matching Activity may not exist, so ensure you - * safeguard against this. - * <p> - * Input: Nothing. - * <p> - * Output: Nothing. - */ - @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) - public static final String ACTION_SCREEN_READER_TUTORIAL = - "android.settings.SCREEN_READER_TUTORIAL"; - - - /** * Activity Action: Show settings to control access to usage information. * <p> * In some cases, a matching Activity may not exist, so ensure you @@ -2108,7 +2093,7 @@ public final class Settings { */ public static void clearConfiguration(Configuration inoutConfig) { inoutConfig.fontScale = 0; - if (!inoutConfig.userSetLocale) { + if (!inoutConfig.userSetLocale && !inoutConfig.getLocales().isEmpty()) { inoutConfig.setLocales(LocaleList.getEmptyLocaleList()); } } @@ -2723,24 +2708,6 @@ public final class Settings { public static final String VOLUME_MASTER = "volume_master"; /** - * Master volume mute (int 1 = mute, 0 = not muted). - * - * @hide - */ - public static final String VOLUME_MASTER_MUTE = "volume_master_mute"; - - private static final Validator VOLUME_MASTER_MUTE_VALIDATOR = sBooleanValidator; - - /** - * Microphone mute (int 1 = mute, 0 = not muted). - * - * @hide - */ - public static final String MICROPHONE_MUTE = "microphone_mute"; - - private static final Validator MICROPHONE_MUTE_VALIDATOR = sBooleanValidator; - - /** * Master mono (int 1 = mono, 0 = normal). * * @hide @@ -3530,8 +3497,6 @@ public final class Settings { PRIVATE_SETTINGS.add(SCREEN_AUTO_BRIGHTNESS_ADJ); PRIVATE_SETTINGS.add(VIBRATE_INPUT_DEVICES); PRIVATE_SETTINGS.add(VOLUME_MASTER); - PRIVATE_SETTINGS.add(VOLUME_MASTER_MUTE); - PRIVATE_SETTINGS.add(MICROPHONE_MUTE); PRIVATE_SETTINGS.add(MASTER_MONO); PRIVATE_SETTINGS.add(NOTIFICATIONS_USE_RING_VOLUME); PRIVATE_SETTINGS.add(VIBRATE_IN_SILENT); @@ -3609,8 +3574,6 @@ public final class Settings { VALIDATORS.put(ADVANCED_SETTINGS, ADVANCED_SETTINGS_VALIDATOR); VALIDATORS.put(SCREEN_AUTO_BRIGHTNESS_ADJ, SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR); VALIDATORS.put(VIBRATE_INPUT_DEVICES, VIBRATE_INPUT_DEVICES_VALIDATOR); - VALIDATORS.put(VOLUME_MASTER_MUTE, VOLUME_MASTER_MUTE_VALIDATOR); - VALIDATORS.put(MICROPHONE_MUTE, MICROPHONE_MUTE_VALIDATOR); VALIDATORS.put(MASTER_MONO, MASTER_MONO_VALIDATOR); VALIDATORS.put(NOTIFICATIONS_USE_RING_VOLUME, NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR); VALIDATORS.put(VIBRATE_IN_SILENT, VIBRATE_IN_SILENT_VALIDATOR); diff --git a/core/java/android/speech/tts/AudioPlaybackQueueItem.java b/core/java/android/speech/tts/AudioPlaybackQueueItem.java index d4fea534aced..ed7534dcf009 100644 --- a/core/java/android/speech/tts/AudioPlaybackQueueItem.java +++ b/core/java/android/speech/tts/AudioPlaybackQueueItem.java @@ -16,7 +16,7 @@ package android.speech.tts; import android.content.Context; -import android.media.AudioSystem; +import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.os.ConditionVariable; @@ -57,7 +57,7 @@ class AudioPlaybackQueueItem extends PlaybackQueueItem { int sessionId = mAudioParams.mSessionId; mPlayer = MediaPlayer.create( mContext, mUri, null, mAudioParams.mAudioAttributes, - sessionId > 0 ? sessionId : AudioSystem.AUDIO_SESSION_ALLOCATE); + sessionId > 0 ? sessionId : AudioManager.AUDIO_SESSION_ID_GENERATE); if (mPlayer == null) { dispatcher.dispatchOnError(TextToSpeech.ERROR_OUTPUT); return; diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index fc075de59cf2..1eaa7cfd5b15 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -19,7 +19,7 @@ import android.annotation.NonNull; import android.app.Service; import android.content.Intent; import android.media.AudioAttributes; -import android.media.AudioSystem; +import android.media.AudioManager; import android.net.Uri; import android.os.Binder; import android.os.Bundle; @@ -659,7 +659,7 @@ public abstract class TextToSpeechService extends Service { /** * Audio session identifier. May be used to associate audio playback with one of the * {@link android.media.audiofx.AudioEffect} objects. If not specified by client, - * it should be equal to {@link AudioSystem#AUDIO_SESSION_ALLOCATE}. + * it should be equal to {@link AudioManager#AUDIO_SESSION_ID_GENERATE}. */ public final int mSessionId; @@ -684,7 +684,7 @@ public abstract class TextToSpeechService extends Service { /** Create AudioOutputParams with default values */ AudioOutputParams() { - mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE; + mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; mVolume = Engine.DEFAULT_VOLUME; mPan = Engine.DEFAULT_PAN; mAudioAttributes = null; @@ -722,7 +722,7 @@ public abstract class TextToSpeechService extends Service { return new AudioOutputParams( paramsBundle.getInt( Engine.KEY_PARAM_SESSION_ID, - AudioSystem.AUDIO_SESSION_ALLOCATE), + AudioManager.AUDIO_SESSION_ID_GENERATE), paramsBundle.getFloat( Engine.KEY_PARAM_VOLUME, Engine.DEFAULT_VOLUME), diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java index bfe5c3ff255f..a1bc2d107f3f 100644 --- a/core/java/android/text/BoringLayout.java +++ b/core/java/android/text/BoringLayout.java @@ -247,23 +247,22 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback */ public static Metrics isBoring(CharSequence text, TextPaint paint, TextDirectionHeuristic textDir, Metrics metrics) { - char[] temp = TextUtils.obtain(500); - int length = text.length(); + final int MAX_BUF_LEN = 500; + final char[] buffer = TextUtils.obtain(MAX_BUF_LEN); + final int textLength = text.length(); boolean boring = true; outer: - for (int i = 0; i < length; i += 500) { - int j = i + 500; + for (int start = 0; start < textLength; start += MAX_BUF_LEN) { + final int end = Math.min(start + MAX_BUF_LEN, textLength); - if (j > length) - j = length; + // No need to worry about getting half codepoints, since we reject surrogate code units + // as non-boring as soon we see one. + TextUtils.getChars(text, start, end, buffer, 0); - TextUtils.getChars(text, i, j, temp, 0); - - int n = j - i; - - for (int a = 0; a < n; a++) { - char c = temp[a]; + final int len = end - start; + for (int i = 0; i < len; i++) { + final char c = buffer[i]; if (c == '\n' || c == '\t' || (c >= 0x0590 && c <= 0x08FF) || // RTL scripts @@ -279,17 +278,19 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback } } - if (textDir != null && textDir.isRtl(temp, 0, n)) { + // TODO: This looks a little suspicious, and in some cases can result in O(n^2) + // run time. Consider moving outside the loop. + if (textDir != null && textDir.isRtl(buffer, 0, len)) { boring = false; break outer; } } - TextUtils.recycle(temp); + TextUtils.recycle(buffer); if (boring && text instanceof Spanned) { Spanned sp = (Spanned) text; - Object[] styles = sp.getSpans(0, length, ParagraphStyle.class); + Object[] styles = sp.getSpans(0, textLength, ParagraphStyle.class); if (styles.length > 0) { boring = false; } @@ -302,7 +303,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback } TextLine line = TextLine.obtain(); - line.set(paint, text, 0, length, Layout.DIR_LEFT_TO_RIGHT, + line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT, Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null); fm.width = (int) Math.ceil(line.metrics(fm)); TextLine.recycle(line); diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java index 93a156b7e24f..e9153ddba831 100644 --- a/core/java/android/text/style/TtsSpan.java +++ b/core/java/android/text/style/TtsSpan.java @@ -1013,7 +1013,7 @@ public class TtsSpan implements ParcelableSpan { * @return This instance. */ public MeasureBuilder setIntegerPart(long integerPart) { - return setNumber(String.valueOf(integerPart)); + return setIntegerPart(String.valueOf(integerPart)); } /** diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java index 98aaa8149c1c..bd00aba325ea 100644 --- a/core/java/android/util/TypedValue.java +++ b/core/java/android/util/TypedValue.java @@ -17,6 +17,7 @@ package android.util; import android.annotation.AnyRes; +import android.content.pm.ActivityInfo.Config; /** * Container for a dynamically typed data value. Primarily used with @@ -183,9 +184,11 @@ public class TypedValue { @AnyRes public int resourceId; - /** If Value came from a resource, these are the configurations for which - * its contents can change. */ - public int changingConfigurations = -1; + /** + * If the value came from a resource, these are the configurations for + * which its contents can change. + */ + public @Config int changingConfigurations = -1; /** * If the Value came from a resource, this holds the corresponding pixel density. diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 1269ad93d306..22d5ed862690 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -16,6 +16,7 @@ package android.view; +import android.annotation.IntDef; import android.annotation.RequiresPermission; import android.content.Context; import android.content.res.CompatibilityInfo; @@ -31,6 +32,8 @@ import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.Log; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM; @@ -715,6 +718,14 @@ public final class Display { } /** + * Returns the display's HDR capabilities. + * @hide + */ + public HdrCapabilities getHdrCapabilities() { + return new HdrCapabilities(); + } + + /** * Gets the supported color transforms of this device. * @hide */ @@ -762,14 +773,23 @@ public final class Display { /** * Gets display metrics that describe the size and density of this display. + * The size returned by this method does not necessarily represent the + * actual raw size (native resolution) of the display. * <p> - * The size is adjusted based on the current rotation of the display. + * 1. The returned size may be adjusted to exclude certain system decor elements + * that are always visible. * </p><p> - * The size returned by this method does not necessarily represent the - * actual raw size (native resolution) of the display. The returned size may - * be adjusted to exclude certain system decor elements that are always visible. - * It may also be scaled to provide compatibility with older applications that + * 2. It may be scaled to provide compatibility with older applications that * were originally designed for smaller displays. + * </p><p> + * 3. It can be different depending on the WindowManager to which the display belongs. + * <pre> + * - If requested from non-Activity context (e.g. Application context via + * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}) + * metrics will report real size of the display based on current rotation. + * - If requested from activity resulting metrics will correspond to current window metrics. + * In this case the size can be smaller than physical size in multi-window mode. + * </pre> * </p> * * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. @@ -807,7 +827,7 @@ public final class Display { * The size is adjusted based on the current rotation of the display. * </p><p> * The real size may be smaller than the physical size of the screen when the - * window manager is emulating a smaller display (using adb shell am display-size). + * window manager is emulating a smaller display (using adb shell wm size). * </p> * * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. @@ -816,8 +836,7 @@ public final class Display { synchronized (this) { updateDisplayInfoLocked(); mDisplayInfo.getLogicalMetrics(outMetrics, - CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, - mDisplayAdjustments.getConfiguration()); + CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); } } @@ -1104,6 +1123,117 @@ public final class Display { } /** + * Encapsulates the HDR capabilities of a given display. + * For example, what HDR types it supports and details about the desired luminance data. + * <p>You can get an instance for a given {@link Display} object with + * {@link Display#getHdrCapabilities getHdrCapabilities()}. + * @hide + */ + public static final class HdrCapabilities implements Parcelable { + /** + * Invalid luminance value. + */ + public static final float INVALID_LUMINANCE = -1; + /** + * Dolby Vision high dynamic range (HDR) display. + */ + public static final int HDR_TYPE_DOLBY_VISION = 1; + /** + * HDR10 display. + */ + public static final int HDR_TYPE_HDR10 = 2; + /** + * Hybrid Log-Gamma HDR display. + */ + public static final int HDR_TYPE_HLG = 3; + + @IntDef({ + HDR_TYPE_DOLBY_VISION, + HDR_TYPE_HDR10, + HDR_TYPE_HLG, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface HdrType {} + + private @HdrType int[] mSupportedHdrTypes = new int[0]; + private float mMaxLuminance = INVALID_LUMINANCE; + private float mMaxAverageLuminance = INVALID_LUMINANCE; + private float mMinLuminance = INVALID_LUMINANCE; + + public HdrCapabilities() { + } + + /** + * Gets the supported HDR types of this display. + * Returns empty array if HDR is not supported by the display. + */ + public @HdrType int[] getSupportedHdrTypes() { + return mSupportedHdrTypes; + } + /** + * Returns the desired content max luminance data in cd/m2 for this display. + */ + public float getDesiredMaxLuminance() { + return mMaxLuminance; + } + /** + * Returns the desired content max frame-average luminance data in cd/m2 for this display. + */ + public float getDesiredMaxAverageLuminance() { + return mMaxAverageLuminance; + } + /** + * Returns the desired content min luminance data in cd/m2 for this display. + */ + public float getDesiredMinLuminance() { + return mMinLuminance; + } + + public static final Creator<HdrCapabilities> CREATOR = new Creator<HdrCapabilities>() { + @Override + public HdrCapabilities createFromParcel(Parcel source) { + return new HdrCapabilities(source); + } + + @Override + public HdrCapabilities[] newArray(int size) { + return new HdrCapabilities[size]; + } + }; + + private HdrCapabilities(Parcel source) { + readFromParcel(source); + } + + public void readFromParcel(Parcel source) { + int types = source.readInt(); + mSupportedHdrTypes = new int[types]; + for (int i = 0; i < types; ++i) { + mSupportedHdrTypes[i] = source.readInt(); + } + mMaxLuminance = source.readFloat(); + mMaxAverageLuminance = source.readFloat(); + mMinLuminance = source.readFloat(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mSupportedHdrTypes.length); + for (int i = 0; i < mSupportedHdrTypes.length; ++i) { + dest.writeInt(mSupportedHdrTypes[i]); + } + dest.writeFloat(mMaxLuminance); + dest.writeFloat(mMaxAverageLuminance); + dest.writeFloat(mMinLuminance); + } + + @Override + public int describeContents() { + return 0; + } + } + + /** * A color transform supported by a given display. * * @see Display#getSupportedColorTransforms() diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index f912e51b5bfb..d8b742107084 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -193,8 +193,7 @@ interface IWindowManager boolean isKeyguardSecure(); boolean inKeyguardRestrictedInputMode(); void dismissKeyguard(); - void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade); + void keyguardGoingAway(int flags); void closeSystemDialogs(String reason); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 57ab6d400cd9..a7bf73a6823c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -84,7 +84,6 @@ import android.view.AccessibilityIterators.CharacterTextSegmentIterator; import android.view.AccessibilityIterators.ParagraphTextSegmentIterator; import android.view.AccessibilityIterators.TextSegmentIterator; import android.view.AccessibilityIterators.WordTextSegmentIterator; -import android.view.ViewGroup.LayoutParams; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEventSource; import android.view.accessibility.AccessibilityManager; @@ -10151,19 +10150,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * {@link #INVISIBLE} or {@link #GONE}. */ protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) { - final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE; - if (visible && mAttachInfo != null) { - initialAwakenScrollBars(); - } - - final Drawable dr = mBackground; - if (dr != null && visible != dr.isVisible()) { - dr.setVisible(visible, false); - } - final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; - if (fg != null && visible != fg.isVisible()) { - fg.setVisible(visible, false); - } } /** @@ -10220,6 +10206,46 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** + * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by + * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()}, + * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}. + * + * @param isVisible true if this view's visibility to the user is uninterrupted by its + * ancestors or by window visibility + * @return true if this view is visible to the user, not counting clipping or overlapping + */ + @Visibility boolean dispatchVisibilityAggregated(boolean isVisible) { + final boolean thisVisible = getVisibility() == VISIBLE; + if (thisVisible) { + onVisibilityAggregated(isVisible); + } + return thisVisible && isVisible; + } + + /** + * Called when the user-visibility of this View is potentially affected by a change + * to this view itself, an ancestor view or the window this view is attached to. + * + * @param isVisible true if this view and all of its ancestors are {@link #VISIBLE} + * and this view's window is also visible + */ + @CallSuper + public void onVisibilityAggregated(boolean isVisible) { + if (isVisible && mAttachInfo != null) { + initialAwakenScrollBars(); + } + + final Drawable dr = mBackground; + if (dr != null && isVisible != dr.isVisible()) { + dr.setVisible(isVisible, false); + } + final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; + if (fg != null && isVisible != fg.isVisible()) { + fg.setVisible(isVisible, false); + } + } + + /** * Returns the current visibility of the window this view is attached to * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}). * @@ -11336,6 +11362,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mAttachInfo != null) { dispatchVisibilityChanged(this, newVisibility); + + // Aggregated visibility changes are dispatched to attached views + // in visible windows where the parent is currently shown/drawn + // or the parent is not a ViewGroup (and therefore assumed to be a ViewRoot), + // discounting clipping or overlapping. This makes it a good place + // to change animation states. + if (mParent != null && getWindowVisibility() == VISIBLE && + ((!(mParent instanceof ViewGroup)) || ((ViewGroup) mParent).isShown())) { + dispatchVisibilityAggregated(newVisibility == VISIBLE); + } notifySubtreeAccessibilityStateChangedIfNeeded(); } } @@ -15246,6 +15282,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int vis = info.mWindowVisibility; if (vis != GONE) { onWindowVisibilityChanged(vis); + if (isShown()) { + // Calling onVisibilityChanged directly here since the subtree will also + // receive dispatchAttachedToWindow and this same call + onVisibilityAggregated(vis == VISIBLE); + } } // Send onVisibilityChanged directly instead of dispatchVisibilityChanged. @@ -15266,6 +15307,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, int vis = info.mWindowVisibility; if (vis != GONE) { onWindowVisibilityChanged(GONE); + if (isShown()) { + // Invoking onVisibilityAggregated directly here since the subtree + // will also receive detached from window + onVisibilityAggregated(false); + } } } @@ -17953,9 +17999,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /* * Regardless of whether we're setting a new background or not, we want - * to clear the previous drawable. + * to clear the previous drawable. setVisible first while we still have the callback set. */ if (mBackground != null) { + if (isAttachedToWindow()) { + mBackground.setVisible(false, false); + } mBackground.setCallback(null); unscheduleDrawable(mBackground); } @@ -17994,12 +18043,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback, requestLayout = true; } + // Set mBackground before we set this as the callback and start making other + // background drawable state change calls. In particular, the setVisible call below + // can result in drawables attempting to start animations or otherwise invalidate, + // which requires the view set as the callback (us) to recognize the drawable as + // belonging to it as per verifyDrawable. + mBackground = background; background.setCallback(this); if (background.isStateful()) { background.setState(getDrawableState()); } - background.setVisible(getVisibility() == VISIBLE, false); - mBackground = background; + if (isAttachedToWindow()) { + background.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); + } applyBackgroundTint(); @@ -18178,6 +18234,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } if (mForegroundInfo.mDrawable != null) { + if (isAttachedToWindow()) { + mForegroundInfo.mDrawable.setVisible(false, false); + } mForegroundInfo.mDrawable.setCallback(null); unscheduleDrawable(mForegroundInfo.mDrawable); } @@ -18194,6 +18253,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, foreground.setState(getDrawableState()); } applyForegroundTint(); + if (isAttachedToWindow()) { + foreground.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); + } } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) { mPrivateFlags |= PFLAG_SKIP_DRAW; } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 56ee47895687..aa11e3f96ef5 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1291,6 +1291,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } @Override + boolean dispatchVisibilityAggregated(boolean isVisible) { + isVisible = super.dispatchVisibilityAggregated(isVisible); + final int count = mChildrenCount; + final View[] children = mChildren; + for (int i = 0; i < count; i++) { + // Only dispatch to visible children. Not visible children and their subtrees already + // know that they aren't visible and that's not going to change as a result of + // whatever triggered this dispatch. + if (children[i].getVisibility() == VISIBLE) { + children[i].dispatchVisibilityAggregated(isVisible); + } + } + return isVisible; + } + + @Override public void dispatchConfigurationChanged(Configuration newConfig) { super.dispatchConfigurationChanged(newConfig); final int count = mChildrenCount; diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java index 69c30bac723a..b770bd50c277 100644 --- a/core/java/android/view/ViewOverlay.java +++ b/core/java/android/view/ViewOverlay.java @@ -216,6 +216,9 @@ public class ViewOverlay { public void clear() { removeAllViews(); if (mDrawables != null) { + for (Drawable drawable : mDrawables) { + drawable.setCallback(null); + } mDrawables.clear(); } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f7405e2db304..a2295ce5fecf 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1472,6 +1472,7 @@ public final class ViewRootImpl implements ViewParent, if (viewVisibilityChanged) { mAttachInfo.mWindowVisibility = viewVisibility; host.dispatchWindowVisibilityChanged(viewVisibility); + host.dispatchVisibilityAggregated(viewVisibility == View.VISIBLE); if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) { endDragResizing(); destroyHardwareResources(); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 9f05990fd781..63f37440f832 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -566,8 +566,8 @@ public abstract class Window { * @param data The data list to populate with shortcuts. * @param menu The current menu, which may be null. */ - public void onProvideKeyboardShortcuts( - List<KeyboardShortcutGroup> data, @Nullable Menu menu); + default public void onProvideKeyboardShortcuts( + List<KeyboardShortcutGroup> data, @Nullable Menu menu) { }; } /** @hide */ diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java index a1cbc1d07575..887cc3acb64a 100644 --- a/core/java/android/view/WindowManagerGlobal.java +++ b/core/java/android/view/WindowManagerGlobal.java @@ -170,7 +170,7 @@ public final class WindowManagerGlobal { sWindowManagerService = getWindowManagerService(); ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale()); } catch (RemoteException e) { - Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e); + throw e.rethrowFromSystemServer(); } } return sWindowManagerService; @@ -192,7 +192,7 @@ public final class WindowManagerGlobal { }, imm.getClient(), imm.getInputContext()); } catch (RemoteException e) { - Log.e(TAG, "Failed to open window session", e); + throw e.rethrowFromSystemServer(); } } return sWindowSession; diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index b011414bc556..c1392fe07235 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -91,6 +91,11 @@ public interface WindowManagerPolicy { public final static int FLAG_INTERACTIVE = 0x20000000; public final static int FLAG_PASS_TO_USER = 0x40000000; + // Flags for IActivityManager.keyguardGoingAway() + public final static int KEYGUARD_GOING_AWAY_FLAG_TO_SHADE = 1 << 0; + public final static int KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS = 1 << 1; + public final static int KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER = 1 << 2; + // Flags used for indicating whether the internal and/or external input devices // of some type are available. public final static int PRESENCE_INTERNAL = 1 << 0; @@ -405,6 +410,12 @@ public interface WindowManagerPolicy { * not attached to any stack. */ int getStackId(); + + /** + * Returns true if the window is current in multi-windowing mode. i.e. it shares the + * screen with other application windows. + */ + public boolean inMultiWindowMode(); } /** diff --git a/core/java/android/view/animation/BaseInterpolator.java b/core/java/android/view/animation/BaseInterpolator.java index 9c0014c951c3..a78fa1eac039 100644 --- a/core/java/android/view/animation/BaseInterpolator.java +++ b/core/java/android/view/animation/BaseInterpolator.java @@ -16,22 +16,24 @@ package android.view.animation; +import android.content.pm.ActivityInfo.Config; + /** * An abstract class which is extended by default interpolators. */ abstract public class BaseInterpolator implements Interpolator { - private int mChangingConfiguration; + private @Config int mChangingConfiguration; /** * @hide */ - public int getChangingConfiguration() { + public @Config int getChangingConfiguration() { return mChangingConfiguration; } /** * @hide */ - void setChangingConfiguration(int changingConfiguration) { + void setChangingConfiguration(@Config int changingConfiguration) { mChangingConfiguration = changingConfiguration; } } diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java index df336988cf8f..35d3bf958feb 100644 --- a/core/java/android/view/textservice/SpellCheckerSubtype.java +++ b/core/java/android/view/textservice/SpellCheckerSubtype.java @@ -50,7 +50,10 @@ public final class SpellCheckerSubtype implements Parcelable { private static final String TAG = SpellCheckerSubtype.class.getSimpleName(); private static final String EXTRA_VALUE_PAIR_SEPARATOR = ","; private static final String EXTRA_VALUE_KEY_VALUE_SEPARATOR = "="; - private static final int SUBTYPE_ID_NONE = 0; + /** + * @hide + */ + public static final int SUBTYPE_ID_NONE = 0; private static final String SUBTYPE_LANGUAGE_TAG_NONE = ""; private final int mSubtypeId; diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 2eb258fb6683..b16508ea6afa 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -32,6 +32,7 @@ import android.net.http.SslCertificate; import android.net.Uri; import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.StrictMode; @@ -2622,6 +2623,16 @@ public class WebView extends AbsoluteLayout mProvider.getViewDelegate().onFinishTemporaryDetach(); } + @Override + public Handler getHandler() { + return mProvider.getViewDelegate().getHandler(super.getHandler()); + } + + @Override + public View findFocus() { + return mProvider.getViewDelegate().findFocus(super.findFocus()); + } + /** * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}. * diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 3d722600abd9..0751ab009c80 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -106,6 +106,9 @@ public final class WebViewFactory { public static final int LIBLOAD_WEBVIEW_BEING_REPLACED = 8; public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 9; + // error for namespace lookup + public static final int LIBLOAD_FAILED_TO_FIND_NAMESPACE = 10; + private static String getWebViewPreparationErrorReason(int error) { switch (error) { case LIBLOAD_FAILED_WAITING_FOR_RELRO: @@ -239,7 +242,8 @@ public final class WebViewFactory { * Load the native library for the given package name iff that package * name is the same as the one providing the webview. */ - public static int loadWebViewNativeLibraryFromPackage(String packageName) { + public static int loadWebViewNativeLibraryFromPackage(String packageName, + ClassLoader clazzLoader) { int ret = waitForProviderAndSetPackageInfo(); if (ret != LIBLOAD_SUCCESS) { return ret; @@ -247,7 +251,7 @@ public final class WebViewFactory { if (!sPackageInfo.packageName.equals(packageName)) return LIBLOAD_WRONG_PACKAGE_NAME; - return loadNativeLibrary(); + return loadNativeLibrary(clazzLoader); } static WebViewFactoryProvider getProvider() { @@ -333,15 +337,16 @@ public final class WebViewFactory { Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); } - Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()"); - loadNativeLibrary(); - Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); - Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()"); try { initialApplication.getAssets().addAssetPathAsSharedLibrary( webViewContext.getApplicationInfo().sourceDir); ClassLoader clazzLoader = webViewContext.getClassLoader(); + + Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()"); + loadNativeLibrary(clazzLoader); + Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW); + Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()"); try { return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, @@ -633,7 +638,7 @@ public final class WebViewFactory { } // Assumes that we have waited for relro creation and set sPackageInfo - private static int loadNativeLibrary() { + private static int loadNativeLibrary(ClassLoader clazzLoader) { if (!sAddressSpaceReserved) { Log.e(LOGTAG, "can't load with relro file; address space not reserved"); return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED; @@ -641,9 +646,10 @@ public final class WebViewFactory { String[] args = getWebViewNativeLibraryPaths(sPackageInfo); int result = nativeLoadWithRelroFile(args[0] /* path32 */, - args[1] /* path64 */, - CHROMIUM_WEBVIEW_NATIVE_RELRO_32, - CHROMIUM_WEBVIEW_NATIVE_RELRO_64); + args[1] /* path64 */, + CHROMIUM_WEBVIEW_NATIVE_RELRO_32, + CHROMIUM_WEBVIEW_NATIVE_RELRO_64, + clazzLoader); if (result != LIBLOAD_SUCCESS) { Log.w(LOGTAG, "failed to load with relro file, proceeding without"); } else if (DEBUG) { @@ -672,5 +678,6 @@ public final class WebViewFactory { private static native boolean nativeCreateRelroFile(String lib32, String lib64, String relro32, String relro64); private static native int nativeLoadWithRelroFile(String lib32, String lib64, - String relro32, String relro64); + String relro32, String relro64, + ClassLoader clazzLoader); } diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java index 94d231c45b98..e5b65e7b07d0 100644 --- a/core/java/android/webkit/WebViewProvider.java +++ b/core/java/android/webkit/WebViewProvider.java @@ -28,6 +28,7 @@ import android.graphics.drawable.Drawable; import android.net.http.SslCertificate; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.os.Message; import android.print.PrintDocumentAdapter; import android.view.DragEvent; @@ -386,6 +387,10 @@ public interface WebViewProvider { public void onFinishTemporaryDetach(); public void onActivityResult(int requestCode, int resultCode, Intent data); + + public Handler getHandler(Handler originalHandler); + + public View findFocus(View originalFocusedView); } interface ScrollDelegate { diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 3b6ba3a758a1..4bcb40655772 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -18,6 +18,7 @@ package android.widget; import android.R; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; @@ -216,6 +217,7 @@ public class Editor { boolean mInBatchEditControllers; boolean mShowSoftInputOnFocus = true; private boolean mPreserveSelection; + private boolean mRestartActionModeOnNextRefresh; boolean mTemporaryDetach; boolean mIsBeingLongClicked; @@ -380,9 +382,8 @@ public class Editor { updateSpellCheckSpans(0, mTextView.getText().length(), true /* create the spell checker if needed */); - if (mTextView.getSelectionStart() != mTextView.getSelectionEnd()) { - // We had an active selection from before, start the selection mode. - startSelectionActionMode(); + if (mTextView.hasSelection()) { + refreshTextActionMode(); } getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true); @@ -1081,6 +1082,10 @@ public class Editor { } private void startDragAndDrop() { + // TODO: Fix drag and drop in full screen extracted mode. + if (mTextView.isInExtractedMode()) { + return; + } final int start = mTextView.getSelectionStart(); final int end = mTextView.getSelectionEnd(); CharSequence selectedText = mTextView.getTransformedText(start, end); @@ -1283,7 +1288,7 @@ public class Editor { } final InputMethodManager imm = InputMethodManager.peekInstance(); if (mTextView.hasSelection() && !extractedTextModeWillBeStarted()) { - startSelectionActionMode(); + refreshTextActionMode(); } } else { if (mBlink != null) { @@ -1846,6 +1851,7 @@ public class Editor { void refreshTextActionMode() { if (extractedTextModeWillBeStarted()) { + mRestartActionModeOnNextRefresh = false; return; } final boolean hasSelection = mTextView.hasSelection(); @@ -1854,12 +1860,19 @@ public class Editor { if ((selectionController != null && selectionController.isCursorBeingModified()) || (insertionController != null && insertionController.isCursorBeingModified())) { // ActionMode should be managed by the currently active cursor controller. + mRestartActionModeOnNextRefresh = false; return; } if (hasSelection) { - if (mTextActionMode == null || selectionController == null - || !selectionController.isActive()) { - // Avoid dismissing the selection if it exists. + hideInsertionPointCursorController(); + if (mTextActionMode == null) { + if (mRestartActionModeOnNextRefresh || mTextView.isInExtractedMode()) { + // To avoid distraction, newly start action mode only when selection action + // mode is being restarted or in full screen extracted mode. + startSelectionActionMode(); + } + } else if (selectionController == null || !selectionController.isActive()) { + // Insertion action mode is active. Avoid dismissing the selection. stopTextActionModeWithPreservingSelection(); startSelectionActionMode(); } else { @@ -1874,6 +1887,7 @@ public class Editor { mTextActionMode.invalidateContentRect(); } } + mRestartActionModeOnNextRefresh = false; } /** @@ -1904,11 +1918,12 @@ public class Editor { * * @return true if the selection mode was actually started. */ - private boolean startSelectionActionMode() { + boolean startSelectionActionMode() { boolean selectionStarted = startSelectionActionModeInternal(); if (selectionStarted) { getSelectionController().show(); } + mRestartActionModeOnNextRefresh = false; return selectionStarted; } @@ -2112,6 +2127,9 @@ public class Editor { } private void stopTextActionModeWithPreservingSelection() { + if (mTextActionMode != null) { + mRestartActionModeOnNextRefresh = true; + } mPreserveSelection = true; stopTextActionMode(); mPreserveSelection = false; @@ -2460,7 +2478,7 @@ public class Editor { } final SubMenu subMenu = menu.addSubMenu(Menu.NONE, Menu.NONE, MENU_ITEM_ORDER_REPLACE, com.android.internal.R.string.replace); - final int numItems = mSuggestionHelper.getSuggestionInfo(suggestionInfoArray); + final int numItems = mSuggestionHelper.getSuggestionInfo(suggestionInfoArray, null); for (int i = 0; i < numItems; i++) { final SuggestionInfo info = suggestionInfoArray[i]; subMenu.add(Menu.NONE, Menu.NONE, i, info.mText) @@ -2516,32 +2534,44 @@ public class Editor { mPreserveSelection = true; } - private void replaceWithSuggestion(final SuggestionInfo suggestionInfo) { + @Nullable + private SuggestionSpan findEquivalentSuggestionSpan( + @NonNull SuggestionSpanInfo suggestionSpanInfo) { final Editable editable = (Editable) mTextView.getText(); - if (editable.getSpanStart(suggestionInfo.mSuggestionSpan) < 0) { - // Suggestion span coundn't be found. Try to find a suggestion span that has the same - // contents. - final SuggestionSpan[] suggestionSpans = editable.getSpans( - suggestionInfo.mSuggestionSpanStart, suggestionInfo.mSuggestionSpanEnd, - SuggestionSpan.class); - for (final SuggestionSpan suggestionSpan : suggestionSpans) { - final int spanStart = editable.getSpanStart(suggestionSpan); - if (spanStart != suggestionInfo.mSuggestionSpanStart) { - continue; - } - int spanEnd = editable.getSpanEnd(suggestionSpan); - if (spanEnd != suggestionInfo.mSuggestionSpanEnd) { - continue; - } - if (suggestionSpan.equals(suggestionInfo.mSuggestionSpan)) { - // Found. - suggestionInfo.mSuggestionSpan = suggestionSpan; - break; - } + if (editable.getSpanStart(suggestionSpanInfo.mSuggestionSpan) >= 0) { + // Exactly same span is found. + return suggestionSpanInfo.mSuggestionSpan; + } + // Suggestion span couldn't be found. Try to find a suggestion span that has the same + // contents. + final SuggestionSpan[] suggestionSpans = editable.getSpans(suggestionSpanInfo.mSpanStart, + suggestionSpanInfo.mSpanEnd, SuggestionSpan.class); + for (final SuggestionSpan suggestionSpan : suggestionSpans) { + final int start = editable.getSpanStart(suggestionSpan); + if (start != suggestionSpanInfo.mSpanStart) { + continue; + } + final int end = editable.getSpanEnd(suggestionSpan); + if (end != suggestionSpanInfo.mSpanEnd) { + continue; + } + if (suggestionSpan.equals(suggestionSpanInfo.mSuggestionSpan)) { + return suggestionSpan; } } - final int spanStart = editable.getSpanStart(suggestionInfo.mSuggestionSpan); - final int spanEnd = editable.getSpanEnd(suggestionInfo.mSuggestionSpan); + return null; + } + + private void replaceWithSuggestion(@NonNull final SuggestionInfo suggestionInfo) { + final SuggestionSpan targetSuggestionSpan = findEquivalentSuggestionSpan( + suggestionInfo.mSuggestionSpanInfo); + if (targetSuggestionSpan == null) { + // Span has been removed + return; + } + final Editable editable = (Editable) mTextView.getText(); + final int spanStart = editable.getSpanStart(targetSuggestionSpan); + final int spanEnd = editable.getSpanEnd(targetSuggestionSpan); if (spanStart < 0 || spanEnd <= spanStart) { // Span has been removed return; @@ -2571,7 +2601,7 @@ public class Editor { } // Notify source IME of the suggestion pick. Do this before swapping texts. - suggestionInfo.mSuggestionSpan.notifySelection( + targetSuggestionSpan.notifySelection( mTextView.getContext(), originalText, suggestionInfo.mSuggestionIndex); // Swap text content between actual text and Suggestion span @@ -2581,7 +2611,7 @@ public class Editor { suggestionStart, suggestionEnd).toString(); mTextView.replaceText_internal(spanStart, spanEnd, suggestion); - String[] suggestions = suggestionInfo.mSuggestionSpan.getSuggestions(); + String[] suggestions = targetSuggestionSpan.getSuggestions(); suggestions[suggestionInfo.mSuggestionIndex] = originalText; // Restore previous SuggestionSpans @@ -3029,28 +3059,44 @@ public class Editor { } } - private static class SuggestionInfo { + private static final class SuggestionInfo { // Range of actual suggestion within mText int mSuggestionStart, mSuggestionEnd; // The SuggestionSpan that this TextView represents + final SuggestionSpanInfo mSuggestionSpanInfo = new SuggestionSpanInfo(); + + // The index of this suggestion inside suggestionSpan + int mSuggestionIndex; + + final SpannableStringBuilder mText = new SpannableStringBuilder(); + + void clear() { + mSuggestionSpanInfo.clear(); + mText.clear(); + } + + // Utility method to set attributes about a SuggestionSpan. + void setSpanInfo(SuggestionSpan span, int spanStart, int spanEnd) { + mSuggestionSpanInfo.mSuggestionSpan = span; + mSuggestionSpanInfo.mSpanStart = spanStart; + mSuggestionSpanInfo.mSpanEnd = spanEnd; + } + } + + private static final class SuggestionSpanInfo { + // The SuggestionSpan; @Nullable SuggestionSpan mSuggestionSpan; // The SuggestionSpan start position - int mSuggestionSpanStart; + int mSpanStart; // The SuggestionSpan end position - int mSuggestionSpanEnd; - - // The index of this suggestion inside suggestionSpan - int mSuggestionIndex; - - final SpannableStringBuilder mText = new SpannableStringBuilder(); + int mSpanEnd; void clear() { mSuggestionSpan = null; - mText.clear(); } } @@ -3109,48 +3155,51 @@ public class Editor { * position. * * @param suggestionInfos SuggestionInfo array the results will be set. + * @param misspelledSpanInfo a struct the misspelled SuggestionSpan info will be set. * @return the number of suggestions actually fetched. */ - public int getSuggestionInfo(SuggestionInfo[] suggestionInfos) { + public int getSuggestionInfo(SuggestionInfo[] suggestionInfos, + @Nullable SuggestionSpanInfo misspelledSpanInfo) { final Spannable spannable = (Spannable) mTextView.getText(); final SuggestionSpan[] suggestionSpans = getSortedSuggestionSpans(); final int nbSpans = suggestionSpans.length; if (nbSpans == 0) return 0; int numberOfSuggestions = 0; - for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) { - final SuggestionSpan suggestionSpan = suggestionSpans[spanIndex]; + for (final SuggestionSpan suggestionSpan : suggestionSpans) { final int spanStart = spannable.getSpanStart(suggestionSpan); final int spanEnd = spannable.getSpanEnd(suggestionSpan); + if (misspelledSpanInfo != null + && (suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) { + misspelledSpanInfo.mSuggestionSpan = suggestionSpan; + misspelledSpanInfo.mSpanStart = spanStart; + misspelledSpanInfo.mSpanEnd = spanEnd; + } + final String[] suggestions = suggestionSpan.getSuggestions(); final int nbSuggestions = suggestions.length; + suggestionLoop: for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) { final String suggestion = suggestions[suggestionIndex]; - boolean suggestionIsDuplicate = false; for (int i = 0; i < numberOfSuggestions; i++) { - if (suggestionInfos[i].mText.toString().equals(suggestion)) { - final SuggestionSpan otherSuggestionSpan = - suggestionInfos[i].mSuggestionSpan; - final int otherSpanStart = spannable.getSpanStart(otherSuggestionSpan); - final int otherSpanEnd = spannable.getSpanEnd(otherSuggestionSpan); + final SuggestionInfo otherSuggestionInfo = suggestionInfos[i]; + if (otherSuggestionInfo.mText.toString().equals(suggestion)) { + final int otherSpanStart = + otherSuggestionInfo.mSuggestionSpanInfo.mSpanStart; + final int otherSpanEnd = + otherSuggestionInfo.mSuggestionSpanInfo.mSpanEnd; if (spanStart == otherSpanStart && spanEnd == otherSpanEnd) { - suggestionIsDuplicate = true; - break; + continue suggestionLoop; } } } - if (suggestionIsDuplicate) { - continue; - } SuggestionInfo suggestionInfo = suggestionInfos[numberOfSuggestions]; - suggestionInfo.mSuggestionSpan = suggestionSpan; + suggestionInfo.setSpanInfo(suggestionSpan, spanStart, spanEnd); suggestionInfo.mSuggestionIndex = suggestionIndex; suggestionInfo.mSuggestionStart = 0; suggestionInfo.mSuggestionEnd = suggestion.length(); - suggestionInfo.mSuggestionSpanStart = spanStart; - suggestionInfo.mSuggestionSpanEnd = spanEnd; suggestionInfo.mText.replace(0, suggestionInfo.mText.length(), suggestion); numberOfSuggestions++; if (numberOfSuggestions >= suggestionInfos.length) { @@ -3180,7 +3229,7 @@ public class Editor { private TextView mAddToDictionaryButton; private TextView mDeleteButton; private ListView mSuggestionListView; - private SuggestionSpan mMisspelledSpan; + private final SuggestionSpanInfo mMisspelledSpanInfo = new SuggestionSpanInfo(); private int mContainerMarginWidth; private int mContainerMarginTop; @@ -3252,9 +3301,18 @@ public class Editor { com.android.internal.R.id.addToDictionaryButton); mAddToDictionaryButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { + final SuggestionSpan misspelledSpan = + findEquivalentSuggestionSpan(mMisspelledSpanInfo); + if (misspelledSpan == null) { + // Span has been removed. + return; + } final Editable editable = (Editable) mTextView.getText(); - final int spanStart = editable.getSpanStart(mMisspelledSpan); - final int spanEnd = editable.getSpanEnd(mMisspelledSpan); + final int spanStart = editable.getSpanStart(misspelledSpan); + final int spanEnd = editable.getSpanEnd(misspelledSpan); + if (spanStart < 0 || spanEnd <= spanStart) { + return; + } final String originalText = TextUtils.substring(editable, spanStart, spanEnd); final Intent intent = new Intent(Settings.ACTION_USER_DICTIONARY_INSERT); @@ -3265,7 +3323,7 @@ public class Editor { mTextView.getContext().startActivity(intent); // There is no way to know if the word was indeed added. Re-check. // TODO The ExtractEditText should remove the span in the original text instead - editable.removeSpan(mMisspelledSpan); + editable.removeSpan(mMisspelledSpanInfo.mSuggestionSpan); Selection.setSelection(editable, spanEnd); updateSpellCheckSpans(spanStart, spanEnd, false); hideWithCleanUp(); @@ -3422,30 +3480,29 @@ public class Editor { for (final SuggestionInfo info : mSuggestionInfos) { info.clear(); } - mMisspelledSpan = null; + mMisspelledSpanInfo.clear(); hide(); } private boolean updateSuggestions() { Spannable spannable = (Spannable) mTextView.getText(); mNumberOfSuggestions = - mSuggestionHelper.getSuggestionInfo(mSuggestionInfos); - if (mNumberOfSuggestions == 0) { + mSuggestionHelper.getSuggestionInfo(mSuggestionInfos, mMisspelledSpanInfo); + if (mNumberOfSuggestions == 0 && mMisspelledSpanInfo.mSuggestionSpan == null) { return false; } int spanUnionStart = mTextView.getText().length(); int spanUnionEnd = 0; - mMisspelledSpan = null; for (int i = 0; i < mNumberOfSuggestions; i++) { - final SuggestionInfo suggestionInfo = mSuggestionInfos[i]; - final SuggestionSpan suggestionSpan = suggestionInfo.mSuggestionSpan; - if ((suggestionSpan.getFlags() & SuggestionSpan.FLAG_MISSPELLED) != 0) { - mMisspelledSpan = suggestionSpan; - } - spanUnionStart = Math.min(spanUnionStart, suggestionInfo.mSuggestionSpanStart); - spanUnionEnd = Math.max(spanUnionEnd, suggestionInfo.mSuggestionSpanEnd); + final SuggestionSpanInfo spanInfo = mSuggestionInfos[i].mSuggestionSpanInfo; + spanUnionStart = Math.min(spanUnionStart, spanInfo.mSpanStart); + spanUnionEnd = Math.max(spanUnionEnd, spanInfo.mSpanEnd); + } + if (mMisspelledSpanInfo.mSuggestionSpan != null) { + spanUnionStart = Math.min(spanUnionStart, mMisspelledSpanInfo.mSpanStart); + spanUnionEnd = Math.max(spanUnionEnd, mMisspelledSpanInfo.mSpanEnd); } for (int i = 0; i < mNumberOfSuggestions; i++) { @@ -3454,17 +3511,23 @@ public class Editor { // Make "Add to dictionary" item visible if there is a span with the misspelled flag int addToDictionaryButtonVisibility = View.GONE; - if (mMisspelledSpan != null) { - final int misspelledStart = spannable.getSpanStart(mMisspelledSpan); - final int misspelledEnd = spannable.getSpanEnd(mMisspelledSpan); - if (misspelledStart >= 0 && misspelledEnd > misspelledStart) { + if (mMisspelledSpanInfo.mSuggestionSpan != null) { + if (mMisspelledSpanInfo.mSpanStart >= 0 + && mMisspelledSpanInfo.mSpanEnd > mMisspelledSpanInfo.mSpanStart) { addToDictionaryButtonVisibility = View.VISIBLE; } } mAddToDictionaryButton.setVisibility(addToDictionaryButtonVisibility); if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan(); - final int underlineColor = mSuggestionInfos[0].mSuggestionSpan.getUnderlineColor(); + final int underlineColor; + if (mNumberOfSuggestions != 0) { + underlineColor = + mSuggestionInfos[0].mSuggestionSpanInfo.mSuggestionSpan.getUnderlineColor(); + } else { + underlineColor = mMisspelledSpanInfo.mSuggestionSpan.getUnderlineColor(); + } + if (underlineColor == 0) { // Fallback on the default highlight color when the first span does not provide one mSuggestionRangeSpan.setBackgroundColor(mTextView.mHighlightColor); @@ -3484,8 +3547,8 @@ public class Editor { private void highlightTextDifferences(SuggestionInfo suggestionInfo, int unionStart, int unionEnd) { final Spannable text = (Spannable) mTextView.getText(); - final int spanStart = suggestionInfo.mSuggestionSpanStart; - final int spanEnd = suggestionInfo.mSuggestionSpanEnd; + final int spanStart = suggestionInfo.mSuggestionSpanInfo.mSpanStart; + final int spanEnd = suggestionInfo.mSuggestionSpanInfo.mSpanEnd; // Adjust the start/end of the suggestion span suggestionInfo.mSuggestionStart = spanStart - unionStart; @@ -3661,6 +3724,8 @@ public class Editor { @Override public void onDestroyActionMode(ActionMode mode) { + // Clear mTextActionMode not to recursively destroy action mode by clearing selection. + mTextActionMode = null; Callback customCallback = getCustomCallback(); if (customCallback != null) { customCallback.onDestroyActionMode(mode); @@ -3679,8 +3744,6 @@ public class Editor { if (mSelectionModifierCursorController != null) { mSelectionModifierCursorController.hide(); } - - mTextActionMode = null; } @Override @@ -5083,27 +5146,12 @@ public class Editor { // No longer dragging to select text, let the parent intercept events. mTextView.getParent().requestDisallowInterceptTouchEvent(false); - int startOffset = mTextView.getSelectionStart(); - int endOffset = mTextView.getSelectionEnd(); - - // Since we don't let drag handles pass once they're visible, we need to - // make sure the start / end locations are correct because the user *can* - // switch directions during the initial drag. - if (endOffset < startOffset) { - int tmp = endOffset; - endOffset = startOffset; - startOffset = tmp; + // No longer the first dragging motion, reset. + resetDragAcceleratorState(); - // Also update the selection with the right offsets in this case. - Selection.setSelection((Spannable) mTextView.getText(), - startOffset, endOffset); - } - if (startOffset != endOffset) { + if (mTextView.hasSelection()) { startSelectionActionMode(); } - - // No longer the first dragging motion, reset. - resetDragAcceleratorState(); break; } } diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java index 1321221eb89f..6d7313da0043 100644 --- a/core/java/android/widget/GridView.java +++ b/core/java/android/widget/GridView.java @@ -1644,7 +1644,7 @@ public class GridView extends AbsListView { boolean handled = false; int action = event.getAction(); if (KeyEvent.isConfirmKey(keyCode) - && event.hasNoModifiers() && action == KeyEvent.ACTION_UP) { + && event.hasNoModifiers() && action != KeyEvent.ACTION_UP) { handled = resurrectSelectionIfNeeded(); if (!handled && event.getRepeatCount() == 0 && getChildCount() > 0) { keyPressed(); diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index 3400873896f8..04d344f0caa6 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -913,6 +913,7 @@ public class ImageView extends View { if (mDrawable != null) { mDrawable.setCallback(null); unscheduleDrawable(mDrawable); + mDrawable.setVisible(false, false); } mDrawable = d; @@ -923,7 +924,8 @@ public class ImageView extends View { if (d.isStateful()) { d.setState(getDrawableState()); } - d.setVisible(getVisibility() == VISIBLE, true); + d.setVisible(isAttachedToWindow() && getWindowVisibility() == VISIBLE && isShown(), + true); d.setLevel(mLevel); mDrawableWidth = d.getIntrinsicWidth(); mDrawableHeight = d.getIntrinsicHeight(); @@ -1498,28 +1500,11 @@ public class ImageView extends View { } } - @RemotableViewMethod - @Override - public void setVisibility(int visibility) { - super.setVisibility(visibility); - if (mDrawable != null) { - mDrawable.setVisible(visibility == VISIBLE, false); - } - } - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); + public void onVisibilityAggregated(boolean isVisible) { + super.onVisibilityAggregated(isVisible); if (mDrawable != null) { - mDrawable.setVisible(getVisibility() == VISIBLE, false); - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mDrawable != null) { - mDrawable.setVisible(false, false); + mDrawable.setVisible(isVisible, false); } } diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index ce948706542f..e9fa26ce4658 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -246,6 +246,8 @@ public class ProgressBar extends View { boolean mMirrorForRtl = false; + private boolean mAggregatedIsVisible; + private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>(); private AccessibilityEventSender mAccessibilityEventSender; @@ -615,14 +617,13 @@ public class ProgressBar extends View { private void swapCurrentDrawable(Drawable newDrawable) { final Drawable oldDrawable = mCurrentDrawable; mCurrentDrawable = newDrawable; + if (oldDrawable != mCurrentDrawable) { if (oldDrawable != null) { oldDrawable.setVisible(false, false); } if (mCurrentDrawable != null) { - mCurrentDrawable.setVisible( - getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE, - false); + mCurrentDrawable.setVisible(getWindowVisibility() == VISIBLE && isShown(), false); } } } @@ -1645,50 +1646,25 @@ public class ProgressBar extends View { } @Override - @RemotableViewMethod - public void setVisibility(int v) { - if (getVisibility() != v) { - super.setVisibility(v); + public void onVisibilityAggregated(boolean isVisible) { + super.onVisibilityAggregated(isVisible); + + if (isVisible != mAggregatedIsVisible) { + mAggregatedIsVisible = isVisible; if (mIndeterminate) { // let's be nice with the UI thread - if (v == GONE || v == INVISIBLE) { - stopAnimation(); - } else { + if (isVisible) { startAnimation(); + } else { + stopAnimation(); } } - } - } - @Override - protected void onVisibilityChanged(View changedView, int visibility) { - super.onVisibilityChanged(changedView, visibility); - - updateVisibility(); - } - - @Override - protected void onWindowVisibilityChanged(@Visibility int visibility) { - super.onWindowVisibilityChanged(visibility); - - updateVisibility(); - } - - private void updateVisibility() { - final boolean isVisible = getVisibility() == VISIBLE && getWindowVisibility() == VISIBLE; - if (mIndeterminate) { - // let's be nice with the UI thread - if (isVisible) { - startAnimation(); - } else { - stopAnimation(); + if (mCurrentDrawable != null) { + mCurrentDrawable.setVisible(isVisible, false); } } - - if (mCurrentDrawable != null) { - mCurrentDrawable.setVisible(isVisible, false); - } } @Override diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 97cdac14ef3c..506035087ead 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -6552,7 +6552,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (TextUtils.equals(content.subSequence(start, end), text.text)) { if (text.text instanceof Spanned) { // OK to copy spans only. - TextUtils.copySpansFrom((Spanned) text.text, start, end, + TextUtils.copySpansFrom((Spanned) text.text, 0, end - start, Object.class, content, start); } } else { @@ -9212,6 +9212,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (start >= 0 && start <= end && end <= text.length()) { Selection.setSelection((Spannable) text, start, end); + // Make sure selection mode is engaged. + if (mEditor != null) { + mEditor.startSelectionActionMode(); + } return true; } } diff --git a/core/java/com/android/internal/app/UnlaunchableAppActivity.java b/core/java/com/android/internal/app/UnlaunchableAppActivity.java index 29190f9baa0a..f6fbaab8f8f3 100644 --- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java +++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java @@ -42,15 +42,13 @@ import com.android.internal.R; /** * A dialog shown to the user when they try to launch an app from a quiet profile - * ({@link UserManager#isQuietModeEnabled(UserHandle)}, or when the app is suspended by the - * profile owner or device owner. + * ({@link UserManager#isQuietModeEnabled(UserHandle)}. */ public class UnlaunchableAppActivity extends Activity implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { private static final String TAG = "UnlaunchableAppActivity"; private static final int UNLAUNCHABLE_REASON_QUIET_MODE = 1; - private static final int UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE = 2; private static final String EXTRA_UNLAUNCHABLE_REASON = "unlaunchable_reason"; private int mUserId; @@ -74,37 +72,6 @@ public class UnlaunchableAppActivity extends Activity if (mReason == UNLAUNCHABLE_REASON_QUIET_MODE) { dialogTitle = getResources().getString(R.string.work_mode_off_title); dialogMessage = getResources().getString(R.string.work_mode_off_message); - } else if (mReason == UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE) { - DevicePolicyManager dpm = (DevicePolicyManager) getSystemService( - Context.DEVICE_POLICY_SERVICE); - String packageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); - String packageLabel = packageName; - try { - Context userContext = createPackageContextAsUser(packageName, 0, - UserHandle.of(mUserId)); - ApplicationInfo appInfo = userContext.getApplicationInfo(); - if (appInfo != null) { - packageLabel = userContext.getPackageManager().getApplicationLabel(appInfo) - .toString(); - } - } catch (NameNotFoundException e) { - } - dialogTitle = String.format(getResources().getString(R.string.suspended_package_title), - packageLabel); - ComponentName profileOwner = dpm.getProfileOwnerAsUser(mUserId); - String profileOwnerName = null; - if (profileOwner != null) { - dialogMessage = dpm.getShortSupportMessageForUser(profileOwner, mUserId); - profileOwnerName = dpm.getProfileOwnerNameAsUser(mUserId); - } - // Fall back to standard message if profile owner hasn't set something specific. - if (TextUtils.isEmpty(dialogMessage)) { - if (TextUtils.isEmpty(profileOwnerName)) { - profileOwnerName = getResources().getString(R.string.unknownName); - } - dialogMessage = getResources().getString(R.string.suspended_package_message, - profileOwnerName); - } } else { Log.wtf(TAG, "Invalid unlaunchable type: " + mReason); finish(); @@ -154,12 +121,4 @@ public class UnlaunchableAppActivity extends Activity intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); return intent; } - - public static Intent createPackageSuspendedDialogIntent(String packageName, int userId) { - Intent intent = createBaseIntent(); - intent.putExtra(EXTRA_UNLAUNCHABLE_REASON, UNLAUNCHABLE_REASON_SUSPENDED_PACKAGE); - intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); - return intent; - } } diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java index 90ee05ec944b..f3ae6881b74a 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java +++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java @@ -854,7 +854,8 @@ public class InputMethodUtils { private final HashMap<String, String> mCopyOnWriteDataStore = new HashMap<>(); private boolean mCopyOnWrite = false; - private String mEnabledInputMethodsStrCache; + @NonNull + private String mEnabledInputMethodsStrCache = ""; @UserIdInt private int mCurrentUserId; private int[] mCurrentProfileIds = new int[0]; @@ -908,14 +909,6 @@ public class InputMethodUtils { return imsList; } - @Deprecated - public InputMethodSettings( - Resources res, ContentResolver resolver, - HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList, - @UserIdInt int userId) { - this(res, resolver, methodMap, methodList, userId, false /* copyOnWrite */); - } - public InputMethodSettings( Resources res, ContentResolver resolver, HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList, @@ -949,7 +942,7 @@ public class InputMethodUtils { // TODO: mCurrentProfileIds should be updated here. } - private void putString(final String key, final String str) { + private void putString(@NonNull final String key, @Nullable final String str) { if (mCopyOnWrite) { mCopyOnWriteDataStore.put(key, str); } else { @@ -957,12 +950,15 @@ public class InputMethodUtils { } } - private String getString(final String key) { + @Nullable + private String getString(@NonNull final String key, @Nullable final String defaultValue) { + final String result; if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) { - final String result = mCopyOnWriteDataStore.get(key); - return result != null ? result : ""; + result = mCopyOnWriteDataStore.get(key); + } else { + result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId); } - return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId); + return result != null ? result : defaultValue; } private void putInt(final String key, final int value) { @@ -1124,16 +1120,24 @@ public class InputMethodUtils { return res; } - private void putEnabledInputMethodsStr(String str) { + private void putEnabledInputMethodsStr(@Nullable String str) { if (DEBUG) { Slog.d(TAG, "putEnabledInputMethodStr: " + str); } - putString(Settings.Secure.ENABLED_INPUT_METHODS, str); - mEnabledInputMethodsStrCache = str; + if (TextUtils.isEmpty(str)) { + // OK to coalesce to null, since getEnabledInputMethodsStr() can take care of the + // empty data scenario. + putString(Settings.Secure.ENABLED_INPUT_METHODS, null); + } else { + putString(Settings.Secure.ENABLED_INPUT_METHODS, str); + } + // TODO: Update callers of putEnabledInputMethodsStr to make str @NonNull. + mEnabledInputMethodsStrCache = (str != null ? str : ""); } + @NonNull public String getEnabledInputMethodsStr() { - mEnabledInputMethodsStrCache = getString(Settings.Secure.ENABLED_INPUT_METHODS); + mEnabledInputMethodsStrCache = getString(Settings.Secure.ENABLED_INPUT_METHODS, ""); if (DEBUG) { Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache + ", " + mCurrentUserId); @@ -1187,11 +1191,17 @@ public class InputMethodUtils { saveSubtypeHistory(subtypeHistory, imeId, subtypeId); } - private void putSubtypeHistoryStr(String str) { + private void putSubtypeHistoryStr(@NonNull String str) { if (DEBUG) { Slog.d(TAG, "putSubtypeHistoryStr: " + str); } - putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str); + if (TextUtils.isEmpty(str)) { + // OK to coalesce to null, since getSubtypeHistoryStr() can take care of the empty + // data scenario. + putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, null); + } else { + putString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str); + } } public Pair<String, String> getLastInputMethodAndSubtypeLocked() { @@ -1308,8 +1318,9 @@ public class InputMethodUtils { return imsList; } + @NonNull private String getSubtypeHistoryStr() { - final String history = getString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY); + final String history = getString(Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, ""); if (DEBUG) { Slog.d(TAG, "getSubtypeHistoryStr: " + history); } @@ -1332,8 +1343,9 @@ public class InputMethodUtils { putInt(Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, subtypeId); } + @Nullable public String getSelectedInputMethod() { - final String imi = getString(Settings.Secure.DEFAULT_INPUT_METHOD); + final String imi = getString(Settings.Secure.DEFAULT_INPUT_METHOD, null); if (DEBUG) { Slog.d(TAG, "getSelectedInputMethodStr: " + imi); } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index c484121236ac..8de9c098e31a 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -1953,7 +1953,7 @@ public class BatteryStatsImpl extends BatteryStats { */ @Override public LongSamplingCounter getIdleTimeCounter() { - return mRxTimeMillis; + return mIdleTimeMillis; } /** diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index df48d6d0df8c..fbd8fb52da6d 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -2073,11 +2073,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> list) { final PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false); if (!mWindow.isDestroyed() && st != null && mWindow.getCallback() != null) { - try { - mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu); - } catch (AbstractMethodError e) { - // We run into this if the app is using supportlib. - } + mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu); } } diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 623b603d8280..c6db0ed6cb69 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -36,7 +36,7 @@ LOCAL_SRC_FILES:= \ android_app_Activity.cpp \ android_app_ApplicationLoaders.cpp \ android_app_NativeActivity.cpp \ - android_auditing_SecurityLog.cpp \ + android_app_admin_SecurityLog.cpp \ android_opengl_EGL14.cpp \ android_opengl_EGLExt.cpp \ android_opengl_GLES10.cpp \ @@ -161,6 +161,7 @@ LOCAL_SRC_FILES:= \ android_hardware_UsbDevice.cpp \ android_hardware_UsbDeviceConnection.cpp \ android_hardware_UsbRequest.cpp \ + android_hardware_location_ContextHubService.cpp \ android_hardware_location_ActivityRecognitionHardware.cpp \ android_util_FileObserver.cpp \ android/opengl/poly_clip.cpp.arm \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 2a04526ed3eb..7ff38fd58db7 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -95,6 +95,7 @@ extern int register_android_hardware_UsbDevice(JNIEnv *env); extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env); extern int register_android_hardware_UsbRequest(JNIEnv *env); extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env); +extern int register_android_hardware_location_ContextHubService(JNIEnv* env); extern int register_android_media_AudioRecord(JNIEnv *env); extern int register_android_media_AudioSystem(JNIEnv *env); @@ -108,7 +109,7 @@ namespace android { * JNI-based registration functions. Note these are properly contained in * namespace android. */ -extern int register_android_auditing_SecurityLog(JNIEnv* env); +extern int register_android_app_admin_SecurityLog(JNIEnv* env); extern int register_android_content_AssetManager(JNIEnv* env); extern int register_android_util_EventLog(JNIEnv* env); extern int register_android_util_Log(JNIEnv* env); @@ -1184,8 +1185,7 @@ static int javaDetachThread(void) void** args = (void**) malloc(3 * sizeof(void*)); // javaThreadShell must free int result; - if (!threadName) - threadName = "unnamed thread"; + LOG_ALWAYS_FATAL_IF(threadName == nullptr, "threadName not provided to javaCreateThreadEtc"); args[0] = (void*) entryFunction; args[1] = userData; @@ -1253,7 +1253,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_util_EventLog), REG_JNI(register_android_util_Log), REG_JNI(register_android_util_PathParser), - REG_JNI(register_android_auditing_SecurityLog), + REG_JNI(register_android_app_admin_SecurityLog), REG_JNI(register_android_content_AssetManager), REG_JNI(register_android_content_StringBlock), REG_JNI(register_android_content_XmlBlock), @@ -1358,6 +1358,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_hardware_UsbDeviceConnection), REG_JNI(register_android_hardware_UsbRequest), REG_JNI(register_android_hardware_location_ActivityRecognitionHardware), + REG_JNI(register_android_hardware_location_ContextHubService), REG_JNI(register_android_media_AudioRecord), REG_JNI(register_android_media_AudioSystem), REG_JNI(register_android_media_AudioTrack), diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index fb9b1e53aa8a..4001283c4c66 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -73,6 +73,9 @@ jstring encodedFormatToString(JNIEnv* env, SkEncodedFormat format) { case SkEncodedFormat::kWBMP_SkEncodedFormat: mimeType = "image/vnd.wap.wbmp"; break; + case SkEncodedFormat::kRAW_SkEncodedFormat: + mimeType = "image/x-adobe-dng"; + break; default: mimeType = nullptr; break; diff --git a/core/jni/android/graphics/Xfermode.cpp b/core/jni/android/graphics/Xfermode.cpp index 7441acc95cea..78975a4f9787 100644 --- a/core/jni/android/graphics/Xfermode.cpp +++ b/core/jni/android/graphics/Xfermode.cpp @@ -15,34 +15,20 @@ */ #include "jni.h" -#include "GraphicsJNI.h" +//#include "GraphicsJNI.h" #include "core_jni_helpers.h" -#include "AvoidXfermode.h" -#include "SkPixelXorXfermode.h" +#include <SkXfermode.h> namespace android { class SkXfermodeGlue { public: - static void finalizer(JNIEnv* env, jobject, jlong objHandle) { SkXfermode* obj = reinterpret_cast<SkXfermode *>(objHandle); SkSafeUnref(obj); } - - static jlong avoid_create(JNIEnv* env, jobject, jint opColor, - jint tolerance, jint modeHandle) - { - AvoidXfermode::Mode mode = static_cast<AvoidXfermode::Mode>(modeHandle); - return reinterpret_cast<jlong>(AvoidXfermode::Create(opColor, tolerance, mode)); - } - - static jlong pixelxor_create(JNIEnv* env, jobject, jint opColor) - { - return reinterpret_cast<jlong>(SkPixelXorXfermode::Create(opColor)); - } }; /////////////////////////////////////////////////////////////////////////////// @@ -51,24 +37,9 @@ static const JNINativeMethod gXfermodeMethods[] = { {"finalizer", "(J)V", (void*) SkXfermodeGlue::finalizer} }; -static const JNINativeMethod gAvoidMethods[] = { - {"nativeCreate", "(III)J", (void*) SkXfermodeGlue::avoid_create} -}; - -static const JNINativeMethod gPixelXorMethods[] = { - {"nativeCreate", "(I)J", (void*) SkXfermodeGlue::pixelxor_create} -}; - int register_android_graphics_Xfermode(JNIEnv* env) { android::RegisterMethodsOrDie(env, "android/graphics/Xfermode", gXfermodeMethods, NELEM(gXfermodeMethods)); - android::RegisterMethodsOrDie(env, "android/graphics/Xfermode", gXfermodeMethods, - NELEM(gXfermodeMethods)); - android::RegisterMethodsOrDie(env, "android/graphics/AvoidXfermode", gAvoidMethods, - NELEM(gAvoidMethods)); - android::RegisterMethodsOrDie(env, "android/graphics/PixelXorXfermode", gPixelXorMethods, - NELEM(gPixelXorMethods)); - return 0; } diff --git a/core/jni/android_app_admin_SecurityLog.cpp b/core/jni/android_app_admin_SecurityLog.cpp new file mode 100644 index 000000000000..da47c4c0fbb9 --- /dev/null +++ b/core/jni/android_app_admin_SecurityLog.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fcntl.h> + +#include "JNIHelp.h" +#include "core_jni_helpers.h" +#include "jni.h" +#include "log/logger.h" + +// The size of the tag number comes out of the payload size. +#define MAX_EVENT_PAYLOAD (LOGGER_ENTRY_MAX_PAYLOAD - sizeof(int32_t)) + +namespace android { + +static jclass gCollectionClass; +static jmethodID gCollectionAddID; + +static jclass gEventClass; +static jmethodID gEventInitID; + +static jclass gIntegerClass; +static jfieldID gIntegerValueID; + +static jclass gLongClass; +static jfieldID gLongValueID; + +static jclass gFloatClass; +static jfieldID gFloatValueID; + +static jclass gStringClass; + + +static jboolean android_app_admin_SecurityLog_isLoggingEnabled(JNIEnv* env, + jobject /* clazz */) { + return (bool)__android_log_security(); +} + +static jint android_app_admin_SecurityLog_writeEvent_String(JNIEnv* env, + jobject /* clazz */, + jint tag, jstring value) { + uint8_t buf[MAX_EVENT_PAYLOAD]; + + // Don't throw NPE -- I feel like it's sort of mean for a logging function + // to be all crashy if you pass in NULL -- but make the NULL value explicit. + const char *str = value != NULL ? env->GetStringUTFChars(value, NULL) : "NULL"; + uint32_t len = strlen(str); + size_t max = sizeof(buf) - sizeof(len) - 2; // Type byte, final newline + if (len > max) len = max; + + buf[0] = EVENT_TYPE_STRING; + memcpy(&buf[1], &len, sizeof(len)); + memcpy(&buf[1 + sizeof(len)], str, len); + buf[1 + sizeof(len) + len] = '\n'; + + if (value != NULL) env->ReleaseStringUTFChars(value, str); + return __android_log_security_bwrite(tag, buf, 2 + sizeof(len) + len); +} + +static jint android_app_admin_SecurityLog_writeEvent_Array(JNIEnv* env, jobject clazz, + jint tag, jobjectArray value) { + if (value == NULL) { + return android_app_admin_SecurityLog_writeEvent_String(env, clazz, tag, NULL); + } + + uint8_t buf[MAX_EVENT_PAYLOAD]; + const size_t max = sizeof(buf) - 1; // leave room for final newline + size_t pos = 2; // Save room for type tag & array count + + jsize copied = 0, num = env->GetArrayLength(value); + for (; copied < num && copied < 255; ++copied) { + jobject item = env->GetObjectArrayElement(value, copied); + if (item == NULL || env->IsInstanceOf(item, gStringClass)) { + if (pos + 1 + sizeof(jint) > max) break; + const char *str = item != NULL ? env->GetStringUTFChars((jstring) item, NULL) : "NULL"; + jint len = strlen(str); + if (pos + 1 + sizeof(len) + len > max) len = max - pos - 1 - sizeof(len); + buf[pos++] = EVENT_TYPE_STRING; + memcpy(&buf[pos], &len, sizeof(len)); + memcpy(&buf[pos + sizeof(len)], str, len); + pos += sizeof(len) + len; + if (item != NULL) env->ReleaseStringUTFChars((jstring) item, str); + } else if (env->IsInstanceOf(item, gIntegerClass)) { + jint intVal = env->GetIntField(item, gIntegerValueID); + if (pos + 1 + sizeof(intVal) > max) break; + buf[pos++] = EVENT_TYPE_INT; + memcpy(&buf[pos], &intVal, sizeof(intVal)); + pos += sizeof(intVal); + } else if (env->IsInstanceOf(item, gLongClass)) { + jlong longVal = env->GetLongField(item, gLongValueID); + if (pos + 1 + sizeof(longVal) > max) break; + buf[pos++] = EVENT_TYPE_LONG; + memcpy(&buf[pos], &longVal, sizeof(longVal)); + pos += sizeof(longVal); + } else if (env->IsInstanceOf(item, gFloatClass)) { + jfloat floatVal = env->GetFloatField(item, gFloatValueID); + if (pos + 1 + sizeof(floatVal) > max) break; + buf[pos++] = EVENT_TYPE_FLOAT; + memcpy(&buf[pos], &floatVal, sizeof(floatVal)); + pos += sizeof(floatVal); + } else { + jniThrowException(env, + "java/lang/IllegalArgumentException", + "Invalid payload item type"); + return -1; + } + env->DeleteLocalRef(item); + } + + buf[0] = EVENT_TYPE_LIST; + buf[1] = copied; + buf[pos++] = '\n'; + return __android_log_security_bwrite(tag, buf, pos); +} + +static void readEvents(JNIEnv* env, int loggerMode, jlong startTime, jobject out) { + struct logger_list *logger_list; + if (startTime) { + logger_list = android_logger_list_alloc_time(loggerMode, + log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0); + } else { + logger_list = android_logger_list_alloc(loggerMode, 0, 0); + } + if (!logger_list) { + jniThrowIOException(env, errno); + return; + } + + if (!android_logger_open(logger_list, LOG_ID_SECURITY)) { + jniThrowIOException(env, errno); + android_logger_list_free(logger_list); + return; + } + + while (1) { + log_msg log_msg; + int ret = android_logger_list_read(logger_list, &log_msg); + + if (ret == 0) { + break; + } + if (ret < 0) { + if (ret == -EINTR) { + continue; + } + if (ret == -EINVAL) { + jniThrowException(env, "java/io/IOException", "Event too short"); + } else if (ret != -EAGAIN) { + jniThrowIOException(env, -ret); // Will throw on return + } + break; + } + + if (log_msg.id() != LOG_ID_SECURITY) { + continue; + } + + jsize len = ret; + jbyteArray array = env->NewByteArray(len); + if (array == NULL) { + break; + } + + jbyte *bytes = env->GetByteArrayElements(array, NULL); + memcpy(bytes, log_msg.buf, len); + env->ReleaseByteArrayElements(array, bytes, 0); + + jobject event = env->NewObject(gEventClass, gEventInitID, array); + if (event == NULL) { + break; + } + + env->CallBooleanMethod(out, gCollectionAddID, event); + env->DeleteLocalRef(event); + env->DeleteLocalRef(array); + } + + android_logger_list_close(logger_list); +} + +static void android_app_admin_SecurityLog_readEvents(JNIEnv* env, jobject /* clazz */, + jobject out) { + + if (out == NULL) { + jniThrowNullPointerException(env, NULL); + return; + } + readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, out); +} + +static void android_app_admin_SecurityLog_readEventsSince(JNIEnv* env, jobject /* clazz */, + jlong timestamp, + jobject out) { + + if (out == NULL) { + jniThrowNullPointerException(env, NULL); + return; + } + readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, timestamp, out); +} + +static void android_app_admin_SecurityLog_readPreviousEvents(JNIEnv* env, jobject /* clazz */, + jobject out) { + + if (out == NULL) { + jniThrowNullPointerException(env, NULL); + return; + } + readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_PSTORE, 0, out); +} + +static void android_app_admin_SecurityLog_readEventsOnWrapping(JNIEnv* env, jobject /* clazz */, + jlong timestamp, + jobject out) { + if (out == NULL) { + jniThrowNullPointerException(env, NULL); + return; + } + readEvents(env, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK | ANDROID_LOG_WRAP, timestamp, out); +} + +/* + * JNI registration. + */ +static const JNINativeMethod gRegisterMethods[] = { + /* name, signature, funcPtr */ + { "isLoggingEnabled", + "()Z", + (void*) android_app_admin_SecurityLog_isLoggingEnabled + }, + { "writeEvent", + "(ILjava/lang/String;)I", + (void*) android_app_admin_SecurityLog_writeEvent_String + }, + { "writeEvent", + "(I[Ljava/lang/Object;)I", + (void*) android_app_admin_SecurityLog_writeEvent_Array + }, + { "readEvents", + "(Ljava/util/Collection;)V", + (void*) android_app_admin_SecurityLog_readEvents + }, + { "readEventsSince", + "(JLjava/util/Collection;)V", + (void*) android_app_admin_SecurityLog_readEventsSince + }, + { "readPreviousEvents", + "(Ljava/util/Collection;)V", + (void*) android_app_admin_SecurityLog_readPreviousEvents + }, + { "readEventsOnWrapping", + "(JLjava/util/Collection;)V", + (void*) android_app_admin_SecurityLog_readEventsOnWrapping + }, +}; + +static struct { const char *name; jclass *clazz; } gClasses[] = { + { "android/app/admin/SecurityLog$SecurityEvent", &gEventClass }, + { "java/lang/Integer", &gIntegerClass }, + { "java/lang/Long", &gLongClass }, + { "java/lang/Float", &gFloatClass }, + { "java/lang/String", &gStringClass }, + { "java/util/Collection", &gCollectionClass }, +}; + +static struct { jclass *c; const char *name, *ft; jfieldID *id; } gFields[] = { + { &gIntegerClass, "value", "I", &gIntegerValueID }, + { &gLongClass, "value", "J", &gLongValueID }, + { &gFloatClass, "value", "F", &gFloatValueID }, +}; + +static struct { jclass *c; const char *name, *mt; jmethodID *id; } gMethods[] = { + { &gEventClass, "<init>", "([B)V", &gEventInitID }, + { &gCollectionClass, "add", "(Ljava/lang/Object;)Z", &gCollectionAddID }, +}; + +int register_android_app_admin_SecurityLog(JNIEnv* env) { + for (int i = 0; i < NELEM(gClasses); ++i) { + jclass clazz = FindClassOrDie(env, gClasses[i].name); + *gClasses[i].clazz = MakeGlobalRefOrDie(env, clazz); + } + + for (int i = 0; i < NELEM(gFields); ++i) { + *gFields[i].id = GetFieldIDOrDie(env, + *gFields[i].c, gFields[i].name, gFields[i].ft); + } + + for (int i = 0; i < NELEM(gMethods); ++i) { + *gMethods[i].id = GetMethodIDOrDie(env, + *gMethods[i].c, gMethods[i].name, gMethods[i].mt); + } + + return RegisterMethodsOrDie( + env, + "android/app/admin/SecurityLog", + gRegisterMethods, NELEM(gRegisterMethods)); +} + +}; // namespace android diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp index 7314fbcd92d2..e17de17e06cc 100644 --- a/core/jni/android_graphics_drawable_VectorDrawable.cpp +++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp @@ -78,11 +78,11 @@ static jlong createFullPath(JNIEnv*, jobject, jlong srcFullPathPtr) { static void updateFullPathPropertiesAndStrokeStyles(JNIEnv*, jobject, jlong fullPathPtr, jfloat strokeWidth, jint strokeColor, jfloat strokeAlpha, jint fillColor, jfloat fillAlpha, jfloat trimPathStart, jfloat trimPathEnd, jfloat trimPathOffset, jfloat strokeMiterLimit, - jint strokeLineCap, jint strokeLineJoin) { + jint strokeLineCap, jint strokeLineJoin, jint fillType) { VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(fullPathPtr); fullPath->updateProperties(strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset, strokeMiterLimit, strokeLineCap, - strokeLineJoin); + strokeLineJoin, fillType); } static void updateFullPathFillGradient(JNIEnv*, jobject, jlong pathPtr, jlong fillGradientPtr) { @@ -331,7 +331,7 @@ static const JNINativeMethod gMethods[] = { {"nDraw", "(JJJLandroid/graphics/Rect;ZZ)V", (void*)draw}, {"nCreateFullPath", "!()J", (void*)createEmptyFullPath}, {"nCreateFullPath", "!(J)J", (void*)createFullPath}, - {"nUpdateFullPathProperties", "!(JFIFIFFFFFII)V", (void*)updateFullPathPropertiesAndStrokeStyles}, + {"nUpdateFullPathProperties", "!(JFIFIFFFFFIII)V", (void*)updateFullPathPropertiesAndStrokeStyles}, {"nUpdateFullPathFillGradient", "!(JJ)V", (void*)updateFullPathFillGradient}, {"nUpdateFullPathStrokeGradient", "!(JJ)V", (void*)updateFullPathStrokeGradient}, {"nGetFullPathProperties", "(J[BI)Z", (void*)getFullPathProperties}, diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp new file mode 100644 index 000000000000..87247292a73b --- /dev/null +++ b/core/jni/android_hardware_location_ContextHubService.cpp @@ -0,0 +1,344 @@ +/* + * Copyright 2016, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "context_hub.h" + +#include <string.h> +#include <stdint.h> +#include <stdio.h> + +#include <jni.h> +#include "JNIHelp.h" +#include "core_jni_helpers.h" +#include "stdint.h" +#include "stdlib.h" + + +namespace android { + +namespace { + +// TODO: We should share this array_length function widely around Android +// code. +/* + * Finds the length of a statically-sized array using template trickery that + * also prevents it from being applied to the wrong type. + */ +template <typename T, size_t N> +constexpr size_t array_length(T (&)[N]) { return N; } + +struct jniInfo_s { + JavaVM *vm; + jclass contextHubInfoClass; + jclass contextHubServiceClass; + jclass memoryRegionsClass; + + jobject jContextHubService; + + jmethodID msgReceiptCallBack; + + jmethodID contextHubInfoCtor; + jmethodID contextHubInfoSetId; + jmethodID contextHubInfoSetName; + jmethodID contextHubInfoSetVendor; + jmethodID contextHubInfoSetToolchain; + jmethodID contextHubInfoSetPlatformVersion; + jmethodID contextHubInfoSetStaticSwVersion; + jmethodID contextHubInfoSetToolchainVersion; + jmethodID contextHubInfoSetPeakMips; + jmethodID contextHubInfoSetStoppedPowerDrawMw; + jmethodID contextHubInfoSetSleepPowerDrawMw; + jmethodID contextHubInfoSetPeakPowerDrawMw; + jmethodID contextHubInfoSetSupportedSensors; + jmethodID contextHubInfoSetMemoryRegions; + + jmethodID contextHubServiceMsgReceiptCallback; +}; + +struct context_hub_info_s { + int cookie; + int numHubs; + const struct context_hub_t *hubs; + struct context_hub_module_t *contextHubModule; +}; + +struct contextHubServiceDb_s { + int initialized; + context_hub_info_s hubInfo; + jniInfo_s jniInfo; +}; + +} // unnamed namespace + +static contextHubServiceDb_s db; + +int context_hub_callback(uint32_t hub_id, const struct hub_message_t *msg, + void *cookie); + +static void initContextHubService() { + int err = 0; + db.hubInfo.hubs = NULL; + db.hubInfo.numHubs = 0; + db.hubInfo.cookie = 0; + int i; + + err = hw_get_module(CONTEXT_HUB_MODULE_ID, + (hw_module_t const**)(&db.hubInfo.contextHubModule)); + + if (err) { + ALOGE("** Could not load %s module : err %s", CONTEXT_HUB_MODULE_ID, + strerror(-err)); + } + + if (db.hubInfo.contextHubModule) { + ALOGD("Fetching hub info"); + db.hubInfo.numHubs = db.hubInfo.contextHubModule->get_hubs(db.hubInfo.contextHubModule, + &db.hubInfo.hubs); + + if (db.hubInfo.numHubs > 0) { + for (i = 0; i < db.hubInfo.numHubs; i++) { + // TODO : Event though one cookie is OK for now, lets change + // this to be one per hub + db.hubInfo.contextHubModule->subscribe_messages(db.hubInfo.hubs[i].hub_id, + context_hub_callback, + &db.hubInfo.cookie); + } + } + } +} + +static int onMessageReceipt(int *header, int headerLen, char *msg, int msgLen) { + JNIEnv *env; + if ((db.jniInfo.vm)->AttachCurrentThread(&env, NULL) != JNI_OK) { + return -1; + } + + jbyteArray jmsg = env->NewByteArray(msgLen); + jintArray jheader = env->NewIntArray(headerLen); + + env->SetByteArrayRegion(jmsg, 0, msgLen, (jbyte *)msg); + env->SetIntArrayRegion(jheader, 0, headerLen, (jint *)header); + + + return env->CallIntMethod(db.jniInfo.jContextHubService, + db.jniInfo.contextHubServiceMsgReceiptCallback, + jheader, jmsg); +} + +int context_hub_callback(uint32_t hub_id, const struct hub_message_t *msg, + void *cookie) { + int msgHeader[4]; + + msgHeader[0] = msg->message_type; + msgHeader[1] = 0; // TODO : HAL does not have a version field + msgHeader[2] = hub_id; + + onMessageReceipt(msgHeader, sizeof(msgHeader), (char *)msg->message, msg->message_len); // TODO : Populate this + return 0; +} + +static int init_jni(JNIEnv *env, jobject instance) { + + if (env->GetJavaVM(&db.jniInfo.vm) != JNI_OK) { + return -1; + } + + db.jniInfo.jContextHubService = env->NewGlobalRef(instance); + + db.jniInfo.contextHubInfoClass = + env->FindClass("android/hardware/location/ContextHubInfo"); + + db.jniInfo.contextHubServiceClass = + env->FindClass("android/hardware/location/ContextHubService"); + + db.jniInfo.memoryRegionsClass = + env->FindClass("android/hardware/location/MemoryRegion"); + + //TODO :: Add error checking + db.jniInfo.contextHubInfoCtor = + env->GetMethodID(db.jniInfo.contextHubInfoClass, "<init>", "()V"); + db.jniInfo.contextHubInfoSetId = + env->GetMethodID(db.jniInfo.contextHubInfoClass, "setId", "(I)V"); + db.jniInfo.contextHubInfoSetName = + env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName", + "(Ljava/lang/String;)V"); + + db.jniInfo.contextHubInfoSetVendor = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setVendor", "(Ljava/lang/String;)V"); + db.jniInfo.contextHubInfoSetToolchain = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setToolchain", "(Ljava/lang/String;)V"); + db.jniInfo.contextHubInfoSetPlatformVersion = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setPlatformVersion", "(I)V"); + db.jniInfo.contextHubInfoSetStaticSwVersion = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setStaticSwVersion", "(I)V"); + db.jniInfo.contextHubInfoSetToolchainVersion = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setToolchainVersion", "(I)V"); + db.jniInfo.contextHubInfoSetPeakMips = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setPeakMips", "(F)V"); + db.jniInfo.contextHubInfoSetStoppedPowerDrawMw = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setStoppedPowerDrawMw", "(F)V"); + db.jniInfo.contextHubInfoSetSleepPowerDrawMw = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setSleepPowerDrawMw", "(F)V"); + db.jniInfo.contextHubInfoSetPeakPowerDrawMw = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setPeakPowerDrawMw", "(F)V"); + db.jniInfo.contextHubInfoSetSupportedSensors = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setSupportedSensors", "([I)V"); + db.jniInfo.contextHubInfoSetMemoryRegions = + env->GetMethodID(db.jniInfo.contextHubInfoClass, + "setMemoryRegions", "([Landroid/hardware/location/MemoryRegion;)V"); + + + db.jniInfo.contextHubServiceMsgReceiptCallback = + env->GetMethodID(db.jniInfo.contextHubServiceClass, "onMessageReceipt", + "([I[B)I"); + db.jniInfo.contextHubInfoSetName = + env->GetMethodID(db.jniInfo.contextHubInfoClass, "setName", + "(Ljava/lang/String;)V"); + + + return 0; +} + +static jobject constructJContextHubInfo(JNIEnv *env, const struct context_hub_t *hub) { + jstring jstrBuf; + jintArray jintBuf; + jobjectArray jmemBuf; + + int dummyConnectedSensors[] = {1, 2, 3, 4, 5}; + + jobject jHub = env->NewObject(db.jniInfo.contextHubInfoClass, + db.jniInfo.contextHubInfoCtor); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetId, hub->hub_id); + + jstrBuf = env->NewStringUTF(hub->name); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetName, jstrBuf); + + jstrBuf = env->NewStringUTF(hub->vendor); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetVendor, jstrBuf); + + jstrBuf = env->NewStringUTF(hub->toolchain); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchain, jstrBuf); + + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPlatformVersion, hub->platform_version); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetToolchainVersion, hub->toolchain_version); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakMips, hub->peak_mips); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetStoppedPowerDrawMw, hub->stopped_power_draw_mw); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetSleepPowerDrawMw, hub->sleep_power_draw_mw); + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetPeakPowerDrawMw, hub->peak_power_draw_mw); + + // TODO : jintBuf = env->NewIntArray(hub->num_connected_sensors); + // TODO : env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, hub->connected_sensors); + jintBuf = env->NewIntArray(array_length(dummyConnectedSensors)); + env->SetIntArrayRegion(jintBuf, 0, hub->num_connected_sensors, dummyConnectedSensors); + + // We are not getting the memory regions from the CH Hal - change this when it is available + jmemBuf = env->NewObjectArray(0, db.jniInfo.memoryRegionsClass, NULL); + // Note the zero size above. We do not need to set any elements + env->CallVoidMethod(jHub, db.jniInfo.contextHubInfoSetMemoryRegions, jmemBuf); + + return jHub; +} + +static jobjectArray nativeInitialize(JNIEnv *env, jobject instance) +{ + jobject hub; + jobjectArray retArray; + + initContextHubService(); + + if (init_jni(env, instance) < 0) { + return NULL; + } + + // Note : The service is clamping the number of hubs to 1 + db.hubInfo.numHubs = 1; + + initContextHubService(); + + retArray = env->NewObjectArray(db.hubInfo.numHubs, db.jniInfo.contextHubInfoClass, NULL); + + for(int i = 0; i < db.hubInfo.numHubs; i++) { + hub = constructJContextHubInfo(env, &db.hubInfo.hubs[i]); + env->SetObjectArrayElement(retArray, i, hub); + } + + return retArray; +} + +static jint nativeSendMessage(JNIEnv *env, jobject instance, jintArray header_, + jbyteArray data_) { + hub_message_t msg; + hub_app_name_t dest; + uint8_t os_name[8]; + + memset(os_name, 0, sizeof(os_name)); + + jint *header = env->GetIntArrayElements(header_, 0); + //int numHeaderElements = env->GetArrayLength(header_); + jbyte *data = env->GetByteArrayElements(data_, 0); + int dataBufferLength = env->GetArrayLength(data_); + + /* Assume an int - thats all we understand */ + dest.app_name_len = array_length(os_name); // TODO : Check this + //dest.app_name = &header[1]; + dest.app_name = os_name; + + msg.app = &dest; + + msg.message_type = header[3]; + msg.message_len = dataBufferLength; + msg.message = data; + + jint retVal = db.hubInfo.contextHubModule->send_message(header[0], &msg); + + env->ReleaseIntArrayElements(header_, header, 0); + env->ReleaseByteArrayElements(data_, data, 0); + + return retVal; +} + +//-------------------------------------------------------------------------------------------------- +// +static const JNINativeMethod gContextHubServiceMethods[] = { + {"nativeInitialize", + "()[Landroid/hardware/location/ContextHubInfo;", + (void*)nativeInitialize }, + {"nativeSendMessage", + "([I[B)I", + (void*)nativeSendMessage } +}; + +}//namespace android + +using namespace android; + +int register_android_hardware_location_ContextHubService(JNIEnv *env) +{ + RegisterMethodsOrDie(env, "android/hardware/location/ContextHubService", + gContextHubServiceMethods, NELEM(gContextHubServiceMethods)); + + return 0; +} diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index 3e4e3522d5dd..1bc4285a23d7 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -200,7 +200,7 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, ALOGE("Error creating AudioRecord: Error retrieving session id pointer"); return (jint) AUDIO_JAVA_ERROR; } - int sessionId = nSession[0]; + audio_session_t sessionId = (audio_session_t) nSession[0]; env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; @@ -385,7 +385,7 @@ android_media_AudioRecord_start(JNIEnv *env, jobject thiz, jint event, jint trig } return nativeToJavaStatus( - lpRecorder->start((AudioSystem::sync_event_t)event, triggerSession)); + lpRecorder->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession)); } diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 1eb011100919..7496124969fe 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -109,7 +109,8 @@ static struct { jfieldID mRule; jfieldID mFormat; jfieldID mRouteFlags; - jfieldID mRegistrationId; + jfieldID mDeviceType; + jfieldID mDeviceAddress; jfieldID mMixType; jfieldID mCallbackFlags; } gAudioMixFields; @@ -388,7 +389,7 @@ android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val) } static void -android_media_AudioSystem_recording_callback(int event, int session, int source, +android_media_AudioSystem_recording_callback(int event, audio_session_t session, int source, const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) { @@ -1539,7 +1540,7 @@ android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz) static jint android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId) { - return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId); + return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId); } static void @@ -1561,13 +1562,15 @@ static jint convertAudioMixToNative(JNIEnv *env, { nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType); nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags); + nAudioMix->mDeviceType = (audio_devices_t) + env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType); - jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix, - gAudioMixFields.mRegistrationId); - const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL); - nAudioMix->mRegistrationId = String8(nRegistrationId); - env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId); - env->DeleteLocalRef(jRegistrationId); + jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix, + gAudioMixFields.mDeviceAddress); + const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL); + nAudioMix->mDeviceAddress = String8(nDeviceAddress); + env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress); + env->DeleteLocalRef(jDeviceAddress); nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags); @@ -1857,7 +1860,8 @@ int register_android_media_AudioSystem(JNIEnv *env) gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat", "Landroid/media/AudioFormat;"); gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I"); - gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId", + gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I"); + gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress", "Ljava/lang/String;"); gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I"); gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I"); diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp index 302cf639f4d9..024c21de4a50 100644 --- a/core/jni/android_media_AudioTrack.cpp +++ b/core/jni/android_media_AudioTrack.cpp @@ -235,7 +235,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job ALOGE("Error creating AudioTrack: Error retrieving session id pointer"); return (jint) AUDIO_JAVA_ERROR; } - int sessionId = nSession[0]; + audio_session_t sessionId = (audio_session_t) nSession[0]; env->ReleasePrimitiveArrayCritical(jSession, nSession, 0); nSession = NULL; diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index a9003c1888d2..a7ac5b8aae66 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -28,6 +28,7 @@ #include <DamageAccumulator.h> #include <Matrix.h> #include <RenderNode.h> +#include <renderthread/CanvasContext.h> #include <TreeInfo.h> #include <Paint.h> @@ -487,15 +488,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override { if (CC_UNLIKELY(!mWeakRef || !info.updateWindowPositions)) return; - ATRACE_NAME("Update SurfaceView position"); - JNIEnv* env = jnienv(); - jobject localref = env->NewLocalRef(mWeakRef); - if (CC_UNLIKELY(!localref)) { - jnienv()->DeleteWeakGlobalRef(mWeakRef); - mWeakRef = nullptr; - return; - } Matrix4 transform; info.damageAccumulator->computeCurrentTransform(&transform); const RenderProperties& props = node.properties(); @@ -505,10 +498,13 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, bounds.right -= info.windowInsetLeft; bounds.top -= info.windowInsetTop; bounds.bottom -= info.windowInsetTop; - env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod, - (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top, - (jint) bounds.right, (jint) bounds.bottom); - env->DeleteLocalRef(localref); + + auto functor = std::bind( + std::mem_fn(&SurfaceViewPositionUpdater::doUpdatePosition), this, + (jlong) info.frameNumber, (jint) bounds.left, (jint) bounds.top, + (jint) bounds.right, (jint) bounds.bottom); + + info.canvasContext.enqueueFrameWork(std::move(functor)); } private: @@ -520,6 +516,23 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject, return env; } + void doUpdatePosition(jlong frameNumber, jint left, jint top, + jint right, jint bottom) { + ATRACE_NAME("Update SurfaceView position"); + + JNIEnv* env = jnienv(); + jobject localref = env->NewLocalRef(mWeakRef); + if (CC_UNLIKELY(!localref)) { + jnienv()->DeleteWeakGlobalRef(mWeakRef); + mWeakRef = nullptr; + return; + } + + env->CallVoidMethod(localref, gSurfaceViewPositionUpdateMethod, + frameNumber, left, top, right, bottom); + env->DeleteLocalRef(localref); + } + JavaVM* mVm; jobject mWeakRef; }; diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index b7701d6d7531..14252dc6bb72 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -144,7 +144,7 @@ android_dataspace android_view_Surface_mapPublicFormatToHalDataspace( PublicFormat f) { switch(f) { case PublicFormat::JPEG: - return HAL_DATASPACE_JFIF; + return HAL_DATASPACE_V0_JFIF; case PublicFormat::DEPTH_POINT_CLOUD: case PublicFormat::DEPTH16: return HAL_DATASPACE_DEPTH; @@ -156,7 +156,7 @@ android_dataspace android_view_Surface_mapPublicFormatToHalDataspace( case PublicFormat::YUV_420_888: case PublicFormat::NV21: case PublicFormat::YV12: - return HAL_DATASPACE_JFIF; + return HAL_DATASPACE_V0_JFIF; default: // Most formats map to UNKNOWN return HAL_DATASPACE_UNKNOWN; @@ -210,7 +210,7 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat( switch (dataSpace) { case HAL_DATASPACE_DEPTH: return PublicFormat::DEPTH_POINT_CLOUD; - case HAL_DATASPACE_JFIF: + case HAL_DATASPACE_V0_JFIF: return PublicFormat::JPEG; default: // Assume otherwise-marked blobs are also JPEG diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index fbc96c262cfc..6444c6c94dc4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1483,11 +1483,21 @@ <!-- Allows an application to manage access to documents, usually as part of a document picker. + <p>This permission should <em>only</em> be requested by the platform + document management app. This permission cannot be granted to + third-party apps. <p>Protection level: signature --> <permission android:name="android.permission.MANAGE_DOCUMENTS" android:protectionLevel="signature" /> + <!-- @hide Allows an application to cache content. + <p>Not for use by third-party applications. + <p>Protection level: signature + --> + <permission android:name="android.permission.CACHE_CONTENT" + android:protectionLevel="signature" /> + <!-- ================================== --> <!-- Permissions for screenlock --> <!-- ================================== --> diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml index 6f3c4d4200f9..c96e2809d8a9 100644 --- a/core/res/res/anim/lock_screen_behind_enter.xml +++ b/core/res/res/anim/lock_screen_behind_enter.xml @@ -16,7 +16,6 @@ --> <set xmlns:android="http://schemas.android.com/apk/res/android" - android:background="#ff000000" android:detachWallpaper="true" android:shareInterpolator="false" android:startOffset="100"> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index de4ccaeec8ec..dfdb6b0bb2c8 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Werkmodus is AF"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Stel werkprofiel in staat om te werk, insluitend programme, agtergrondsinkronisering en verwante kenmerke."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Skakel aan"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Deur %1$s gedeaktiveer"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Deur %1$s-administrateur gedeaktiveer. Kontak hulle om meer uit te vind."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Jy het nuwe boodskappe"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Maak SMS-program oop om te bekyk"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Sommige funksies kan beperk wees"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Ontspeld"</string> <string name="app_info" msgid="6856026610594615344">"Programinligting"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Voer \'n fabriekterugstelling uit om hierdie toestel normaal te gebruik"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Raak om meer te wete te kom."</string> </resources> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 88e9367ba5cf..50f5f766ee33 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"የሥራ ሁነታ ጠፍቷል"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"መተግበሪያዎችን፣ የበስተጀርባ ሥምረት እና ተዛማጅ ባሕሪዎችን ጨምሮ የሥራ መገለጫ እንዲሰራ ይፍቀዱ።"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"አብራ"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ተሰናክሏል"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"በ%1$s አስተዳዳሪ ተሰናክሏል። የበለጠ ለመረዳት ያነጋግሯቸው።"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"አዲስ መልእክቶች አለዎት"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"ለመመልከት የኤስኤምኤስ መተግበሪያ ይክፈቱ"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"አንዳንድ ተግባሮች የተገደቡ ሊሆኑ ይችላሉ"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"ንቀል"</string> <string name="app_info" msgid="6856026610594615344">"የመተግበሪያ መረጃ"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"ይህን መሣሪያ በመደበኛነት ለመጠቀም የፋብሪካ ዳግም ያስጀምሩ"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"የበለጠ ለመረዳት ይንኩ።"</string> </resources> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 84bc7683b45b..fcde6912eff0 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1625,8 +1625,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"وضع العمل معطَّل"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"السماح باستخدام الملف الشخصي للعمل، بما في ذلك التطبيقات ومزامنة الخلفية والميزات ذات الصلة."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"تشغيل"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"تم تعطيل %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"تم التعطيل بواسطة مشرف %1$s. يمكنك الاتصال به لمعرفة المزيد."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"لديك رسائل جديدة"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"فتح تطبيق الرسائل القصيرة SMS للعرض"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ربما تكون بعض الوظائف مُقيّدة."</string> @@ -1640,6 +1638,7 @@ <string name="unpin_target" msgid="3556545602439143442">"إزالة تثبيت"</string> <string name="app_info" msgid="6856026610594615344">"معلومات عن التطبيق"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"يمكنك إعادة تعيين إعدادات المصنع لاستخدام هذا الجهاز بشكل عادي"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"المس للتعرف على مزيد من المعلومات."</string> </resources> diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml index 3c4ce89e5988..3bc0ec36608d 100644 --- a/core/res/res/values-az-rAZ/strings.xml +++ b/core/res/res/values-az-rAZ/strings.xml @@ -1051,12 +1051,12 @@ <string name="usb_notification_message" msgid="7347368030849048437">"Əlavə seçimlər üçün toxunun."</string> <string name="adb_active_notification_title" msgid="6729044778949189918">"USB sazlama qoşuludur"</string> <string name="adb_active_notification_message" msgid="1016654627626476142">"USB debaqı deaktivasiya etmək üçün toxunun."</string> - <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Baq hesabat verilir..."</string> + <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Baq hesabatı verilir..."</string> <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Baq hesabatı paylaşılsın?"</string> <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Baq hesabatı paylaşılır..."</string> - <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"IT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla bilər."</string> + <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"İT admininiz bu cihazda nasazlıqların aşkarlanması üçün baq hesabatı sorğusu göndərdi. Tətbiqlər və data paylaşıla bilər."</string> <string name="share_remote_bugreport_action" msgid="6249476773913384948">"PAYLAŞIN"</string> - <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RƏDD ET"</string> + <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RƏDD EDİN"</string> <string name="select_input_method" msgid="8547250819326693584">"Klaviaturanı dəyişin"</string> <string name="configure_input_methods" msgid="4769971288371946846">"Klaviaturaları seçin"</string> <string name="show_ime" msgid="2506087537466597099">"Fiziki klaviatura aktiv olduğu halda ekranda saxlayın"</string> @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"İş rejimi DEAKTİVDİR"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Tətbiq, arxa fon sinxronizasiyası və digər əlaqədar xüsusiyyətlər daxil olmaqla iş profilinin fəaliyyətinə icazə verin."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivləşdirin"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dekativ edildi"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s administratoru tərəfindən deaktiv edildi. Ətraflı məlumat üçün onlarla əlaqə saxlayın."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Yeni mesajlarınız var"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Baxmaq üçün SMS tətbiqini açın"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Bir neçə funksionallıq məhdudlaşdırıla bilər"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Çıxarın"</string> <string name="app_info" msgid="6856026610594615344">"Tətbiq məlumatı"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Cihazı normal istifadə etmək üçün fabrik sıfırlaması"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha çox məlumat üçün toxunun."</string> </resources> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 5c73fafe6fed..be40fa85d663 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -1568,8 +1568,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Režim za Work je ISKLJUČEN"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Dozvoljava profilu za Work da funkcioniše, uključujući aplikacije, sinhronizaciju u pozadini i srodne funkcije."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Paket %1$s je onemogućen"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio je administrator kompanije %1$s. Kontaktirajte ga da biste saznali više."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite aplikaciju za SMS da biste pregledali"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Neke funkcije su možda ograničene"</string> @@ -1583,6 +1581,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Otkači"</string> <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Resetujte uređaj na fabrička podešavanja da biste ga normalno koristili"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string> </resources> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index b2633a9f683a..40e9572c02b9 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Работният режим е ИЗКЛЮЧЕН"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Разрешаване на функционирането на служебния потребителски профил, включително приложенията, синхронизирането на заден план и свързаните функции."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Включване"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Пакетът „%1$s“ е деактивиран"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Деактивирано от администратора на %1$s. Свържете се с него, за да научите повече."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нови съобщения"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Преглед в приложението за SMS"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Някои функции може да са огранич."</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Освобождаване"</string> <string name="app_info" msgid="6856026610594615344">"Информация за приложението"</string> <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Възстановете фабричните настройки, за да използвате това устройство нормално"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Докоснете, за да научите повече."</string> </resources> diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml index 2042c4c2b830..92bd3e7d82d1 100644 --- a/core/res/res/values-bn-rBD/strings.xml +++ b/core/res/res/values-bn-rBD/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"কাজের মোড বন্ধ আছে"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"অ্যাপ্লিকেশান, পটভূমি সিঙ্ক এবং সম্পর্কিত বৈশিষ্ট্যগুলি সহ কর্মস্থলের প্রোফাইলটিকে কাজ করার মঞ্জুরি দিন।"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"চালু করুন"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s অক্ষম করা আছে"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s প্রশাসক অক্ষম করেছেন। আরো জানতে তাদের সাথে যোগাযোগ করুন।"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"আপনার নতুন বার্তা আছে"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"দেখার জন্য SMS অ্যাপ্লিকেশান খুলুন"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"কিছু ক্রিয়াকলাপ সীমিত হতে পারে"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"আনপিন করুন"</string> <string name="app_info" msgid="6856026610594615344">"অ্যাপ্লিকেশানের তথ্য"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"এই ডিভাইসটিকে স্বাভাবিকভাবে ব্যবহার করতে ফ্যাক্টরি পুনরায় সেট করুন"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"আরো জানতে স্পর্শ করুন৷"</string> </resources> diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml index f352620b23b4..ca7a80aed734 100644 --- a/core/res/res/values-bs-rBA/strings.xml +++ b/core/res/res/values-bs-rBA/strings.xml @@ -1568,8 +1568,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Radni način rada je ISKLJUČEN"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Omogući radnom profilu da funkcionira, uključujući aplikacije, sinhronizaciju u pozadini i povezane funkcije."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogućeno"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio administrator (%1$s). Obratite mu se za više informacija."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Neke funkcije mogu biti ograničene"</string> @@ -1583,6 +1581,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Otkači"</string> <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Vratite na fabričke postavke kako biste mogli normalno koristiti ovaj uređaj"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da saznate više."</string> </resources> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 54828960573e..a73741204300 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Mode de feina desactivat"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Permet que el perfil professional funcioni, incloses les aplicacions, la sincronització en segon pla i les funcions relacionades."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Activa"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Aplicació %1$s desactivada"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"L\'administrador de l\'empresa %1$s ha desactivat el paquet. Contacta-hi per obtenir-ne més informació."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Tens missatges nous"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Obre l\'aplicació de SMS per veure\'ls"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Algunes funcions es limitaran"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"No fixis"</string> <string name="app_info" msgid="6856026610594615344">"Informació de l\'aplicació"</string> <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Restableix les dades de fàbrica del dispositiu per utilitzar-lo amb normalitat"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca per obtenir més informació."</string> </resources> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 390dfd063eac..5b6a213b5101 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1587,8 +1587,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Pracovní režim je VYPNUTÝ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Povolí fungování pracovního profilu, včetně aplikací, synchronizace na pozadí a souvisejících funkcí."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Zapnout"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Balíček %1$s byl zakázán"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Zakázáno administrátorem zařízení %1$s. Chcete-li získat další informace, kontaktujte jej."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Máte nové zprávy"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Zobrazíte je v aplikaci pro SMS"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Funkce mohou být omezeny"</string> @@ -1602,6 +1600,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Odepnout"</string> <string name="app_info" msgid="6856026610594615344">"Informace o aplikaci"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Chcete-li toto zařízení normálně používat, obnovte jej do továrního nastavení"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím zobrazíte další informace."</string> </resources> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 583a6b70603c..06861e7568de 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Arbejdstilstand er slået FRA"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Tillad, at arbejdsprofilen aktiveres, bl.a. i forbindelse med apps, baggrundssynkronisering og relaterede funktioner."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Slå til"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s er deaktiveret"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Deaktiveret af %1$s administrator. Kontakt vedkommende for at få flere oplysninger."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nye beskeder"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Åbn sms-appen for at se beskeden"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Nogle funktioner er begrænsede"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Frigør"</string> <string name="app_info" msgid="6856026610594615344">"Oplysninger om appen"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Nulstil enheden til fabriksindstillingerne for at bruge den på normal vis"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryk for at få flere oplysninger."</string> </resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index b67402aac27b..30188b52beb5 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Arbeitsmodus ist AUS"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Arbeitsprofil aktivieren, einschließlich Apps, Synchronisierung im Hintergrund und verknüpfter Funktionen."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivieren"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s deaktiviert"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Durch den Administrator von %1$s deaktiviert. Setze dich für weitere Informationen mit ihm in Verbindung."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Du hast neue Nachrichten"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Zum Ansehen SMS-App öffnen"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Einige Funktionen sind evtl. eingeschränkt"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Markierung entfernen"</string> <string name="app_info" msgid="6856026610594615344">"App-Informationen"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Gerät zur normalen Verwendung auf Werkseinstellungen zurücksetzen"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Für weitere Informationen tippen."</string> </resources> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 845018982dbd..10914950d81a 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Λειτουργία εργασίας ΑΠΕΝΕΡΓ/ΝΗ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Να επιτρέπεται η λειτουργία του προφίλ εργασίας σας, συμπεριλαμβανομένων των εφαρμογών, του συγχρονισμού στο παρασκήνιο και των σχετικών λειτουργιών."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Ενεργοποίηση"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Το %1$s απενεργοποιήθηκε"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Απενεργοποιήθηκε από το διαχειριστή της συσκευής %1$s. Επικοινωνήστε με το διαχειριστή για να μάθετε περισσότερα."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Έχετε νέα μηνύματα"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Άνοιγμα της εφαρμογής SMS για προβολή"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Μερ. λειτ. ίσως είναι περιορ."</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Ξεκαρφίτσωμα"</string> <string name="app_info" msgid="6856026610594615344">"Πληροφορίες εφαρμογής"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Επαναφέρετε τις εργοστασιακές ρυθμίσεις για να χρησιμοποιήσετε αυτήν τη συσκευή κανονικά"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Αγγίξτε για να μάθετε περισσότερα."</string> </resources> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index ac7ad91522ed..58d45baae6eb 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string> <string name="app_info" msgid="6856026610594615344">"App info"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Restore this device to factory settings to use normally"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string> </resources> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index ac7ad91522ed..58d45baae6eb 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string> <string name="app_info" msgid="6856026610594615344">"App info"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Restore this device to factory settings to use normally"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string> </resources> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index ac7ad91522ed..58d45baae6eb 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Work mode is OFF"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Allow work profile to function, including apps, background sync and related features."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Turn on"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disabled"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Disabled by %1$s administrator. Contact them to find out more."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"You have new messages"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Open SMS app to view"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Some functionality may be limited"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string> <string name="app_info" msgid="6856026610594615344">"App info"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Restore this device to factory settings to use normally"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touch to find out more."</string> </resources> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 4623d77a00ee..225116fb44dd 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabajo DESACTIVADO"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que se active el perfil de trabajo, incluidas las apps, la sincronización en segundo plano y las funciones relacionadas."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Se inhabilitó %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"El administrador de %1$s lo inhabilitó. Comunícate con él para obtener más información."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Tienes mensajes nuevos"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Abrir app de SMS para ver el mensaje"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Funciones limitadas"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"No fijar"</string> <string name="app_info" msgid="6856026610594615344">"Información de la app"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Restablece la configuración de fábrica para usar este dispositivo con normalidad"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string> </resources> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index d44c07eb63fc..5ce171172b97 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -909,8 +909,8 @@ <string name="noApplications" msgid="2991814273936504689">"Ninguna aplicación puede realizar esta acción."</string> <string name="aerr_application" msgid="250320989337856518">"La aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> ha dejado de funcionar"</string> <string name="aerr_process" msgid="6201597323218674729">"El proceso <xliff:g id="PROCESS">%1$s</xliff:g> ha dejado de funcionar"</string> - <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> sigue dejando de funcionar"</string> - <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> sigue dejando de funcionar"</string> + <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> sigue sin funcionar"</string> + <string name="aerr_process_repeated" msgid="6235302956890402259">"<xliff:g id="PROCESS">%1$s</xliff:g> sigue sin funcionar"</string> <string name="aerr_restart" msgid="9001379185665886595">"Reiniciar aplicación"</string> <string name="aerr_reset" msgid="7645427603514220451">"Restablecer y reiniciar aplicación"</string> <string name="aerr_report" msgid="5371800241488400617">"Enviar sugerencias"</string> @@ -1135,7 +1135,7 @@ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string> <string name="notification_listener_binding_label" msgid="2014162835481906429">"Detector de notificaciones"</string> - <string name="vr_listener_binding_label" msgid="4316591939343607306">"Procesador de Realidad Virtual"</string> + <string name="vr_listener_binding_label" msgid="4316591939343607306">"Procesador de RV"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string> <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servicio de clasificación de notificaciones"</string> <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string> @@ -1549,12 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabajo desactivado"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que se utilice el perfil de trabajo, incluidas las aplicaciones, la sincronización en segundo plano y las funciones relacionadas."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string> - <!-- String.format failed for translation --> - <!-- no translation found for suspended_package_title (3408150347778524435) --> - <skip /> - <!-- String.format failed for translation --> - <!-- no translation found for suspended_package_message (6341091587106868601) --> - <skip /> <string name="new_sms_notification_title" msgid="8442817549127555977">"Tienes mensajes nuevos"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Abre la aplicación de SMS para ver el mensaje"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Algunas funciones limitadas"</string> @@ -1568,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"No fijar"</string> <string name="app_info" msgid="6856026610594615344">"Información de la aplicación"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Restablece los datos de fábrica para utilizar este dispositivo con normalidad"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para obtener más información."</string> </resources> diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml index c35d222da2f9..3ce50d986816 100644 --- a/core/res/res/values-et-rEE/strings.xml +++ b/core/res/res/values-et-rEE/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Töörežiim on VÄLJA LÜLITATUD"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Lubatakse tööprofiili toimingud, sh rakendused, taustal sünkroonimine ja seotud funktsioonid."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Lülita sisse"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Üksus %1$s on keelatud"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Keelas seadme %1$s administraator. Lisateabe saamiseks võtke temaga ühendust."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Teile on uusi sõnumeid"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Avage vaatamiseks SMS-rakendus"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Funktsioon võib olla piiratud"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Vabasta"</string> <string name="app_info" msgid="6856026610594615344">"Rakenduse teave"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Seadme tavapäraseks kasutamiseks lähtestage see tehaseseadetele"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lisateabe saamiseks puudutage."</string> </resources> diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml index bb83a9e57db8..6c41c2c0538e 100644 --- a/core/res/res/values-eu-rES/strings.xml +++ b/core/res/res/values-eu-rES/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Desaktibatuta dago laneko modua"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Baimendu laneko profilak funtzionatzea, besteak beste, aplikazioak, atzeko planoko sinkronizazioa eta erlazionatutako eginbideak."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktibatu"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Desgaituta dago %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Desgaitu egin du %1$s gailuaren administratzaileak. Informazio gehiago lortu nahi baduzu, jarri harekin harremanetan."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Mezu berriak dituzu"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Mezuak ikusteko, ireki SMS mezuen aplikazioa"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Funtzioak mugatuta egon litezke"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Kendu aingura"</string> <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Berrezarri jatorrizko egoerara gailua ohi bezala erabiltzen jarraitu ahal izateko"</string> - <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ukitu informazio gehiago lortzeko."</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> + <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sakatu informazio gehiago lortzeko."</string> </resources> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index eeab6d35a3f4..aba5e08a6a93 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"حالت کاری خاموش است"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"به نمایه کاری اجازه فعالیت ( شامل استفاده از برنامهها، همگامسازی در پسزمینه و قابلیتهای مرتبط) داده شود."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"روشن کردن"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s غیرفعال است"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"سرپرست %1$s آن را غیرفعال کرده است. برای اطلاعات بیشتر با او تماس بگیرید."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"پیامهای جدیدی دارید"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"برای مشاهده، برنامه پیامک را باز کنید"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ممکن است برخی از عملکردها محدود باشند"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"برداشتن پین"</string> <string name="app_info" msgid="6856026610594615344">"اطلاعات برنامه"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"بازنشانی کارخانهای برای استفاده عادی از این دستگاه"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"برای یادگیری بیشتر لمس کنید."</string> </resources> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index d45e0bd60efe..e52d8707c6c2 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Työtila on pois käytöstä"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Sallii työprofiiliin toiminnan, esimerkiksi sovellukset ja taustasynkronoinnin."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Ota käyttöön"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s poisti tämän käytöstä"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Organisaation %1$s järjestelmänvalvojan käytöstä poistama. Kysy häneltä lisätietoja."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Sinulle on uusia viestejä"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Katso avaamalla tekstiviestisovellus."</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Toimintorajoitus mahdollinen"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Irrota"</string> <string name="app_info" msgid="6856026610594615344">"Sovelluksen tiedot"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Palauta tehdasasetukset, jotta voit käyttää laitetta tavallisesti"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Lue lisätietoja koskettamalla."</string> </resources> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 6fa6f4915f5b..acfd0a656572 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Le mode Travail est désactivé"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Autoriser le fonctionnement du profil professionnel, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Activer"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s est désactivé"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Cette option a été désactivée par l\'administrateur de %1$s. Communiquez avec lui pour en savoir plus."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Vous avez de nouveaux messages"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Ouvrez l\'application de messagerie texte pour l\'afficher"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Certaines fonct. sont limitées"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Annuler l\'épinglage"</string> <string name="app_info" msgid="6856026610594615344">"Détails de l\'application"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Rétablissez la configuration d\'usine pour utiliser cet appareil normalement"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Touchez ici pour en savoir plus."</string> </resources> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 02ad9e6a2d56..d3bb5d0405fa 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Mode professionnel DÉSACTIVÉ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Autoriser le fonctionnement du profil professionnel, y compris les applications, la synchronisation en arrière-plan et les fonctionnalités associées."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Activer"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s désactivé"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Désactivé par l\'administrateur %1$s. Contactez-le pour en savoir plus."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Vous avez de nouveaux messages"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Ouvrir l\'application de SMS pour afficher le message"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Des fonctionnalités peuvent être limitées"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Retirer"</string> <string name="app_info" msgid="6856026610594615344">"Infos sur l\'appli"</string> <string name="negative_duration" msgid="5688706061127375131">"− <xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Rétablir la configuration d\'usine pour utiliser cet appareil normalement"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Appuyez ici pour en savoir plus."</string> </resources> diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml index cb0ac76e4ee2..6a2b7f3454d2 100644 --- a/core/res/res/values-gl-rES/strings.xml +++ b/core/res/res/values-gl-rES/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de traballo DESACTIVADO"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Permite que funcione o perfil de traballo, incluídas as aplicacións, a sincronización en segundo plano e as funcións relacionadas."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Activar"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Desactivouse %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"O administrador de %1$s desactivou este paquete. Contacta con el para obter máis información."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Tes mensaxes novas"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Abre a aplicación de SMS para ver as mensaxes"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Pode haber funcións limitadas"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string> <string name="app_info" msgid="6856026610594615344">"Información da aplicación"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Restablecemento da configuración de fábrica para usar este dispositivo con normalidade"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toca para acceder a máis información"</string> </resources> diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml index 6270867d1e03..7595a88a8dfc 100644 --- a/core/res/res/values-gu-rIN/strings.xml +++ b/core/res/res/values-gu-rIN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"કાર્ય મોડ બંધ છે"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"કાર્ય પ્રોફાઇલને ઍપ્લિકેશનો, પૃષ્ઠભૂમિ સમન્વયન અને સંબંધિત સુવિધાઓ સહિતનું કાર્ય કરવાની મંજૂરી આપો."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ચાલુ કરો"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s અક્ષમ કરેલ"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ. વધુ જાણવા માટે તેમનો સંપર્ક કરો."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"તમારી પાસે નવા સંદેશા છે"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"જોવા માટે SMS ઍપ્લિકેશન ખોલો"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"કેટલીક કાર્યક્ષમતા મર્યાદિત હોઈ શકે છે"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"અનપિન કરો"</string> <string name="app_info" msgid="6856026610594615344">"ઍપ્લિકેશન માહિતી"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"આ ઉપકરણને સામાન્ય રીતે ઉપયોગ કરવા માટે ફેક્ટરી રીસેટ કરો"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"વધુ જાણવા માટે ટચ કરો."</string> </resources> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 82e1d83b1139..3c33b38a0af1 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बंद है"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"ऐप्स, पृष्ठभूमि समन्वयन और संबंधित सुविधाओं सहित कार्य प्रोफ़ाइल को काम करने की अनुमति दें"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"चालू करें"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s को अक्षम किया गया"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s व्यवस्थापक द्वारा अक्षम किया गया. अधिक जानने के लिए उनसे संपर्क करें."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"आपके पास नए संदेश हैं"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"देखने के लिए SMS ऐप खोलें"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"कुछ कार्य क्षमताएं सीमित हो सकती हैं"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"अनपिन करें"</string> <string name="app_info" msgid="6856026610594615344">"ऐप की जानकारी"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"इस डिवाइस का सामान्य रूप से उपयोग करने के लिए फ़ैक्टरी रीसेट करें"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जानने के लिए स्पर्श करें."</string> </resources> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index cd23a1af5075..862ee6050b93 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1568,8 +1568,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Radni je način ISKLJUČEN"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Omogućuje radnom profilu da funkcionira, uključujući aplikacije, sinkronizaciju u pozadini i povezane značajke."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Uključi"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogućeno"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Onemogućio administrator (%1$s). Obratite mu se za više informacija."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nove poruke"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorite SMS aplikaciju da biste pregledali poruke"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Funkcije mogu biti ograničene"</string> @@ -1583,6 +1581,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Otkvači"</string> <string name="app_info" msgid="6856026610594615344">"Informacije o aplikaciji"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Uređaj je vraćen na tvorničke postavke da biste ga mogli upotrebljavati na pravilan način"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dodirnite da biste saznali više."</string> </resources> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index ffa8d214543d..d6114fa58fe7 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"A munka mód KI van kapcsolva"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Munkaprofil használatának engedélyezése, beleértve az alkalmazásokat, a háttérben való szinkronizálást és a kapcsolódó funkciókat."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Bekapcsolás"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s letiltva"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"A(z) %1$s szervezet rendszergazdája letiltotta. További információért vegye fel vele a kapcsolatot."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Új üzenetei érkeztek"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"SMS-alkalmazás megnyitása a megtekintéshez"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Egyes funkciók korlátozva lehetnek"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Feloldás"</string> <string name="app_info" msgid="6856026610594615344">"Alkalmazásinformáció"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Gyári beállítások visszaállítása az eszköz normál módú használatához"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Érintse meg a további információkért."</string> </resources> diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml index 909a5c9b7c86..0b2fe576cb43 100644 --- a/core/res/res/values-hy-rAM/strings.xml +++ b/core/res/res/values-hy-rAM/strings.xml @@ -1137,7 +1137,7 @@ <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ծանուցման ունկնդիր"</string> <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ունկնդրիչ"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Պայմանների մատակարար"</string> - <string name="notification_ranker_binding_label" msgid="774540592299064747">"Ըստ կարևորության ծանուցումների դասակարգման ծառայություն"</string> + <string name="notification_ranker_binding_label" msgid="774540592299064747">"Ծանուցումների դասակարգման ծառայություն"</string> <string name="vpn_title" msgid="19615213552042827">"VPN-ը ակտիվացված է"</string> <string name="vpn_title_long" msgid="6400714798049252294">"VPN-ն ակտիվացված է <xliff:g id="APP">%s</xliff:g>-ի կողմից"</string> <string name="vpn_text" msgid="3011306607126450322">"Հպեք` ցանցի կառավարման համար:"</string> @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Աշխատանքային ռեժիմն ԱՆՋԱՏՎԱԾ Է"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Թույլատրել աշխատանքային պրոֆիլի (այդ թվում նաև հավելվածների, ֆոնային համաժամացման և առնչվող գործառական հնարավորությունների) աշխատանքը:"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Միացնել"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s-ը կասեցվել է"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Կասեցվել է %1$s ադմինիստրատորի կողմից: Ավելին իմանալու համար կապվեք նրա հետ:"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Դուք ունեք նոր հաղորդագրություններ"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Դիտելու համար բացել SMS հավելվածը"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Որոշ գործառույթներ կարող են սահմանափակված լինել"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Ապամրացնել"</string> <string name="app_info" msgid="6856026610594615344">"Հավելվածի տվյալներ"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Սարքը սովորական ռեժիմում օգտագործելու համար կատարեք գործարանային վերակայում"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Հպեք՝ ավելին իմանալու համար:"</string> </resources> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 14b7526bf10a..fca667a9c98c 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Mode kerja NONAKTIF"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Izinkan profil kerja berfungsi, termasuk aplikasi, sinkronisasi latar belakang, dan fitur terkait."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktifkan"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dinonaktifkan"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Dinonaktifkan oleh administrator %1$s. Hubungi administrator untuk mempelajari lebih lanjut."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Ada pesan baru"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Buka aplikasi SMS untuk melihat"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Beberapa fungsi mungkin terbatas"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Lepas pin"</string> <string name="app_info" msgid="6856026610594615344">"Info aplikasi"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Dikembalikan ke setelan pabrik untuk menggunakan perangkat ini secara normal"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sentuh untuk mempelajari lebih lanjut."</string> </resources> diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml index e3278f3823a4..dc4121484659 100644 --- a/core/res/res/values-is-rIS/strings.xml +++ b/core/res/res/values-is-rIS/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Slökkt á vinnusniði"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Leyfa virkni vinnusniðs, m.a. forrita, samstillingar í bakgrunni og tengdra eiginleika."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Kveikja"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s óvirkt"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Gert óvirkt af stjórnanda %1$s. Hafðu samband við hann til að fá frekari upplýsingar."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Þú ert með ný skilaboð"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Opnaðu SMS-forritið til að skoða"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Sum virkni kann að vera takmörkuð"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Losa"</string> <string name="app_info" msgid="6856026610594615344">"Forritsupplýsingar"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Núllstilltu til að nota þetta tæki í venjulegri stillingu"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Snertu til að fá frekari upplýsingar."</string> </resources> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 6f1c1ec12019..c43470ba178e 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modalità Lavoro DISATTIVATA"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Attiva il profilo di lavoro, incluse app, sincronizzazione in background e funzioni correlate."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Attiva"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s disattivato"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Disattivato dall\'amministratore di %1$s. Contattalo per ulteriori informazioni."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Hai nuovi messaggi"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Apri l\'app SMS per la visualizzazione"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Funzioni potenzial. limitate"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Sblocca"</string> <string name="app_info" msgid="6856026610594615344">"Informazioni app"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Esegui il ripristino dei dati di fabbrica per utilizzare normalmente il dispositivo"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tocca per ulteriori informazioni."</string> </resources> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 8ac349061c5a..246140b3c3ee 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1151,7 +1151,7 @@ <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string> <string name="notification_listener_binding_label" msgid="2014162835481906429">"מאזין להתראות"</string> - <string name="vr_listener_binding_label" msgid="4316591939343607306">"מאזין VR"</string> + <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR ליסנר"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ספק תנאי"</string> <string name="notification_ranker_binding_label" msgid="774540592299064747">"שירות של דירוג הודעות"</string> <string name="vpn_title" msgid="19615213552042827">"VPN מופעל"</string> @@ -1587,8 +1587,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"מצב העבודה כבוי"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"אפשר לפרופיל העבודה לפעול, כולל אפליקציות, סנכרון ברקע ותכונות קשורות."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"הפעל"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"החבילה %1$s הושבתה"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"הושבתה על ידי מנהל המערכת של %1$s. צור איתו קשר כדי לקבל מידע נוסף."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"יש לך הודעות חדשות"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"פתח את אפליקציית ה-SMS כדי להציג"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ייתכן שחלק מהפונקציונליות תהיה מוגבלת"</string> @@ -1602,6 +1600,7 @@ <string name="unpin_target" msgid="3556545602439143442">"בטל הצמדה"</string> <string name="app_info" msgid="6856026610594615344">"פרטי אפליקציה"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"איפוס להגדרות היצרן לצורך שימוש במכשיר זה באופן רגיל"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"גע לקבלת מידע נוסף."</string> </resources> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 5c9729532bd8..1cd079be243d 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Work モード OFF"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"仕事用プロファイルで、アプリ、バックグラウンド同期などの関連機能の使用を許可します。"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ON にする"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$sが無効です"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s管理者によって無効になっています。詳しくは管理者までお問い合わせください。"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"新着メッセージがあります"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"表示するには SMS アプリを開きます"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"一部機能が制限されている可能性"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"固定を解除"</string> <string name="app_info" msgid="6856026610594615344">"アプリ情報"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"この端末は正常に使用するために出荷時設定にリセットされました"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"タップして詳細をご確認ください。"</string> </resources> diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml index 15167f735215..8ff6a09bb841 100644 --- a/core/res/res/values-ka-rGE/strings.xml +++ b/core/res/res/values-ka-rGE/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"სამსახურის რეჟიმი გამორთულია"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"სამსახურის პროფილის მუშაობის დაშვება, მათ შორის, აპების, ფონური სინქრონიზაციის და დაკავშირებული ფუნქციების."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ჩართვა"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s გათიშულია"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"გათიშულია „%1$s“-ის ადმინისტრატორის მიერ. დაუკავშირდით მას მეტის გასაგებად."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"თქვენ ახალი შეტყობინებები გაქვთ"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"სანახავად, გახსენით SMS აპი"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ზოგიერთი ფუნქცია შეიძლება შეიზღუდოს"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"ჩამაგრების მოხსნა"</string> <string name="app_info" msgid="6856026610594615344">"აპის შესახებ"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"ამ მოწყობილობის ჩვეულებრივად გამოსაყენებლად, დააბრუნეთ ქარხნული პარამეტრები"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"შეეხეთ მეტის გასაგებად."</string> </resources> diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml index 24b5e07dea5b..a0e987d135ff 100644 --- a/core/res/res/values-kk-rKZ/strings.xml +++ b/core/res/res/values-kk-rKZ/strings.xml @@ -1054,7 +1054,7 @@ <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"Қате туралы есеп алынуда…"</string> <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"Қате туралы есепті бөлісу керек пе?"</string> <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"Қате туралы есеп бөлісілуде…"</string> - <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Қолданбалар мен деректерді бөлісуі мүмкін."</string> + <string name="share_remote_bugreport_notification_message_finished" msgid="8610614010660772643">"АТ әкімшісі осы құрылғы ақауларын жоюға көмектесу үшін қате туралы есепті сұрады. Оған қолданбалар мен деректер көрсетілуі мүмкін."</string> <string name="share_remote_bugreport_action" msgid="6249476773913384948">"БӨЛІСУ"</string> <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ҚАБЫЛДАМАУ"</string> <string name="select_input_method" msgid="8547250819326693584">"Пернетақтаны өзгерту"</string> @@ -1135,7 +1135,7 @@ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Артқы фоны"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Артқы фонын өзгерту"</string> <string name="notification_listener_binding_label" msgid="2014162835481906429">"Хабар бақылағыш"</string> - <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR тыңдаушы"</string> + <string name="vr_listener_binding_label" msgid="4316591939343607306">"Виртуалды шынайылық тыңдаушысы"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Шарт провайдері"</string> <string name="notification_ranker_binding_label" msgid="774540592299064747">"Хабарландыруларды жіктеу қызметі"</string> <string name="vpn_title" msgid="19615213552042827">"VPN белсенді"</string> @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Жұмыс режимі ӨШІРУЛІ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Жұмыс профиліне, соның ішінде, қолданбаларға, фондық синхрондауға және қатысты мүмкіндіктерге жұмыс істеуге рұқсат ету."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Қосу"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s өшірілген"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s әкімшісі өшірген. Қосымша мәліметтер алу үшін оларға хабарласыңыз."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Сізде жаңа хабарлар бар"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Көру үшін SMS қолданбасын ашыңыз"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Кейбір функциялар істемеуі мүмкін"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Босату"</string> <string name="app_info" msgid="6856026610594615344">"Қолданба ақпараты"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Осы құрылғыны әдеттегідей пайдалану үшін зауыттық параметрлерді қалпына келтіріңіз"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Қосымша мәліметтер алу үшін түртіңіз."</string> </resources> diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml index e3e46b05ccad..e586c78c9573 100644 --- a/core/res/res/values-km-rKH/strings.xml +++ b/core/res/res/values-km-rKH/strings.xml @@ -1551,8 +1551,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"របៀបការងារបានបិទ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"អនុញ្ញាតឲ្យប្រវត្តិរូបការងារដំណើរការ ដោយរាប់បញ្ចូលទាំងកម្មវិធី ការធ្វើសមកាលកម្មផ្ទៃខាងក្រោយ និងលក្ខណៈពិសេសដែលពាក់ព័ន្ធ។"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"បើក"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"បានបិទដំណើរការ %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"បិទដំណើរការដោយអ្នកគ្រប់គ្រង %1$s។ សូមទាក់ទងពួកគេដើម្បីស្វែងយល់បន្ថែម។"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"អ្នកមានសារថ្មី"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"បើកកម្មវិធីសារ SMS ដើម្បីមើល"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"លទ្ធភាពប្រើមុខងារមួយចំនួនអាចត្រូវបាកម្រិត"</string> @@ -1566,6 +1564,7 @@ <string name="unpin_target" msgid="3556545602439143442">"មិនខ្ទាស់"</string> <string name="app_info" msgid="6856026610594615344">"ព័ត៌មានកម្មវិធី"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"កំណត់ដូចចេញពីរោងចក្រឡើងវិញដើម្បីប្រើឧបករណ៍នេះតាមធម្មតា"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ប៉ះ ដើម្បីស្វែងយល់បន្ថែម។"</string> </resources> diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml index 7a41d4bb7077..74aa8019d5f8 100644 --- a/core/res/res/values-kn-rIN/strings.xml +++ b/core/res/res/values-kn-rIN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"ಕೆಲಸದ ಮೋಡ್ ಆಫ್ ಆಗಿದೆ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"ಅಪ್ಲಿಕೇಶನ್ಗಳು, ಹಿನ್ನೆಲೆ ಸಿಂಕ್ ಮತ್ತು ಇತರ ಸಂಬಂಧಿತ ವೈಶಿಷ್ಟ್ಯಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಕಾರ್ಯನಿರ್ವಹಿಸಲು ಅನುಮತಿಸಿ."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ಆನ್ ಮಾಡು"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s ನಿರ್ವಾಹಕರಿಂದ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ. ಇನ್ನಷ್ಟು ತಿಳಿದುಕೊಳ್ಳಲು ಅವರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"ನೀವು ಹೊಸ ಸಂದೇಶಗಳನ್ನು ಹೊಂದಿರುವಿರಿ"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"ವೀಕ್ಷಿಸಲು SMS ಅಪ್ಲಿಕೇಶನ್ ತೆರೆಯಿರಿ"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ಕೆಲವು ಕಾರ್ಯನಿರ್ವಹಣೆಗಳು ಸೀಮಿತವಾಗಿರಬಹುದು"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"ಅನ್ಪಿನ್"</string> <string name="app_info" msgid="6856026610594615344">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"ಈ ಸಾಧನವನ್ನು ಸಾಮಾನ್ಯ ರೀತಿಯಲ್ಲಿ ಬಳಸಲು ಫ್ಯಾಕ್ಟರಿ ರಿಸೆಟ್ ಮಾಡಿ"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಸ್ಪರ್ಶಿಸಿ."</string> </resources> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index b236d398d0a3..3c09cfb8b43c 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"직장 모드가 사용 중지됨"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"앱, 백그라운드 동기화 및 관련 기능을 포함한 직장 프로필이 작동하도록 허용"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"사용 설정"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s이(가) 사용 중지됨"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s 관리자에 의해 사용 중지되었습니다. 자세히 알아보려면 관리자에게 문의하세요."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"새 메시지 있음"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"SMS 앱을 열고 확인"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"일부 기능이 제한될 수 있습니다."</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"고정 해제"</string> <string name="app_info" msgid="6856026610594615344">"앱 정보"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"정상적인 기기 사용을 위한 초기화"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"자세한 내용을 보려면 터치하세요."</string> </resources> diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml index fe89bf9237d8..d10a50f04b7a 100644 --- a/core/res/res/values-ky-rKG/strings.xml +++ b/core/res/res/values-ky-rKG/strings.xml @@ -1136,9 +1136,9 @@ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тушкагаз"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Тушкагазды өзгөртүү"</string> <string name="notification_listener_binding_label" msgid="2014162835481906429">"Эскертүү тыңшагычы"</string> - <string name="vr_listener_binding_label" msgid="4316591939343607306">"Виртуалдык угуучу"</string> + <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR режими"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Шарт түзүүчү"</string> - <string name="notification_ranker_binding_label" msgid="774540592299064747">"Эскертмени баалоо кызматы"</string> + <string name="notification_ranker_binding_label" msgid="774540592299064747">"Эскертмелердин маанилүүлүгүн баалоо кызматы"</string> <string name="vpn_title" msgid="19615213552042827">"VPN иштетилди"</string> <string name="vpn_title_long" msgid="6400714798049252294">"VPN <xliff:g id="APP">%s</xliff:g> аркылуу жандырылды"</string> <string name="vpn_text" msgid="3011306607126450322">"желени башкаруу үчүн басыңыз."</string> @@ -1550,8 +1550,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Жумуш режими ӨЧҮРҮЛГӨН"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Жумуш профилин, ошондой эле колдонмолорду, фондо шайкештирүү жана ага байланыштуу функцияларды иштетиңиз."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Күйгүзүү"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s өчүрүлгөн"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s администратору тарабынан өчүрүлгөн. Көбүрөөк билүү үчүн администраторго кайрылыңыз."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Сизге жаңы билдирүүлөр келди"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Көрүү үчүн SMS колдонмосун ачыңыз"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Айрым функциялар чектлши мүмкн"</string> @@ -1565,6 +1563,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Кадоодон алып коюу"</string> <string name="app_info" msgid="6856026610594615344">"Колдонмо тууралуу"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Бул түзмөктү кадимкидей колдонуу үчүн заводдук баштапкы абалына келтириңиз"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Көбүрөөк билүү үчүн тийип коюңуз."</string> </resources> diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml index 5ad178673fad..46cc85aa3080 100644 --- a/core/res/res/values-lo-rLA/strings.xml +++ b/core/res/res/values-lo-rLA/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"ໂໝດບ່ອນເຮັດວຽກປິດຢູ່"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"ອະນຸຍາດໃຫ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກສາມາດນຳໃຊ້ໄດ້ ເຊິ່ງຮວມທັງແອັບ, ການຊິ້ງຂໍ້ມູນໃນພື້ນຫຼັງ ແລະ ຄຸນສົມບັດທີ່ກ່ຽວຂ້ອງ."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ເປີດ"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ຖືກປິດໃຊ້ແລ້ວ"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"ຖືກປິດໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບ %1$s. ກະລຸນາຕິດຕໍ່ຫາພວກເຂົາເພື່ອສຶກສາເພີ່ມເຕີມ."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"ທ່ານມີຂໍ້ຄວາມໃໝ່"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"ເປີດແອັບ SMS ເພື່ອເບິ່ງ"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ບາງຄວາມສາມາດນຳໃຊ້ອາດຈະຖືກຈຳກັດ"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"ຖອນປັກໝຸດ"</string> <string name="app_info" msgid="6856026610594615344">"ຂໍ້ມູນແອັບ"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"ຣີເຊັດເປັນຄ່າໂຮງງານເພື່ອໃຊ້ອຸປະກອນນີ້ປົກກະຕິ"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ແຕະເພື່ອສຶກສາເພີ່ມເຕີມ."</string> </resources> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 5496adaf6e07..0efdfcaf9896 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1587,8 +1587,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Darbo režimas išjungtas"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Leisti veikti darbo profiliui, įskaitant programas, sinchronizavimą fone ir susijusias funkcijas."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Įjungti"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s išjungtas"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Išjungė %1$s administratorius. Kad sužinotumėte daugiau, susisiekite su juo."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Turite naujų pranešimų"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Atidaryti SMS programą, norint peržiūrėti"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Kai kurios funkcijos gali būti ribojamos"</string> @@ -1602,6 +1600,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Atsegti"</string> <string name="app_info" msgid="6856026610594615344">"Programos informacija"</string> <string name="negative_duration" msgid="5688706061127375131">"–<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Atkurkite gamyklinius nustatymus, kad galėtumėte įprastai naudoti šį įrenginį"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Palieskite, kad sužinotumėte daugiau."</string> </resources> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 59ffdc3224f4..f5c59219eb99 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1568,8 +1568,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Darba režīms IZSLĒGTS"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Atļaujiet darboties darba profilam, tostarp lietotnēm, sinhronizācijai fonā un saistītajām funkcijām."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Ieslēgt"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Pakotne %1$s atspējota"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Atspējoja %1$s administrators. Lai uzzinātu vairāk, sazinieties ar administratoru."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Jums ir jaunas īsziņas."</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Lai skatītu, atveriet īsziņu lietotni."</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Funkcijas var būt ierobežotas"</string> @@ -1583,6 +1581,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Atspraust"</string> <string name="app_info" msgid="6856026610594615344">"Lietotnes informācija"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Rūpnīcas datu atiestatīšana ierīces normālai darbībai"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pieskarieties, lai uzzinātu vairāk."</string> </resources> diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml index d0a7b20e8bbd..1fbf3630bcef 100644 --- a/core/res/res/values-mk-rMK/strings.xml +++ b/core/res/res/values-mk-rMK/strings.xml @@ -1551,8 +1551,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Режимот на работа е ИСКЛУЧЕН"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Дозволете работниот профил да функционира, вклучувајќи ги апликациите, синхронизирањето во заднина и други поврзани функции."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Вклучи"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s е оневозможен"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Оневозможено од администраторот на %1$s. Контактирајте со него за да дознаете повеќе."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нови пораки"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Отворете ја апликацијата за СМС за приказ"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Некои функции се ограничени"</string> @@ -1566,6 +1564,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Откачете"</string> <string name="app_info" msgid="6856026610594615344">"Информации за апликација"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Ресетирање на фабрички вредности за уредот да се користи нормално"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Допрете за да дознаете повеќе."</string> </resources> diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml index 829e06aac987..2fa6786226fa 100644 --- a/core/res/res/values-ml-rIN/strings.xml +++ b/core/res/res/values-ml-rIN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"ഔദ്യോഗിക മോഡ് ഓഫാണ്"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"ആപ്സും, പശ്ചാത്തല സമന്വയവും ബന്ധപ്പെട്ട ഫീച്ചറുകളും ഉൾപ്പെടെ, ഔദ്യോഗിക പ്രൊഫൈലിനെ പ്രവർത്തിക്കാൻ അനുവദിക്കുക."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ഓണാക്കുക"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s പ്രവർത്തനരഹിതമാക്കി"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s അഡ്മിനിസ്ട്രേറ്റർ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു. കൂടുതലറിയാൻ അഡ്മിനിസ്ട്രേറ്ററെ ബന്ധപ്പെടുക."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"നിങ്ങൾക്ക് പുതിയ സന്ദേശങ്ങൾ ഉണ്ട്"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"കാണുന്നതിന് SMS ആപ്പ് തുറക്കുക"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ചില പ്രവർത്തനക്ഷമതകൾ പരിമിതപ്പെടാം"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"അൺപിൻ ചെയ്യുക"</string> <string name="app_info" msgid="6856026610594615344">"ആപ്പ് വിവരം"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"ഈ ഉപകരണം സാധാരണ നിലയിൽ ഉപയോഗിക്കാൻ ഫാക്ടറി പുനഃസജ്ജീകരണം നടത്തുക"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"കൂടുതലറിയുന്നതിന് സ്പർശിക്കുക."</string> </resources> diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml index 9414f4e646a1..9956dbf0c319 100644 --- a/core/res/res/values-mn-rMN/strings.xml +++ b/core/res/res/values-mn-rMN/strings.xml @@ -1547,8 +1547,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Ажлын горимыг УНТРААСАН байна"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Ажлын профайлд апп, дэвсгэр синхрончлол болон бусад холбоотой тохиргоог ажиллахыг зөвшөөрнө үү."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Асаах"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s идэвхгүй болгосон"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s админ идэвхгүй болгосон. Дэлгэрэнгүй мэдэхийн тулд тэдэнтэй холбоо барина уу."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Танд шинэ зурвасууд байна"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Үзэхийн тулд SMS аппыг нээх"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Зарим үйлдэл хязгаарлалттай байж болно"</string> @@ -1562,6 +1560,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Unpin"</string> <string name="app_info" msgid="6856026610594615344">"Апп-н мэдээлэл"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Энэ төхөөрөмжийг хэвийн ашиглахын тулд үйлдвэрийн тохиргоонд дахин тохируулна уу"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Дэлгэрэнгүй үзэх бол дарна уу."</string> </resources> diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml index 67351eac138b..40f780780d61 100644 --- a/core/res/res/values-mr-rIN/strings.xml +++ b/core/res/res/values-mr-rIN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बंद आहे"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"कार्य प्रोफाइलला अॅप्स, पार्श्वभूमी संकालन आणि संबंधित वैशिष्ट्यांच्या समावेशासह कार्य करण्याची परवानगी द्या."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"चालू करा"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s अक्षम केले"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s प्रशासकाद्वारे अक्षम केले. अधिक जाणून घेण्यासाठी त्यांच्याशी संपर्क साधा."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"आपल्याकडे नवीन संदेश आहेत"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"पाहण्यासाठी SMS अॅप उघडा"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"काही कार्यक्षमता मर्यादित असू शकतात"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"अनपिन करा"</string> <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"हे डिव्हाइस सामान्यपणे वापरण्यासाठी फॅक्टरी रीसेट करा"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"अधिक जाणून घेण्यासाठी स्पर्श करा."</string> </resources> diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml index 5c342f0608e3..2154bda338cf 100644 --- a/core/res/res/values-ms-rMY/strings.xml +++ b/core/res/res/values-ms-rMY/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Mod kerja DIMATIKAN"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Benarkan profil kerja berfungsi, termasuk apl, penyegerakan latar belakang dan ciri yang berkaitan."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Hidupkan"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s dilumpuhkan"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Dilumpuhkan oleh pentadbir %1$s. Hubungi mereka untuk mengetahui lebih lanjut."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Anda mempunyai mesej baharu"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Buka apl SMS untuk melihat"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Sesetengah fungsi mungkin terhad"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Nyahsemat"</string> <string name="app_info" msgid="6856026610594615344">"Maklumat apl"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Lakukan tetapan semula kilang untuk menggunakan peranti ini seperti biasa"</string> - <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sentuh untuk mengetahui lebih lanjut."</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> + <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ketik untuk mengetahui lebih lanjut."</string> </resources> diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml index e66cf66a06f7..4a934f018116 100644 --- a/core/res/res/values-my-rMM/strings.xml +++ b/core/res/res/values-my-rMM/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"အလုပ်မုဒ် ပိတ်ထားသည်"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"အက်ပ်များ၊ နောက်ခံစင့်ခ်လုပ်ခြင်း၊ နှင့်သက်ဆိုင်သည့်အင်္ဂါရပ်များကို ဆောင်ရွက်ရန် အလုပ်ပရိုဖိုင်ကိုခွင့်ပြုပါ။"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ဖွင့်ပါ"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ကိုပိတ်ထားသည်"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s စီမံခန့်ခွဲသူမှ ပိတ်ထားသည်။ ပိုမိုလေ့လာရန် ၎င်းတို့ကိုဆက်သွယ်ပါ။"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"သင့်ထံတွင် စာအသစ်များရောက်နေသည်"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"ကြည့်ရှုရန် SMS အက်ပ်ကိုဖွင့်ပါ"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"အချို့လုပ်ဆောင်ချက်များ ကန့်သတ်ချက်ရှိနိုင်သည်"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"ဖြုတ်ပါ"</string> <string name="app_info" msgid="6856026610594615344">"အက်ပ်အချက်အလက်"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"ဤစက်ပစ္စည်းကို သာမန်အသုံးပြုနိုင်ရန် စက်ရုံထုတ်အတိုင်း ပြန်လည်သတ်မှတ်ပါ"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ပိုမိုလေ့လာရန် တို့ပါ။"</string> </resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 6c2358b4e13c..79a5a8603458 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1549,10 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Jobbmodus er AV"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Slå på jobbprofilen, inkludert apper, synkronisering i bakgrunnen og relaterte funksjoner."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Slå på"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s er slått av"</string> - <!-- String.format failed for translation --> - <!-- no translation found for suspended_package_message (6341091587106868601) --> - <skip /> <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nye meldinger"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Åpne SMS-appen for å se"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Enkelte funksjoner kan være begrenset"</string> @@ -1566,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Løsne"</string> <string name="app_info" msgid="6856026610594615344">"Info om appen"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Tilbakestill til fabrikkstandard for å bruke denne enheten som normalt"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Trykk for å finne ut mer."</string> </resources> diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml index 40d13f091cea..db7cd0193d46 100644 --- a/core/res/res/values-ne-rNP/strings.xml +++ b/core/res/res/values-ne-rNP/strings.xml @@ -1555,8 +1555,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"कार्य मोड बन्द छ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"अनुप्रयोग, पृष्ठभूमि सिंक र सम्बन्धित विशेषताहरू सहित, कार्य प्रोफाइललाई कार्य गर्न अनुमति दिनुहोस्।"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"सक्रिय गर्नुहोस्"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s असक्षम भयो"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s प्रशासकद्वारा असक्षम गरिएको। थप जान्नका लागि तिनीहरूलाई सम्पर्क गर्नुहोस्।"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"तपाईंलाई नयाँ सन्देश आएको छ"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"हेर्नका लागि SMS अनुप्रयोग खोल्नुहोस्"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"केही कार्य सीमित हुनसक्छ"</string> @@ -1570,6 +1568,7 @@ <string name="unpin_target" msgid="3556545602439143442">"अनपिन गर्नुहोस्"</string> <string name="app_info" msgid="6856026610594615344">"अनुप्रयोगका बारे जानकारी"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"यस यन्त्रलाई सामान्य रूपमा प्रयोग गर्नका लागि फ्याक्ट्री रिसेट गर्नुहोस्"</string> - <string name="audit_safemode_notification_details" msgid="1860601176690176413">"थप जान्नका लागि स्पर्श गर्नुहोस्।"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> + <string name="audit_safemode_notification_details" msgid="1860601176690176413">"थप जान्नका लागि छुनुहोस्।"</string> </resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index b48fc3329b41..c7c95e195ed8 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Werkmodus is UIT"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Functioneren van werkprofiel toestaan, waaronder apps, synchronisatie op de achtergrond en gerelateerde functies."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Inschakelen"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s is uitgeschakeld"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Uitgeschakeld door de beheerder van %1$s. Neem voor meer informatie contact op met de beheerder."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Je hebt nieuwe berichten"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Open je sms-app om ze te bekijken"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Bepaalde functionaliteit kan zijn beperkt"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Losmaken"</string> <string name="app_info" msgid="6856026610594615344">"App-info"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Zet dit apparaat terug op de fabrieksinstellingen om het normaal te gebruiken"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tik voor meer informatie."</string> </resources> diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml index 7ff207183f3e..cbb26282b582 100644 --- a/core/res/res/values-pa-rIN/strings.xml +++ b/core/res/res/values-pa-rIN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"ਕੰਮ ਮੋਡ ਬੰਦ ਹੈ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"ਐਪਾਂ, ਬੈਕਗ੍ਰਾਊਂਡ ਸਮਕਾਲੀਕਰਨ, ਅਤੇ ਸਬੰਧਿਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋਏ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਕੰਮ ਕਰਨ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ।"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ਚਾਲੂ ਕਰੋ"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ। ਹੋਰ ਜਾਣਨ ਲਈ ਉਹਨਾਂ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"ਤੁਹਾਨੂੰ ਨਵੇਂ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਹੋਏ ਹਨ"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"ਵੇਖਣ ਲਈ SMS ਐਪ ਖੋਲ੍ਹੋ"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ਕੁਝ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਸੀਮਿਤ ਹੋ ਸਕਦੀ ਹੈ"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"ਅਨਪਿੰਨ ਕਰੋ"</string> <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਸਧਾਰਨ ਰੂਪ ਵਿੱਚ ਵਰਤਣ ਲਈ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਕਰੋ"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"ਹੋਰ ਜਾਣਨ ਲਈ ਸਪਰਸ਼ ਕਰੋ।"</string> </resources> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index b68b45a8508e..5eb6b563a08a 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1587,8 +1587,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Tryb pracy jest WYŁĄCZONY"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Włącz profil do pracy, w tym aplikacje, synchronizację w tle i inne funkcje."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Włącz"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Wyłączono pakiet %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Wyłączone przez administratora organizacji %1$s. Skontaktuj się z nim, by dowiedzieć się więcej."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Masz nowe wiadomości"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Otwórz aplikację do SMS-ów, by wyświetlić wiadomość"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Niektóre funkcje mogą być niedostępne"</string> @@ -1602,6 +1600,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Odepnij"</string> <string name="app_info" msgid="6856026610594615344">"O aplikacji"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Aby używać tego urządzenia normalnie, przywróć ustawienia fabryczne"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Kliknij, by dowiedzieć się więcej."</string> </resources> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index cd0de0e2feb8..21f6665d7677 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir que o perfil de trabalho funcione, incluindo apps, sincronização em segundo plano e recursos relacionados"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Entre em contato com ele para saber mais."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Você tem mensagens novas"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra o app de SMS para ver"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalidades são limitadas"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string> <string name="app_info" msgid="6856026610594615344">"Informações do app"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Redefinir para a configuração original para usar este dispositivo normalmente"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string> </resources> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index dde0131118e4..011ad4ecfa73 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir o funcionamento do perfil de trabalho, incluindo as aplicações, a sincronização em segundo plano e as funcionalidades relacionadas."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Contacte-o para saber mais."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Tem mensagens novas"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra a aplicação de SMS para ver"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalid. limitadas"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Soltar"</string> <string name="app_info" msgid="6856026610594615344">"Informações da aplicação"</string> <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Fazer uma reposição de dados de fábrica para utilizar este dispositivo normalmente"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string> </resources> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index cd0de0e2feb8..21f6665d7677 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modo de trabalho DESATIVADO"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Permitir que o perfil de trabalho funcione, incluindo apps, sincronização em segundo plano e recursos relacionados"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Ativar"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s desativado"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Desativado pelo administrador de %1$s. Entre em contato com ele para saber mais."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Você tem mensagens novas"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Abra o app de SMS para ver"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Algumas funcionalidades são limitadas"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Liberar guia"</string> <string name="app_info" msgid="6856026610594615344">"Informações do app"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Redefinir para a configuração original para usar este dispositivo normalmente"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Toque para saber mais."</string> </resources> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 1c6e02445908..fe5139eb618e 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1568,8 +1568,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modul de serviciu e DEZACTIVAT"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Permiteți profilului de serviciu să funcționeze, inclusiv aplicațiile, sincronizarea în fundal și funcțiile asociate."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Activați"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Dezactivat de %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Dezactivat de administratorul companiei %1$s. Contactați-l pentru a afla mai multe."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Aveți mesaje noi"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Deschideți aplicația pentru SMS-uri ca să vizualizați"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Unele funcții ar putea fi limitate"</string> @@ -1583,6 +1581,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Anulați fixarea"</string> <string name="app_info" msgid="6856026610594615344">"Informații despre aplicație"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Reveniți la setările din fabrică pentru a folosi acest dispozitiv ca de obicei"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Atingeți pentru a afla mai multe."</string> </resources> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index f13435797101..40c85510bb48 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1587,8 +1587,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Рабочий режим отключен"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Включить рабочий профиль: приложения, фоновую синхронизацию и связанные функции."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Включить"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Пакет \"%1$s\" заблокирован"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Пакет заблокирован администратором компании \"%1$s\". Обратитесь к нему за дополнительной информацией."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Новые сообщения"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Чтобы просмотреть, откройте приложение для обмена SMS"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Некоторые функции недоступны"</string> @@ -1602,6 +1600,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Открепить"</string> <string name="app_info" msgid="6856026610594615344">"О приложении"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Сброс до заводских настроек в целях безопасности"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Нажмите, чтобы узнать больше."</string> </resources> diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml index 9a6d3af92557..4f0c9713d901 100644 --- a/core/res/res/values-si-rLK/strings.xml +++ b/core/res/res/values-si-rLK/strings.xml @@ -1551,8 +1551,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"වැඩ ප්රකාරය ක්රියාවිරහිතයි"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"යෙදුම්, පසුබිම සමමුහුර්ත කිරීම, සහ සම්බන්ධිත විශේෂාංග ඇතුළුව, ක්රියා කිරීමට කාර්යාල පැතිකඩට ඉඩ දෙන්න"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ක්රියාත්මක කරන්න"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s අබල කරන ලදී"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s පරිපාලක විසින් අබල කරන ලදී. තව දැන ගැනීමට ඔවුන් අමතන්න."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"ඔබට නව පණිවිඩ තිබේ"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"බැලීමට විවෘත SMS යෙදුම විවෘත කරන්න"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"ඇතැම් ක්රියාකාරිත්ව සීමිත විය හැකිය"</string> @@ -1566,6 +1564,7 @@ <string name="unpin_target" msgid="3556545602439143442">"ගලවන්න"</string> <string name="app_info" msgid="6856026610594615344">"යෙදුම් තොරතුරු"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"මෙම උපාංගය සාමාන්ය ලෙස භාවිත කිරීමට කර්මාන්තශාලා යළි සැකසීම"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"තව දැන ගැනීමට ස්පර්ශ කරන්න."</string> </resources> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index f4794a6cacdb..46304349394d 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1587,8 +1587,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Pracovný režim je VYPNUTÝ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Povoľte fungovanie pracovného profilu vrátane aplikácií, synchronizácie na pozadí a súvisiacich funkcií."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Zapnúť"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Balík %1$s bol zakázaný"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Zakázané správcom %1$s. Ak chcete získať ďalšie informácie, kontaktujte ho."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Máte nové správy."</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Otvorte aplikáciu pre SMS a zobrazte správu"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Niektoré funkcie môžu byť obmedzené"</string> @@ -1602,6 +1600,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Uvoľniť"</string> <string name="app_info" msgid="6856026610594615344">"Info o aplikácii"</string> <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Ak chcete toto zariadenie používať normálnym spôsobom, obnovte na ňom továrenské nastavenia"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Klepnutím získate ďalšie informácie."</string> </resources> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 3e0cfaff83cf..bf6075239b16 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1587,8 +1587,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Delovni način IZKLOPLJEN"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Dovoljeno delovanje delovnega profila, vključno z aplikacijami, sinhronizacijo v ozadju in povezanimi funkcijami."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Vklop"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s – onemogočeno"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Onemogočil skrbnik %1$s. Za več informacij se obrnite nanj."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Imate nova sporočila."</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Za ogled odprite aplikacijo za SMS-je"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Nekatere funkcije bodo omejene"</string> @@ -1602,6 +1600,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Odpenjanje"</string> <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Napravo ponastavite na tovarniške nastavitve, če jo želite uporabljati brez težav"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Dotaknite se, če želite izvedeti več."</string> </resources> diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml index bc8bd2ba50e0..8b78c767efe6 100644 --- a/core/res/res/values-sq-rAL/strings.xml +++ b/core/res/res/values-sq-rAL/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Modaliteti i punës është JOAKTIV"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Lejoje profilin e punës të funksionojë, duke përfshirë aplikacionet, sinkronizimin në sfond dhe funksionet e lidhura."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivizo"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s është çaktivizuar"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Çaktivizuar nga administratori i %1$s. Kontaktoje për të mësuar më shumë."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Ke mesazhe të reja"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Hap aplikacionin SMS për ta parë"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Disa funksione mund të jenë të kufizuara"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Zhgozhdo"</string> <string name="app_info" msgid="6856026610594615344">"Informacioni mbi aplikacionin"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Rivendos cilësimet e fabrikës për ta përdorur normalisht këtë pajisje"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Prek për të mësuar më shumë."</string> </resources> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index d14c166d71a9..c68ec8867957 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1568,8 +1568,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Режим за Work је ИСКЉУЧЕН"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Дозвољава профилу за Work да функционише, укључујући апликације, синхронизацију у позадини и сродне функције."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Укључи"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Пакет %1$s је онемогућен"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Онемогућио је администратор компаније %1$s. Контактирајте га да бисте сазнали више."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Имате нове поруке"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Отворите апликацију за SMS да бисте прегледали"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Неке функције су можда ограничене"</string> @@ -1583,6 +1581,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Откачи"</string> <string name="app_info" msgid="6856026610594615344">"Информације о апликацији"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Ресетујте уређај на фабричка подешавања да бисте га нормално користили"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Додирните да бисте сазнали више."</string> </resources> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 3eb4ae346ee6..46b1bf6d6f3d 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Arbetsläget är inaktiverat"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Tillåt att jobbprofilen är aktiv, inklusive appar, bakgrundssynkronisering och andra tillhörande funktioner."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Aktivera"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s har inaktiverats"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Inaktiverat av administratören för %1$s. Kontakta administratören om du vill veta mer."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Du har nya meddelanden"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Öppna sms-appen och visa meddelandet"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Vissa funktioner är begränsade"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Lossa"</string> <string name="app_info" msgid="6856026610594615344">"Info om appen"</string> <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Återställ standardinställningarna om du vill använda enheten normalt"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Tryck här om du vill läsa mer."</string> </resources> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 04994d55a1ce..fa3d151316cf 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1551,8 +1551,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Hali ya kazi IMEZIMWA"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Ruhusu wasifu wa kazini utumike, ikiwa ni pamoja na programu, usawazishaji wa chini chini na vipengele vinavyohusiana."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Washa"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Imezimwa na %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Imezimwa na msimamizi wa %1$s. Wasiliana naye ili upate maelezo zaidi."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Una ujumbe mpya"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Fungua programu ya SMS ili uweze kuangalia"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Huenda baadhi ya utendaji ukawa vikwazo"</string> @@ -1566,6 +1564,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Bandua"</string> <string name="app_info" msgid="6856026610594615344">"Maelezo ya programu"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Rejesha mipangilio ya kiwandani katika kifaa hiki ili ukitumie kwa njia ya kawaida"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Gusa ili kupata maelezo zaidi."</string> </resources> diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml index 2cb08c9e2d96..57bde42a2f81 100644 --- a/core/res/res/values-ta-rIN/strings.xml +++ b/core/res/res/values-ta-rIN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"பணிப் பயன்முறை முடக்கப்பட்டது"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"செயல்பட, பணி சுயவிவரத்தை அனுமதி. இதில் பயன்பாடுகள், பின்னணி ஒத்திசைவு மற்றும் தொடர்புடைய அம்சங்கள் அடங்கும்."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"இயக்கு"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s முடக்கப்பட்டது"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s நிர்வாகி முடக்கியுள்ளார். மேலும் அறிய, அவரைத் தொடர்புகொள்ளவும்."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"புதிய செய்திகள் வந்துள்ளன"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"பார்க்க, SMS பயன்பாட்டைத் திறக்கவும்"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"சில செயல்பாடு வரம்பிடப்பட்டிருக்கலாம்"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"பின்னை அகற்று"</string> <string name="app_info" msgid="6856026610594615344">"பயன்பாட்டுத் தகவல்"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"சாதாரணமாக இந்தச் சாதனத்தைப் பயன்படுத்த, ஆரம்ப நிலைக்கு மீட்டமைக்கவும்"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"மேலும் அறிய தொடவும்."</string> </resources> diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml index 4fd8aadd4b02..d2381fc0a729 100644 --- a/core/res/res/values-te-rIN/strings.xml +++ b/core/res/res/values-te-rIN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"కార్యాలయ మోడ్ ఆఫ్ చేయబడింది"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"అనువర్తనాలు, నేపథ్య సమకాలీకరణ మరియు సంబంధిత లక్షణాలతో సహా కార్యాలయ ప్రొఫైల్ను పని చేయడానికి అనుమతించండి."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"ఆన్ చేయి"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$sని నిలిపివేసారు"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$sని నిర్వాహకుడు నిలిపివేసారు. మరింత తెలుసుకోవడానికి వారిని సంప్రదించండి."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"మీకు కొత్త సందేశాలు ఉన్నాయి"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"వీక్షించడానికి SMS అనువర్తనాన్ని తెరవండి"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"కొంత కార్యాచరణ పరిమితం కావచ్చు"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"అన్పిన్ చేయి"</string> <string name="app_info" msgid="6856026610594615344">"అనువర్తన సమాచారం"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"ఈ పరికరాన్ని సాధారణంగా ఉపయోగించడానికి ఫ్యాక్టరీ రీసెట్ చేయండి"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"మరింత తెలుసుకోవడానికి తాకండి."</string> </resources> diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml index ae19150de3c0..58d3d9153013 100644 --- a/core/res/res/values-television/config.xml +++ b/core/res/res/values-television/config.xml @@ -25,7 +25,7 @@ <bool name="config_defaultWindowFeatureOptionsPanel">false</bool> <!-- Default bounds [left top right bottom] on screen for picture-in-picture windows. --> - <string translatable="false" name="config_defaultPictureInPictureBounds">"1420 100 1820 325"</string> + <string translatable="false" name="config_defaultPictureInPictureBounds">"1328 54 1808 324"</string> <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP is located in center. --> @@ -33,5 +33,5 @@ <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP is shown with Recents. --> - <string translatable="false" name="config_pictureInPictureBoundsInRecents">"1480 123 1760 303"</string> + <string translatable="false" name="config_pictureInPictureBoundsInRecents">"1484 96 1804 276"</string> </resources> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index fabecc39661b..1eedd0190766 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"โหมดทำงานปิดอยู่"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"อนุญาตให้โปรไฟล์งานทำงานได้ ซึ่งรวมถึงแอป การซิงค์ในพื้นหลัง และคุณลักษณะอื่นที่เกี่ยวข้อง"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"เปิด"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"ปิดใช้ %1$s แล้ว"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"ผู้ดูแลระบบ %1$s ได้ปิดใช้แล้ว โปรดสอบถามข้อมูลเพิ่มเติมจากเขา"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"คุณมีข้อความใหม่"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"เปิดแอป SMS เพื่อดู"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"อาจมีข้อจำกัดในบางฟังก์ชัน"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"เลิกปักหมุด"</string> <string name="app_info" msgid="6856026610594615344">"ข้อมูลแอป"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"รีเซ็ตเป็นค่าเริ่มต้นเพื่อใช้อุปกรณ์นี้ตามปกติ"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"แตะเพื่อเรียนรู้เพิ่มเติม"</string> </resources> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 981567d3c1f8..d785cf4f398b 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"NAKA-OFF ang work mode"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Payagang gumana ang profile sa trabaho, kasama na ang mga app, pag-sync sa background at mga may kaugnayang feature."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"I-on"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"Na-disable ang %1$s"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Na-disable ng administrator ng %1$s. Makipag-ugnayan sa administrator upang matuto nang higit pa."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Mayroon kang mga bagong mensahe"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Buksan ang SMS app upang tingnan"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Limitado ilang functionality"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"I-unpin"</string> <string name="app_info" msgid="6856026610594615344">"Impormasyon ng app"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Mag-factory reset upang magamit nang normal ang device na ito"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Pindutin upang matuto nang higit pa."</string> </resources> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index af5652b5b3ec..d4f2891c9d01 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"İş modu KAPALI"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Uygulamalar, arka planda senkronizasyon ve ilgili özellikler dahil olmak üzere iş profilinin çalışmasına izin ver."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Aç"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s devre dışı bırakıldı"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s yöneticisi tarafından devre dışı bırakıldı. Daha fazla bilgi edinmek için kendileriyle iletişime geçin."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Yeni mesajlarınız var"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Görüntülemek için SMS uygulamasını açın"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Bazı işlevler sınırlı olabilir"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Sabitlemeyi kaldır"</string> <string name="app_info" msgid="6856026610594615344">"Uygulama bilgileri"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Cihazı normal olarak kullanmak için fabrika ayarlarına sıfırlayın"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Daha fazla bilgi edinmek için dokunun."</string> </resources> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 344797f3245b..aba18b58b83b 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1153,7 +1153,7 @@ <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба читання сповіщень"</string> <string name="vr_listener_binding_label" msgid="4316591939343607306">"Обробник віртуальної реальності"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Постачальник умов"</string> - <string name="notification_ranker_binding_label" msgid="774540592299064747">"Служба позиціонування сповіщень"</string> + <string name="notification_ranker_binding_label" msgid="774540592299064747">"Служба встановлення пріоритетності сповіщень"</string> <string name="vpn_title" msgid="19615213552042827">"Мережу VPN активовано"</string> <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string> <string name="vpn_text" msgid="3011306607126450322">"Торкніться, щоб керувати мережею."</string> @@ -1587,8 +1587,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Робочий профіль ВИМКНЕНО"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Увімкнути робочий профіль, зокрема додатки, фонову синхронізацію та пов’язані функції."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Увімкнути"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s вимкнено"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Вимкнув адміністратор %1$s. Зв’яжіться з ним, щоб дізнатися більше."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"У вас є нові повідомлення"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Щоб переглянути, відкрийте додаток для SMS"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Деякі функції можуть не працювати"</string> @@ -1602,6 +1600,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Відкріпити"</string> <string name="app_info" msgid="6856026610594615344">"Про додаток"</string> <string name="negative_duration" msgid="5688706061127375131">"-<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Відновлення заводських налаштувань для належної роботи пристрою"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Торкніться, щоб дізнатися більше."</string> </resources> diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml index a58f5c282ce9..47e6e885e15f 100644 --- a/core/res/res/values-ur-rPK/strings.xml +++ b/core/res/res/values-ur-rPK/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"کام موڈ آف ہے"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"دفتری پروفائل کو کام کرنے دیں، بشمول ایپس، پس منظر کی مطابقت پذیری اور متعلقہ خصوصیات۔"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"آن کریں"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s غیر فعال کردہ"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s منتظم کی جانب سے غیر فعال کر دیا گیا۔ مزید جاننے کیلئے ان سے رابطہ کریں۔"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"آپ کے پاس نئے پیغامات ہیں"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"دیکھنے کیلئے SMS ایپ کھولیں"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"کچھ فعالیت محدود ہو سکتی ہے"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"پن ہٹائیں"</string> <string name="app_info" msgid="6856026610594615344">"ایپ کی معلومات"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"اس آلہ کو معمولاً استعمال کرنے کیلئے فیکٹری ری سیٹ کریں"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"مزید جاننے کیلئے ٹچ کریں۔"</string> </resources> diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml index 4ca18252352b..88a417b5d531 100644 --- a/core/res/res/values-uz-rUZ/strings.xml +++ b/core/res/res/values-uz-rUZ/strings.xml @@ -1135,7 +1135,7 @@ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fon rasmi"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Fon rasmini o‘zgartirish"</string> <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirishnoma tinglovchisi"</string> - <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR tinglovchisi"</string> + <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR rejimi"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Shartlarni taqdim etuvchi"</string> <string name="notification_ranker_binding_label" msgid="774540592299064747">"Bildirishnomalarni baholash xizmati"</string> <string name="vpn_title" msgid="19615213552042827">"VPN faollashtirildi"</string> @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Ish rejimi O‘CHIQ"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Ishchi profilini yoqish: ilovalar, fonda sinxronlash va bog‘liq funksiyalar."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Yoqish"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s o‘chirilgan"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"%1$s administratori tomonidan o‘chirilgan. Batafsil ma’lumot uchun bog‘laning."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Sizga yangi SMS keldi"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Ko‘rish uchun SMS ilovasini oching"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Ba’zi funksiyalar cheklanishi m-n"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Olib tashlash"</string> <string name="app_info" msgid="6856026610594615344">"Ilova haqida"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Bu qurilmadan odatdagidek foydalanish uchun zavod sozlamalarini tiklang"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Ko‘proq o‘rganish uchun bosing."</string> </resources> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 283198f435df..b67008e02851 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Chế độ làm việc đang TẮT"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Cho phép hồ sơ công việc hoạt động, bao gồm ứng dụng, đồng bộ hóa trong nền và các tính năng liên quan."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Bật"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s đã bị tắt"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Đã bị quản trị viên %1$s tắt. Hãy liên hệ với quản trị viên để tìm hiểu thêm."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Bạn có tin nhắn mới"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Mở ứng dụng SMS để xem"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Một số chức năng có thể bị hạn chế"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Bỏ ghim"</string> <string name="app_info" msgid="6856026610594615344">"Thông tin ứng dụng"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Thiết lập cài đặt gốc để sử dụng thiết bị này một cách bình thường"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Chạm để tìm hiểu thêm."</string> </resources> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 8dfbaed93296..d9e5a145ccd3 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"工作模式已关闭"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"启用工作资料,包括应用、后台同步和相关功能。"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"开启"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"%1$s已被禁用"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"该软件包已被%1$s管理员禁用。请与管理员联系以了解详情。"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新消息"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"打开短信应用查看"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"部分功能可能会受到限制"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string> <string name="app_info" msgid="6856026610594615344">"应用信息"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"恢复出厂设置即可正常使用此设备"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"触摸即可了解详情。"</string> </resources> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index c52d84371178..64de938faff0 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"工作模式已關閉"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"允許使用應用程式、背景同步及相關功能的工作設定檔。"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"開啟"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"已停用「%1$s」"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"「%1$s」管理員已停用此套件。請與管理員聯絡以瞭解詳情。"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新的訊息"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"開啟短訊應用程式查看內容"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"部分功能可能會受到限制"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string> <string name="app_info" msgid="6856026610594615344">"應用程式資料"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"將此裝置回復至原廠設定,方可正常使用"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸以瞭解詳情。"</string> </resources> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 8ff0fed42aaf..756c52d62d07 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Work 模式已關閉"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"啟用 Work 設定檔,包括應用程式、背景同步處理和相關功能。"</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"開啟"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"已由「%1$s」停用"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"這個套件已由「%1$s」管理員停用。請與對方聯絡以瞭解詳情。"</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"您有新訊息"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"開啟簡訊應用程式來查看內容"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"部分功能可能受到鎖定"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"取消固定"</string> <string name="app_info" msgid="6856026610594615344">"應用程式資訊"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"恢復原廠設定即可正常使用這個裝置"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"輕觸即可瞭解詳情。"</string> </resources> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index fe2c8a61c8cd..6ff550b7e2a8 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1549,8 +1549,6 @@ <string name="work_mode_off_title" msgid="8954725060677558855">"Imodi yomsebenzi IVALIWE"</string> <string name="work_mode_off_message" msgid="3286169091278094476">"Vumela iphrofayela yomsebenzi ukuze isebenze, efaka izinhlelo zokusebenza, ukuvumelanisa kwangemuva, nezici ezisondelene."</string> <string name="work_mode_turn_on" msgid="2062544985670564875">"Vula"</string> - <string name="suspended_package_title" msgid="3408150347778524435">"I-%1$s ikhutshaziwe"</string> - <string name="suspended_package_message" msgid="6341091587106868601">"Ikhutshazwe umlawuli we-%1$s. Xhumana nabo ukuze ufunde kabanzi."</string> <string name="new_sms_notification_title" msgid="8442817549127555977">"Unemilayezo emisha"</string> <string name="new_sms_notification_content" msgid="7002938807812083463">"Vula uhlelo lokusebenza lwe-SMS ukuze ubuke"</string> <string name="user_encrypted_title" msgid="9054897468831672082">"Okunye ukusebenza kungakhawulelwe"</string> @@ -1564,6 +1562,7 @@ <string name="unpin_target" msgid="3556545602439143442">"Susa ukuphina"</string> <string name="app_info" msgid="6856026610594615344">"Ulwazi lohlelo lokusebenza"</string> <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="audit_safemode_notification" msgid="6351827251856877200">"Setha kabusha ngokwefekthri ukuze usebenzise le divayisi ngokuvamile"</string> + <!-- no translation found for audit_safemode_notification (6416076898350685856) --> + <skip /> <string name="audit_safemode_notification_details" msgid="1860601176690176413">"Thinta ukuze ufunde kabanzi."</string> </resources> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 50c7bfbd0d0f..a52c4e5ffbf4 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5876,6 +5876,12 @@ i </attr> <!-- sets the Miter limit for a stroked path --> <attr name="strokeMiterLimit" format="float"/> + <!-- sets the fillType for a path. It is the same as SVG's "fill-rule" properties. + For more details, see https://www.w3.org/TR/SVG/painting.html#FillRuleProperty --> + <attr name="fillType" format="enum"> + <enum name="nonZero" value="0"/> + <enum name="evenOdd" value="1"/> + </attr> </declare-styleable> <!-- Defines the clip path used in VectorDrawables. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 51cd0299b4f2..01b2c4715a49 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1860,6 +1860,10 @@ <item>-1</item> </integer-array> + <!-- When true, local displays that do not contain any of their own content will automatically + mirror the content of the default display. --> + <bool name="config_localDisplaysMirrorContent">true</bool> + <!-- When true use the linux /dev/input/event subsystem to detect the switch changes on the headphone/microphone jack. When false use the older uevent framework. --> <bool name="config_useDevInputEventForAudioJack">false</bool> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 2b0ef4266ee1..4e8740a52fb5 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2706,6 +2706,7 @@ <public type="attr" name="canRecord" /> <public type="attr" name="tunerCount" /> <public type="attr" name="nfcAntennaPositionDrawable" /> + <public type="attr" name="fillType" /> <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" /> <public type="style" name="Widget.Material.SeekBar.Discrete" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 17afd92b648a..5d083d7f43c7 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4188,10 +4188,6 @@ <string name="work_mode_off_message">Allow work profile to function, including apps, background sync, and related features.</string> <!-- Title for button to turn on work profile. [CHAR LIMIT=NONE] --> <string name="work_mode_turn_on">Turn on</string> - <!-- Title for dialog displayed when a packge is suspended by device admin. [CHAR LIMIT=30] --> - <string name="suspended_package_title">%1$s disabled</string> - <!-- Message for dialog displayed when a packge is suspended by device admin. [CHAR LIMIT=NONE] --> - <string name="suspended_package_message">Disabled by %1$s administrator. Contact them to learn more.</string> <!-- Notification title shown when new SMS/MMS is received while the device is locked [CHAR LIMIT=NONE] --> <string name="new_sms_notification_title">You have new messages</string> @@ -4229,7 +4225,7 @@ <string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string> <!-- Title of notification shown when device has been forced to safe mode after a security compromise. --> - <string name="audit_safemode_notification">Factory reset to use this device normally</string> + <string name="audit_safemode_notification">Factory reset to use this device without restrictions</string> <!-- Description of notification shown when device has been forced to safe mode after a security compromise. --> <string name="audit_safemode_notification_details">Touch to learn more.</string> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index a65a813da84b..e636bc09d2bd 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -993,7 +993,7 @@ please see styles_device_defaults.xml. </style> <style name="Widget.Material.SuggestionItem" parent="@android:style/TextAppearance.Material.Body1"> - <item name="textColor">#8a000000</item> <!-- alpha=.54, textColor=@color/black --> + <item name="textColor">?attr/textColorSecondary</item> <item name="drawablePadding">8dip</item> <item name="gravity">start|center_vertical</item> <item name="layout_gravity">start|center_vertical</item> @@ -1008,11 +1008,11 @@ please see styles_device_defaults.xml. </style> <style name="TextAppearance.Material.TextSuggestionHighlight" parent="Widget.Material.SuggestionItem"> - <item name="textColor">#de000000</item> <!-- alpha=.87, textColor=@color/black --> + <item name="textColor">?attr/textColorPrimary</item> </style> <style name="Widget.Material.SuggestionButton" parent="@android:style/TextAppearance.Material.Button"> - <item name="textColor">#de009688</item> <!-- alpha=.87, textColor=#009688 --> + <item name="textColor">?attr/colorAccent</item> <item name="drawablePadding">8dip</item> <item name="gravity">start|center_vertical</item> <item name="layout_gravity">start|center_vertical</item> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 14707413c4dc..f01cce320b08 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -306,6 +306,7 @@ <java-symbol type="bool" name="config_freeformWindowManagement" /> <java-symbol type="bool" name="config_supportsMultiWindow" /> <java-symbol type="bool" name="config_guestUserEphemeral" /> + <java-symbol type="bool" name="config_localDisplaysMirrorContent" /> <java-symbol type="string" name="config_defaultPictureInPictureBounds" /> <java-symbol type="string" name="config_centeredPictureInPictureBounds" /> <java-symbol type="string" name="config_pictureInPictureBoundsInRecents" /> @@ -2507,8 +2508,6 @@ <java-symbol type="string" name="work_mode_off_title" /> <java-symbol type="string" name="work_mode_off_message" /> <java-symbol type="string" name="work_mode_turn_on" /> - <java-symbol type="string" name="suspended_package_title" /> - <java-symbol type="string" name="suspended_package_message" /> <!-- New SMS notification while phone is locked. --> <java-symbol type="string" name="new_sms_notification_title" /> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index 5970a22953b6..a361eda8ae75 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -223,6 +223,7 @@ please see themes_device_defaults.xml. <item name="textSelectHandleWindowStyle">@style/Widget.Material.TextSelectHandle</item> <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item_material</item> <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container_material</item> + <item name="textEditSuggestionHighlightStyle">@style/TextAppearance.Material.TextSuggestionHighlight</item> <item name="textCursorDrawable">@drawable/text_cursor_material</item> <!-- Widget styles --> diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml index cf7978c12bfe..c02a01a364bc 100644 --- a/core/res/res/xml/sms_short_codes.xml +++ b/core/res/res/xml/sms_short_codes.xml @@ -102,7 +102,7 @@ <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU: http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf, visual voicemail code for EE: 887 --> - <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|887|83669|34664|40406" /> + <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406" /> <!-- Georgia: 4 digits, known premium codes listed --> <shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" /> @@ -214,7 +214,7 @@ <!-- USA: 5-6 digits (premium codes from https://www.premiumsmsrefunds.com/ShortCodes.htm), visual voicemail code for T-Mobile: 122 --> - <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:567|578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" free="122|87902" /> + <shortcode country="us" pattern="\\d{5,6}" premium="20433|21(?:344|472)|22715|23(?:333|847)|24(?:15|28)0|25209|27(?:449|606|663)|28498|305(?:00|83)|32(?:340|941)|33(?:166|786|849)|34746|35(?:182|564)|37975|38(?:135|146|254)|41(?:366|463)|42335|43(?:355|500)|44(?:578|711|811)|45814|46(?:157|173|327)|46666|47553|48(?:221|277|669)|50(?:844|920)|51(?:062|368)|52944|54(?:723|892)|55928|56483|57370|59(?:182|187|252|342)|60339|61(?:266|982)|62478|64(?:219|898)|65(?:108|500)|69(?:208|388)|70877|71851|72(?:078|087|465)|73(?:288|588|882|909|997)|74(?:034|332|815)|76426|79213|81946|83177|84(?:103|685)|85797|86(?:234|236|666)|89616|90(?:715|842|938)|91(?:362|958)|94719|95297|96(?:040|666|835|969)|97(?:142|294|688)|99(?:689|796|807)" standard="44567" free="122|87902" /> <!-- Vietnam --> <shortcode country="vn" free="5001" /> diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index a72397710ef5..9074f8a97132 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -17,8 +17,8 @@ package android.net; import static android.net.NetworkStats.ROAMING_ALL; -import static android.net.NetworkStats.ROAMING_DEFAULT; -import static android.net.NetworkStats.ROAMING_ROAMING; +import static android.net.NetworkStats.ROAMING_NO; +import static android.net.NetworkStats.ROAMING_YES; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; import static android.net.NetworkStats.SET_DBG_VPN_IN; @@ -46,57 +46,57 @@ public class NetworkStatsTest extends TestCase { public void testFindIndex() throws Exception { final NetworkStats stats = new NetworkStats(TEST_START, 4) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L, 0L, 10) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 1024L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 1024L, 8L, 11) - .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 1024L, 8L, 12) - .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 1024L, 8L, + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES, 1024L, 8L, 1024L, 8L, 12); - assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING)); - assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT)); - assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT)); - assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT)); - assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT)); + assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES)); + assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO)); + assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO)); + assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO)); + assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, ROAMING_NO)); } public void testFindIndexHinted() { final NetworkStats stats = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L, 0L, 10) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 1024L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 1024L, 8L, 11) - .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 1024L, 8L, 12) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 1024L, 8L, 0L, 0L, 10) - .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 0L, 0L, 1024L, + .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 0L, 0L, 1024L, 8L, 11) - .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 1024L, 8L, 12) - .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 1024L, 8L, + .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_YES, 1024L, 8L, 1024L, 8L, 12); // verify that we correctly find across regardless of hinting for (int hint = 0; hint < stats.size(); hint++) { assertEquals(0, stats.findIndexHinted(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, - ROAMING_DEFAULT, hint)); + ROAMING_NO, hint)); assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, - ROAMING_DEFAULT, hint)); + ROAMING_NO, hint)); assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, - ROAMING_DEFAULT, hint)); + ROAMING_NO, hint)); assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, - ROAMING_DEFAULT, hint)); + ROAMING_NO, hint)); assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, - ROAMING_DEFAULT, hint)); + ROAMING_NO, hint)); assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - ROAMING_DEFAULT, hint)); + ROAMING_NO, hint)); assertEquals(6, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, - ROAMING_ROAMING, hint)); + ROAMING_YES, hint)); assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, - ROAMING_DEFAULT, hint)); + ROAMING_NO, hint)); } } @@ -106,41 +106,41 @@ public class NetworkStatsTest extends TestCase { assertEquals(0, stats.size()); assertEquals(3, stats.internalSize()); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L, 2L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L, 2L, 3); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2L, 2L, 2L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2L, 2L, 2L, 2L, 4); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 3L, 3L, 2L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 3L, 3L, 2L, 2L, 5); assertEquals(3, stats.size()); assertEquals(3, stats.internalSize()); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 4L, 40L, 4L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L, 40L, 4L, 40L, 7); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 5L, 50L, 4L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L, 50L, 4L, 40L, 8); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 6L, 60L, 5L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L, 60L, 5L, 50L, 10); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 7L, 70L, 5L, + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L, 70L, 5L, 50L, 11); assertEquals(7, stats.size()); assertTrue(stats.internalSize() >= 7); - assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L, + assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L, 2L, 3); - assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2L, 2L, + assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2L, 2L, 2L, 2L, 4); - assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 3L, 3L, + assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 3L, 3L, 2L, 2L, 5); - assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 4L, + assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4L, 40L, 4L, 40L, 7); - assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 5L, + assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 5L, 50L, 4L, 40L, 8); - assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 6L, + assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_NO, 6L, 60L, 5L, 50L, 10); - assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 7L, + assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_YES, 7L, 70L, 5L, 50L, 11); } @@ -152,19 +152,19 @@ public class NetworkStatsTest extends TestCase { stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L, -128L, -1L, -1); - assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 384L, 3L, + assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, ROAMING_NO, 384L, 3L, 128L, 1L, 9); - assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, ROAMING_DEFAULT, 128L, 1L, 128L, + assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, ROAMING_NO, 128L, 1L, 128L, 1L, 2); // now try combining that should create row stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 1L, + assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 1L, 128L, 1L, 3); stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 256L, 2L, + assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_NO, 256L, 2L, 256L, 2L, 6); } @@ -180,9 +180,9 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // identical data should result in zero delta - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, 0L, 0); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, 0L, 0); } @@ -198,9 +198,9 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // expect delta between measurements - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L, 2L, + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 1L, 2L, 1L, 4); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 3L, 1L, 4L, + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 3L, 1L, 4L, 1L, 8); } @@ -217,11 +217,11 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // its okay to have new rows - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, 0L, 0); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, 0L, 0); - assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 1024L, 8L, 20); } @@ -237,7 +237,7 @@ public class NetworkStatsTest extends TestCase { // should silently drop omitted rows assertEquals(1, result.size()); - assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, + assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1L, 2L, 3L, 4L, 0); assertEquals(4L, result.getTotalBytes()); } @@ -264,11 +264,11 @@ public class NetworkStatsTest extends TestCase { assertEquals(64L, uidTag.getTotalBytes()); final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L, 0L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_YES, 32L, 0L, 0L, 0L, 0L); assertEquals(96L, uidRoaming.getTotalBytes()); } @@ -283,11 +283,11 @@ public class NetworkStatsTest extends TestCase { public void testGroupedByIfaceAll() throws Exception { final NetworkStats uidStats = new NetworkStats(TEST_START, 3) - .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, 2L, + .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 2L, 20L) - .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 2L, 20L) - .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L, 2L, + .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, ROAMING_YES, 128L, 8L, 0L, 2L, 20L); final NetworkStats grouped = uidStats.groupedByIface(); @@ -300,19 +300,19 @@ public class NetworkStatsTest extends TestCase { public void testGroupedByIface() throws Exception { final NetworkStats uidStats = new NetworkStats(TEST_START, 7) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 2L, 20L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, 0L, + .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 4L, 0L, 0L, + .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 4L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L, 0L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 8L, 0L, 0L, 0L); final NetworkStats grouped = uidStats.groupedByIface(); @@ -328,49 +328,49 @@ public class NetworkStatsTest extends TestCase { public void testAddAllValues() { final NetworkStats first = new NetworkStats(TEST_START, 5) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L, + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 32L, 0L, 0L, 0L, 0L); final NetworkStats second = new NetworkStats(TEST_START, 2) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, + .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L, + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 32L, 0L, 0L, 0L, 0L); first.combineAllValues(second); assertEquals(4, first.size()); - assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 64L, 0L, 0L, + assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 64L, 0L, 0L, 0L, 0L); - assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, + assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L); - assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 64L, 0L, + assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_YES, 64L, 0L, 0L, 0L, 0L); - assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, + assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, 32L, 0L, 0L, 0L, 0L); } public void testGetTotal() { final NetworkStats stats = new NetworkStats(TEST_START, 7) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 2L, 20L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, 0L, + .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 4L, 0L, 0L, + .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 4L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L, 0L, + .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L, + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 8L, 0L, 0L, 0L); assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L); @@ -396,9 +396,9 @@ public class NetworkStatsTest extends TestCase { final NetworkStats after = before.withoutUids(new int[] { 100 }); assertEquals(6, before.size()); assertEquals(2, after.size()); - assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, + assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 8L, 0L, 0L, 0L); - assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L, + assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_NO, 128L, 8L, 0L, 0L, 0L); } @@ -457,53 +457,53 @@ public class NetworkStatsTest extends TestCase { assertEquals(21, delta.size()); // tunIface and TEST_IFACE entries are not changed. - assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 39605L, 46L, 12259L, 55L, 0L); - assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, + assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, 0L, 0L); - assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_NO, 72667L, 197L, 43909L, 241L, 0L); - assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, + assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 9297L, 17L, 4128L, 21L, 0L); - assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, 4983L, 10L, 1801L, 12L, 0L); - assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, + assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, 0L, 0L); - assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, ROAMING_DEFAULT, + assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO, 21691L, 41L, 13820L, 51L, 0L); - assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, ROAMING_DEFAULT, 1281L, + assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO, 1281L, 2L, 665L, 2L, 0L); - assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1685L, 5L, + assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1685L, 5L, 2070L, 6L, 0L); // Existing underlying Iface entries are updated - assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_NO, 44783L, 54L, 13829L, 60L, 0L); - assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, + assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, 0L, 0L); // VPN underlying Iface entries are updated - assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_NO, 28304L, 27L, 1719L, 12L, 0L); - assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, + assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 0L, 0L, 0L, 0L, 0L); // New entries are added for new application's underlying Iface traffic - assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_NO, 72667L, 197L, 41872L, 219L, 0L); - assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 9297L, 17L, 3936, 19L, 0L); - assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_DEFAULT, + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_NO, 21691L, 41L, 13179L, 46L, 0L); - assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_DEFAULT, + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_NO, 1281L, 2L, 634L, 1L, 0L); // New entries are added for debug purpose - assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT, + assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, 39605L, 46L, 11690, 49, 0); - assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT, + assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, 81964, 214, 45808, 238, 0); - assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT, + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, ROAMING_NO, 4983, 10, 1717, 10, 0); assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL, 126552, 270, 59215, 297, 0); diff --git a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java index cbf17a43dbc6..ec8cd71accbe 100644 --- a/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java +++ b/core/tests/coretests/src/android/print/IPrintManagerParametersTest.java @@ -37,6 +37,8 @@ import android.print.mockservice.PrintServiceCallbacks; import android.print.mockservice.PrinterDiscoverySessionCallbacks; import android.print.mockservice.StubbablePrinterDiscoverySession; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.MediumTest; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -253,6 +255,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.getPrintJobInfo */ + @LargeTest public void testGetPrintJobInfo() throws Exception { startPrinting(); @@ -274,6 +277,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.getPrintJobInfos */ + @LargeTest public void testGetPrintJobInfos() throws Exception { startPrinting(); @@ -301,6 +305,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.print */ + @LargeTest public void testPrint() throws Exception { final String name = "dummy print job"; @@ -354,6 +359,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.cancelPrintJob */ + @LargeTest public void testCancelPrintJob() throws Exception { startPrinting(); @@ -377,6 +383,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.restartPrintJob */ + @LargeTest public void testRestartPrintJob() throws Exception { startPrinting(); @@ -399,6 +406,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.addPrintJobStateChangeListener */ + @MediumTest public void testAddPrintJobStateChangeListener() throws Exception { final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener(); @@ -424,6 +432,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.removePrintJobStateChangeListener */ + @MediumTest public void testRemovePrintJobStateChangeListener() throws Exception { final IPrintJobStateChangeListener listener = createMockIPrintJobStateChangeListener(); @@ -447,6 +456,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.addPrintServicesChangeListener */ + @MediumTest public void testAddPrintServicesChangeListener() throws Exception { final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener(); @@ -465,6 +475,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.removePrintServicesChangeListener */ + @MediumTest public void testRemovePrintServicesChangeListener() throws Exception { final IPrintServicesChangeListener listener = createMockIPrintServicesChangeListener(); @@ -488,6 +499,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.getPrintServices */ + @MediumTest public void testGetPrintServices() throws Exception { List<PrintServiceInfo> printServices = mIPrintManager.getPrintServices( PrintManager.ALL_SERVICES, mUserId); @@ -509,6 +521,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.setPrintServiceEnabled */ + @MediumTest public void testSetPrintServiceEnabled() throws Exception { final ComponentName printService = mIPrintManager.getPrintServices( PrintManager.ALL_SERVICES, mUserId).get(0).getComponentName(); @@ -548,6 +561,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.createPrinterDiscoverySession */ + @MediumTest public void testCreatePrinterDiscoverySession() throws Exception { final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver(); @@ -573,6 +587,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.startPrinterDiscovery */ + @LargeTest public void testStartPrinterDiscovery() throws Exception { startPrinting(); @@ -615,6 +630,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.stopPrinterDiscovery */ + @MediumTest public void testStopPrinterDiscovery() throws Exception { final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver(); @@ -638,6 +654,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.validatePrinters */ + @LargeTest public void testValidatePrinters() throws Exception { startPrinting(); @@ -678,6 +695,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.startPrinterStateTracking */ + @LargeTest public void testStartPrinterStateTracking() throws Exception { startPrinting(); @@ -699,6 +717,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.getCustomPrinterIcon */ + @LargeTest public void testGetCustomPrinterIcon() throws Exception { startPrinting(); @@ -720,6 +739,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.stopPrinterStateTracking */ + @LargeTest public void testStopPrinterStateTracking() throws Exception { startPrinting(); @@ -746,6 +766,7 @@ public class IPrintManagerParametersTest extends BasePrintTest { /** * test IPrintManager.destroyPrinterDiscoverySession */ + @MediumTest public void testDestroyPrinterDiscoverySession() throws Exception { final IPrinterDiscoveryObserver listener = createMockIPrinterDiscoveryObserver(); diff --git a/core/tests/coretests/src/android/transition/AutoTransitionTest.java b/core/tests/coretests/src/android/transition/AutoTransitionTest.java new file mode 100644 index 000000000000..834fb7aa72a5 --- /dev/null +++ b/core/tests/coretests/src/android/transition/AutoTransitionTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 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.transition; + +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +public class AutoTransitionTest { + @Test + @SmallTest + public void testFadeOutMoveFadeIn() throws Throwable { + AutoTransition autoTransition = new AutoTransition(); + assertEquals(3, autoTransition.getTransitionCount()); + Transition fadeOut = autoTransition.getTransitionAt(0); + assertNotNull(fadeOut); + assertTrue(fadeOut instanceof Fade); + assertEquals(Visibility.MODE_OUT, ((Fade)fadeOut).getMode()); + + Transition move = autoTransition.getTransitionAt(1); + assertNotNull(move); + assertTrue(move instanceof ChangeBounds); + + Transition fadeIn = autoTransition.getTransitionAt(2); + assertNotNull(fadeIn); + assertTrue(fadeIn instanceof Fade); + assertEquals(Visibility.MODE_IN, ((Fade)fadeIn).getMode()); + + assertEquals(TransitionSet.ORDERING_SEQUENTIAL, autoTransition.getOrdering()); + } +} diff --git a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java index 3d8fe69d1bb7..a37abf185097 100644 --- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java +++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java @@ -32,6 +32,8 @@ import com.android.frameworks.coretests.R; /** * SuggestionsPopupWindowTest tests. + * + * TODO: Add tests for when there are no suggestions */ public class SuggestionsPopupWindowTest extends ActivityInstrumentationTestCase2<TextViewActivity> { diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index 844eadbae692..4a4727fd891f 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -47,6 +47,8 @@ import com.android.frameworks.coretests.R; import android.support.test.espresso.action.EspressoKey; import android.test.ActivityInstrumentationTestCase2; import android.test.suitebuilder.annotation.SmallTest; +import android.text.Selection; +import android.text.Spannable; import android.view.KeyEvent; import static org.hamcrest.Matchers.anyOf; @@ -534,4 +536,68 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV .perform(dragHandle(textView, Handle.SELECTION_END, text.indexOf('i'))); onView(withId(R.id.textview)).check(hasSelection("hijk")); } + + @SmallTest + public void testSetSelectionAndActionMode() throws Exception { + final String text = "abc def"; + onView(withId(R.id.textview)).perform(click()); + onView(withId(R.id.textview)).perform(replaceText(text)); + + final TextView textView = (TextView) getActivity().findViewById(R.id.textview); + assertFloatingToolbarIsNotDisplayed(); + textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); + getInstrumentation().waitForIdleSync(); + sleepForFloatingToolbarPopup(); + // Don't automatically start action mode. + assertFloatingToolbarIsNotDisplayed(); + // Make sure that "Select All" is included in the selection action mode when the entire text + // is not selected. + onView(withId(R.id.textview)).perform(doubleClickOnTextAtIndex(text.indexOf('e'))); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + // Changing the selection range by API should not interrupt the selection action mode. + textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0, 3)); + getInstrumentation().waitForIdleSync(); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.selectAll)); + // Make sure that "Select All" is no longer included when the entire text is selected by + // API. + textView.post( + () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length())); + getInstrumentation().waitForIdleSync(); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + assertFloatingToolbarDoesNotContainItem( + getActivity().getString(com.android.internal.R.string.selectAll)); + // Make sure that shrinking the selection range to cursor (an empty range) by API + // terminates selection action mode and does not trigger the insertion action mode. + textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0)); + getInstrumentation().waitForIdleSync(); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsNotDisplayed(); + // Make sure that user click can trigger the insertion action mode. + onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.length())); + onHandleView(com.android.internal.R.id.insertion_handle).perform(click()); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + // Make sure that an existing insertion action mode keeps alive after the insertion point is + // moved by API. + textView.post(() -> Selection.setSelection((Spannable) textView.getText(), 0)); + getInstrumentation().waitForIdleSync(); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + assertFloatingToolbarDoesNotContainItem( + getActivity().getString(com.android.internal.R.string.copy)); + // Make sure that selection action mode is started after selection is created by API when + // insertion action mode is active. + textView.post( + () -> Selection.setSelection((Spannable) textView.getText(), 1, text.length())); + getInstrumentation().waitForIdleSync(); + sleepForFloatingToolbarPopup(); + assertFloatingToolbarIsDisplayed(); + assertFloatingToolbarContainsItem( + getActivity().getString(com.android.internal.R.string.copy)); + } } diff --git a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java index 12a75b824fb6..327f3fda3f34 100644 --- a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java +++ b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java @@ -16,7 +16,7 @@ package com.android.internal.net; -import static android.net.NetworkStats.ROAMING_DEFAULT; +import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; @@ -157,7 +157,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase { private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, int tag, long rxBytes, long txBytes) { - final int i = stats.findIndex(iface, uid, set, tag, ROAMING_DEFAULT); + final int i = stats.findIndex(iface, uid, set, tag, ROAMING_NO); final NetworkStats.Entry entry = stats.getValues(i, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected txBytes", txBytes, entry.txBytes); @@ -165,7 +165,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase { private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) { - final int i = stats.findIndex(iface, uid, set, tag, ROAMING_DEFAULT); + final int i = stats.findIndex(iface, uid, set, tag, ROAMING_NO); final NetworkStats.Entry entry = stats.getValues(i, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk index dc85046f518e..fd28f64db19e 100644 --- a/data/fonts/Android.mk +++ b/data/fonts/Android.mk @@ -105,4 +105,4 @@ FONTCHAIN_LINTER := frameworks/base/tools/fonts/fontchain_lint.py .PHONY: fontchain_lint fontchain_lint: $(FONTCHAIN_LINTER) $(TARGET_OUT)/etc/fonts.xml PYTHONPATH=$$PYTHONPATH:external/fonttools/Lib \ - python $(FONTCHAIN_LINTER) $(TARGET_OUT)
\ No newline at end of file + python $(FONTCHAIN_LINTER) $(TARGET_OUT) external/unicode diff --git a/graphics/java/android/graphics/AvoidXfermode.java b/graphics/java/android/graphics/AvoidXfermode.java index 48ee6fae3879..683c15702427 100644 --- a/graphics/java/android/graphics/AvoidXfermode.java +++ b/graphics/java/android/graphics/AvoidXfermode.java @@ -19,6 +19,8 @@ package android.graphics; /** * AvoidXfermode xfermode will draw the src everywhere except on top of the * opColor or, depending on the Mode, draw only on top of the opColor. + * + * @removed */ @Deprecated public class AvoidXfermode extends Xfermode { @@ -53,9 +55,5 @@ public class AvoidXfermode extends Xfermode { if (tolerance < 0 || tolerance > 255) { throw new IllegalArgumentException("tolerance must be 0..255"); } - native_instance = nativeCreate(opColor, tolerance, mode.nativeInt); } - - private static native long nativeCreate(int opColor, int tolerance, - int nativeMode); } diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java index d3124545ae84..3973f2ff428b 100644 --- a/graphics/java/android/graphics/Outline.java +++ b/graphics/java/android/graphics/Outline.java @@ -17,10 +17,13 @@ package android.graphics; import android.annotation.FloatRange; +import android.annotation.IntDef; import android.annotation.NonNull; -import android.annotation.Nullable; import android.graphics.drawable.Drawable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * Defines a simple shape, used for bounding graphical regions. * <p> @@ -32,13 +35,30 @@ import android.graphics.drawable.Drawable; * @see Drawable#getOutline(Outline) */ public final class Outline { - private static final float RADIUS_UNDEFINED = -1.0f; + private static final float RADIUS_UNDEFINED = Float.NEGATIVE_INFINITY; + + private static final int MODE_EMPTY = 0; + private static final int MODE_RECT = 1; + private static final int MODE_CONVEX_PATH = 2; /** @hide */ - public Path mPath; + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = false, + value = { + MODE_EMPTY, + MODE_RECT, + MODE_CONVEX_PATH, + }) + public @interface Mode {} + + @Mode + private int mMode = MODE_EMPTY; /** @hide */ - public Rect mRect; + public final Path mPath = new Path(); + + /** @hide */ + public final Rect mRect = new Rect(); /** @hide */ public float mRadius = RADIUS_UNDEFINED; /** @hide */ @@ -63,8 +83,9 @@ public final class Outline { * @see #isEmpty() */ public void setEmpty() { - mPath = null; - mRect = null; + mMode = MODE_EMPTY; + mPath.rewind(); + mRect.setEmpty(); mRadius = RADIUS_UNDEFINED; } @@ -77,7 +98,7 @@ public final class Outline { * @see #setEmpty() */ public boolean isEmpty() { - return mRect == null && mPath == null; + return mMode == MODE_EMPTY; } @@ -90,7 +111,7 @@ public final class Outline { * @see {@link android.view.View#setClipToOutline(boolean)} */ public boolean canClip() { - return !isEmpty() && mRect != null; + return mMode != MODE_CONVEX_PATH; } /** @@ -122,19 +143,9 @@ public final class Outline { * @param src Source outline to copy from. */ public void set(@NonNull Outline src) { - if (src.mPath != null) { - if (mPath == null) { - mPath = new Path(); - } - mPath.set(src.mPath); - mRect = null; - } - if (src.mRect != null) { - if (mRect == null) { - mRect = new Rect(); - } - mRect.set(src.mRect); - } + mMode = src.mMode; + mPath.set(src.mPath); + mRect.set(src.mRect); mRadius = src.mRadius; mAlpha = src.mAlpha; } @@ -165,10 +176,10 @@ public final class Outline { return; } - if (mRect == null) mRect = new Rect(); + mMode = MODE_RECT; mRect.set(left, top, right, bottom); mRadius = radius; - mPath = null; + mPath.rewind(); } /** @@ -188,7 +199,7 @@ public final class Outline { * bounds, or {@code false} if no outline bounds are set */ public boolean getRect(@NonNull Rect outRect) { - if (mRect == null) { + if (mMode != MODE_RECT) { return false; } outRect.set(mRect); @@ -196,11 +207,11 @@ public final class Outline { } /** - * Returns the rounded rect radius, if set, or {@code -1} if a path has + * Returns the rounded rect radius, if set, or a value less than 0 if a path has * been set via {@link #setConvexPath(Path)}. A return value of {@code 0} * indicates a non-rounded rect. * - * @return the rounded rect radius or {@code -1} + * @return the rounded rect radius, or value < 0 */ public float getRadius() { return mRadius; @@ -221,10 +232,10 @@ public final class Outline { return; } - if (mPath == null) mPath = new Path(); - mPath.reset(); + mMode = MODE_CONVEX_PATH; + mPath.rewind(); mPath.addOval(left, top, right, bottom, Path.Direction.CW); - mRect = null; + mRect.setEmpty(); mRadius = RADIUS_UNDEFINED; } @@ -248,10 +259,10 @@ public final class Outline { if (!convexPath.isConvex()) { throw new IllegalArgumentException("path must be convex"); } - if (mPath == null) mPath = new Path(); + mMode = MODE_CONVEX_PATH; mPath.set(convexPath); - mRect = null; + mRect.setEmpty(); mRadius = RADIUS_UNDEFINED; } @@ -259,9 +270,9 @@ public final class Outline { * Offsets the Outline by (dx,dy) */ public void offset(int dx, int dy) { - if (mRect != null) { + if (mMode == MODE_RECT) { mRect.offset(dx, dy); - } else if (mPath != null) { + } else if (mMode == MODE_CONVEX_PATH) { mPath.offset(dx, dy); } } diff --git a/graphics/java/android/graphics/PixelXorXfermode.java b/graphics/java/android/graphics/PixelXorXfermode.java index 0080e6536d77..27884e07ecfb 100644 --- a/graphics/java/android/graphics/PixelXorXfermode.java +++ b/graphics/java/android/graphics/PixelXorXfermode.java @@ -17,17 +17,11 @@ package android.graphics; /** - * PixelXorXfermode implements a simple pixel xor (op ^ src ^ dst). - * This transformation does not follow premultiplied conventions, therefore - * this mode *always* returns an opaque color (alpha == 255). Thus it is - * not really usefull for operating on blended colors. + * @removed */ @Deprecated public class PixelXorXfermode extends Xfermode { public PixelXorXfermode(int opColor) { - native_instance = nativeCreate(opColor); } - - private static native long nativeCreate(int opColor); } diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java index 0cde0b990456..93ef3f0c5f9b 100644 --- a/graphics/java/android/graphics/Rect.java +++ b/graphics/java/android/graphics/Rect.java @@ -30,6 +30,11 @@ import java.util.regex.Pattern; * These fields can be accessed directly. Use width() and height() to retrieve * the rectangle's width and height. Note: most methods do not check to see that * the coordinates are sorted correctly (i.e. left <= right and top <= bottom). + * <p> + * Note that the right and bottom coordinates are exclusive. This means a Rect + * being drawn untransformed onto a {@link android.graphics.Canvas} will draw + * into the column and row described by its left and top coordinates, but not + * those of its bottom and right. */ public final class Rect implements Parcelable { public int left; diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 39ea2054ce6b..ae9ebc762d76 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -27,6 +27,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityThread; import android.app.Application; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -156,7 +157,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false; /** Local, mutable animator set. */ - private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorRT(this); + private VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimatorUI(this); /** * The resources against which this drawable was created. Used to attempt @@ -230,7 +231,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mAnimatedVectorState.getChangingConfigurations(); } @@ -449,7 +450,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } private static class AnimatedVectorDrawableState extends ConstantState { - int mChangingConfigurations; + @Config int mChangingConfigurations; VectorDrawable mVectorDrawable; /** Animators that require a theme before inflation. */ @@ -513,7 +514,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations; } diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index bffbc751ee83..9d8ede048924 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -17,6 +17,7 @@ package android.graphics.drawable; import android.annotation.NonNull; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -454,7 +455,7 @@ public class BitmapDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mBitmapState.getChangingConfigurations(); } @@ -910,7 +911,7 @@ public class BitmapDrawable extends Drawable { int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; boolean mAutoMirrored = false; - int mChangingConfigurations; + @Config int mChangingConfigurations; boolean mRebuildShader; BitmapState(Bitmap bitmap) { @@ -958,7 +959,7 @@ public class BitmapDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | (mTint != null ? mTint.getChangingConfigurations() : 0); } diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index 5ad31f75f20a..7524cac47491 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -18,6 +18,7 @@ package android.graphics.drawable; import android.annotation.ColorInt; import android.annotation.NonNull; +import android.content.pm.ActivityInfo.Config; import android.graphics.*; import android.graphics.PorterDuff.Mode; import android.content.res.ColorStateList; @@ -70,7 +71,7 @@ public class ColorDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mColorState.getChangingConfigurations(); } @@ -292,7 +293,7 @@ public class ColorDrawable extends Drawable { int mBaseColor; // base color, independent of setAlpha() @ViewDebug.ExportedProperty int mUseColor; // basecolor modulated by setAlpha() - int mChangingConfigurations; + @Config int mChangingConfigurations; ColorStateList mTint = null; Mode mTintMode = DEFAULT_TINT_MODE; @@ -326,7 +327,7 @@ public class ColorDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | (mTint != null ? mTint.getChangingConfigurations() : 0); } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index f106c680bbc8..391598447573 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -19,6 +19,7 @@ package android.graphics.drawable; import android.annotation.ColorInt; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -134,7 +135,7 @@ public abstract class Drawable { private int[] mStateSet = StateSet.WILD_CARD; private int mLevel = 0; - private int mChangingConfigurations = 0; + private @Config int mChangingConfigurations = 0; private Rect mBounds = ZERO_BOUNDS_RECT; // lazily becomes a new Rect() private WeakReference<Callback> mCallback = null; private boolean mVisible = true; @@ -249,7 +250,7 @@ public abstract class Drawable { * * @see android.content.pm.ActivityInfo */ - public void setChangingConfigurations(int configs) { + public void setChangingConfigurations(@Config int configs) { mChangingConfigurations = configs; } @@ -266,7 +267,7 @@ public abstract class Drawable { * * @see android.content.pm.ActivityInfo */ - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations; } @@ -1294,7 +1295,7 @@ public abstract class Drawable { * Return a bit mask of configuration changes that will impact * this drawable (and thus require completely reloading it). */ - public abstract int getChangingConfigurations(); + public abstract @Config int getChangingConfigurations(); /** * @return Total pixel count diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index a91d1f0ac780..42f48633eacb 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -17,6 +17,7 @@ package android.graphics.drawable; import android.annotation.NonNull; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -87,7 +88,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mDrawableContainerState.getChangingConfigurations(); } @@ -649,8 +650,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { Resources mSourceRes; int mDensity = DisplayMetrics.DENSITY_DEFAULT; - int mChangingConfigurations; - int mChildrenChangingConfigurations; + @Config int mChangingConfigurations; + @Config int mChildrenChangingConfigurations; SparseArray<ConstantState> mDrawableFutures; Drawable[] mDrawables; @@ -781,7 +782,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | mChildrenChangingConfigurations; } diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java index 4df2d57f2574..5abfc54bfce3 100644 --- a/graphics/java/android/graphics/drawable/DrawableWrapper.java +++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java @@ -23,6 +23,7 @@ import org.xmlpull.v1.XmlPullParserException; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -229,7 +230,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | (mState != null ? mState.getChangingConfigurations() : 0) | mDrawable.getChangingConfigurations(); @@ -444,7 +445,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb abstract static class DrawableWrapperState extends Drawable.ConstantState { private int[] mThemeAttrs; - int mChangingConfigurations; + @Config int mChangingConfigurations; int mDensity = DisplayMetrics.DENSITY_DEFAULT; Drawable.ConstantState mDrawableState; @@ -524,7 +525,7 @@ public abstract class DrawableWrapper extends Drawable implements Drawable.Callb public abstract Drawable newDrawable(@Nullable Resources res); @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | (mDrawableState != null ? mDrawableState.getChangingConfigurations() : 0); } diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 7b1e62a6390d..bcc354c5b736 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -20,6 +20,7 @@ import android.annotation.ColorInt; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -958,7 +959,7 @@ public class GradientDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mGradientState.getChangingConfigurations(); } @@ -1734,7 +1735,7 @@ public class GradientDrawable extends Drawable { } final static class GradientState extends ConstantState { - public int mChangingConfigurations; + public @Config int mChangingConfigurations; public @Shape int mShape = RECTANGLE; public @GradientType int mGradient = LINEAR_GRADIENT; public int mAngle = 0; @@ -1962,7 +1963,7 @@ public class GradientDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | (mStrokeColors != null ? mStrokeColors.getChangingConfigurations() : 0) | (mSolidColors != null ? mSolidColors.getChangingConfigurations() : 0) diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index d142f9502d91..d9c3a02f02d7 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -18,6 +18,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -88,7 +89,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { * @see #getLayerInsetStart(int) * @see #getLayerInsetEnd(int) */ - public static final int UNDEFINED_INSET = Integer.MIN_VALUE; + public static final int INSET_UNDEFINED = Integer.MIN_VALUE; LayerState mLayerState; @@ -758,7 +759,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { * @attr ref android.R.styleable#LayerDrawableItem_bottom */ public void setLayerInset(int index, int l, int t, int r, int b) { - setLayerInsetInternal(index, l, t, r, b, UNDEFINED_INSET, UNDEFINED_INSET); + setLayerInsetInternal(index, l, t, r, b, INSET_UNDEFINED, INSET_UNDEFINED); } /** @@ -873,7 +874,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { /** * @param index the index of the layer * @return the number of pixels to inset from the start bound, or - * {@link #UNDEFINED_INSET} if not specified + * {@link #INSET_UNDEFINED} if not specified * @attr ref android.R.styleable#LayerDrawableItem_start */ public int getLayerInsetStart(int index) { @@ -884,7 +885,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { /** * @param index the index of the layer to adjust * @param e number of pixels to inset from the end bound, or - * {@link #UNDEFINED_INSET} if not specified + * {@link #INSET_UNDEFINED} if not specified * @attr ref android.R.styleable#LayerDrawableItem_end */ public void setLayerInsetEnd(int index, int e) { @@ -971,7 +972,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mLayerState.getChangingConfigurations(); } @@ -1502,8 +1503,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { // insets. final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS; final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE; - final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL; - final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR; + final int insetL = insetRtlL == INSET_UNDEFINED ? r.mInsetL : insetRtlL; + final int insetR = insetRtlR == INSET_UNDEFINED ? r.mInsetR : insetRtlR; // Establish containing region based on aggregate padding and // requested insets for the current layer. @@ -1601,8 +1602,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { // left / right ones. final int insetRtlL = isLayoutRtl ? r.mInsetE : r.mInsetS; final int insetRtlR = isLayoutRtl ? r.mInsetS : r.mInsetE; - final int insetL = insetRtlL == UNDEFINED_INSET ? r.mInsetL : insetRtlL; - final int insetR = insetRtlR == UNDEFINED_INSET ? r.mInsetR : insetRtlR; + final int insetL = insetRtlL == INSET_UNDEFINED ? r.mInsetL : insetRtlL; + final int insetR = insetRtlR == INSET_UNDEFINED ? r.mInsetR : insetRtlR; // Don't apply padding and insets for children that don't have // an intrinsic dimension. @@ -1762,8 +1763,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { public int[] mThemeAttrs; public int mDensity = DisplayMetrics.DENSITY_DEFAULT; public int mInsetL, mInsetT, mInsetR, mInsetB; - public int mInsetS = UNDEFINED_INSET; - public int mInsetE = UNDEFINED_INSET; + public int mInsetS = INSET_UNDEFINED; + public int mInsetE = INSET_UNDEFINED; public int mWidth = -1; public int mHeight = -1; public int mGravity = Gravity.NO_GRAVITY; @@ -1832,10 +1833,10 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { mInsetT = Drawable.scaleFromDensity(mInsetT, sourceDensity, targetDensity, false); mInsetR = Drawable.scaleFromDensity(mInsetR, sourceDensity, targetDensity, false); mInsetB = Drawable.scaleFromDensity(mInsetB, sourceDensity, targetDensity, false); - if (mInsetS != UNDEFINED_INSET) { + if (mInsetS != INSET_UNDEFINED) { mInsetS = Drawable.scaleFromDensity(mInsetS, sourceDensity, targetDensity, false); } - if (mInsetE != UNDEFINED_INSET) { + if (mInsetE != INSET_UNDEFINED) { mInsetE = Drawable.scaleFromDensity(mInsetE, sourceDensity, targetDensity, false); } if (mWidth > 0) { @@ -1864,8 +1865,8 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { int mPaddingEnd = -1; int mOpacityOverride = PixelFormat.UNKNOWN; - int mChangingConfigurations; - int mChildrenChangingConfigurations; + @Config int mChangingConfigurations; + @Config int mChildrenChangingConfigurations; private boolean mHaveOpacity; private int mOpacity; @@ -1989,7 +1990,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | mChildrenChangingConfigurations; } diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index 681653967aa1..fd3b9b47fe1a 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -18,6 +18,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -260,7 +261,7 @@ public class NinePatchDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mNinePatchState.getChangingConfigurations(); } @@ -575,7 +576,7 @@ public class NinePatchDrawable extends Drawable { } final static class NinePatchState extends ConstantState { - int mChangingConfigurations; + @Config int mChangingConfigurations; // Values loaded during inflation. NinePatch mNinePatch = null; @@ -651,7 +652,7 @@ public class NinePatchDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | (mTint != null ? mTint.getChangingConfigurations() : 0); } diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index ee0861ae60f5..caf2e7a4cb4c 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -23,6 +23,7 @@ import org.xmlpull.v1.XmlPullParserException; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources.Theme; @@ -1033,7 +1034,7 @@ public class RippleDrawable extends LayerDrawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | (mColor != null ? mColor.getChangingConfigurations() : 0); } diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index 30b588e1b4b7..fe82a93cf5b5 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -16,6 +16,7 @@ package android.graphics.drawable; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; @@ -260,7 +261,7 @@ public class ShapeDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mShapeState.getChangingConfigurations(); } @@ -526,7 +527,7 @@ public class ShapeDrawable extends Drawable { */ final static class ShapeState extends ConstantState { int[] mThemeAttrs; - int mChangingConfigurations; + @Config int mChangingConfigurations; Paint mPaint; Shape mShape; ColorStateList mTint = null; @@ -571,7 +572,7 @@ public class ShapeDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | (mTint != null ? mTint.getChangingConfigurations() : 0); } diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java index e5c235efaba5..0122338a7255 100644 --- a/graphics/java/android/graphics/drawable/TransitionDrawable.java +++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java @@ -16,6 +16,7 @@ package android.graphics.drawable; +import android.content.pm.ActivityInfo.Config; import android.content.res.Resources; import android.graphics.Canvas; import android.os.SystemClock; @@ -259,7 +260,7 @@ public class TransitionDrawable extends LayerDrawable implements Drawable.Callba } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations; } } diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 44a91fefc4a0..bd069ffeddad 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -16,6 +16,7 @@ package android.graphics.drawable; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.ActivityInfo.Config; import android.content.res.ColorStateList; import android.content.res.ComplexColor; import android.content.res.GradientColor; @@ -686,7 +687,7 @@ public class VectorDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return super.getChangingConfigurations() | mVectorState.getChangingConfigurations(); } @@ -714,7 +715,7 @@ public class VectorDrawable extends Drawable { static class VectorDrawableState extends ConstantState { // Variables below need to be copied (deep copy if applicable) for mutation. int[] mThemeAttrs; - int mChangingConfigurations; + @Config int mChangingConfigurations; ColorStateList mTint = null; Mode mTintMode = DEFAULT_TINT_MODE; boolean mAutoMirrored; @@ -823,7 +824,7 @@ public class VectorDrawable extends Drawable { } @Override - public int getChangingConfigurations() { + public @Config int getChangingConfigurations() { return mChangingConfigurations | (mTint != null ? mTint.getChangingConfigurations() : 0); } @@ -923,7 +924,7 @@ public class VectorDrawable extends Drawable { // mLocalMatrix is updated based on the update of transformation information, // either parsed from the XML or by animation. - private int mChangingConfigurations; + private @Config int mChangingConfigurations; private int[] mThemeAttrs; private String mGroupName = null; @@ -1169,7 +1170,7 @@ public class VectorDrawable extends Drawable { protected PathParser.PathData mPathData = null; String mPathName; - int mChangingConfigurations; + @Config int mChangingConfigurations; public VPath() { // Empty constructor. @@ -1280,8 +1281,10 @@ public class VectorDrawable extends Drawable { private static final int STROKE_LINE_CAP_INDEX = 8; private static final int STROKE_LINE_JOIN_INDEX = 9; private static final int STROKE_MITER_LIMIT_INDEX = 10; - private static final int TOTAL_PROPERTY_COUNT = 11; + private static final int FILL_TYPE_INDEX = 11; + private static final int TOTAL_PROPERTY_COUNT = 12; + // Property map for animatable attributes. private final static HashMap<String, Integer> sPropertyMap = new HashMap<String, Integer> () { { @@ -1398,6 +1401,7 @@ public class VectorDrawable extends Drawable { int strokeLineCap = properties.getInt(STROKE_LINE_CAP_INDEX * 4); int strokeLineJoin = properties.getInt(STROKE_LINE_JOIN_INDEX * 4); float strokeMiterLimit = properties.getFloat(STROKE_MITER_LIMIT_INDEX * 4); + int fillType = properties.getInt(FILL_TYPE_INDEX * 4); Shader fillGradient = null; Shader strokeGradient = null; // Account for any configuration changes. @@ -1473,10 +1477,11 @@ public class VectorDrawable extends Drawable { R.styleable.VectorDrawablePath_trimPathOffset, trimPathOffset); trimPathStart = a.getFloat( R.styleable.VectorDrawablePath_trimPathStart, trimPathStart); + fillType = a.getInt(R.styleable.VectorDrawablePath_fillType, fillType); nUpdateFullPathProperties(mNativePtr, strokeWidth, strokeColor, strokeAlpha, fillColor, fillAlpha, trimPathStart, trimPathEnd, trimPathOffset, - strokeMiterLimit, strokeLineCap, strokeLineJoin); + strokeMiterLimit, strokeLineCap, strokeLineJoin, fillType); } @Override @@ -1644,7 +1649,7 @@ public class VectorDrawable extends Drawable { private static native void nUpdateFullPathProperties(long pathPtr, float strokeWidth, int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap, - int strokeLineJoin); + int strokeLineJoin, int fillType); private static native void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr); private static native void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr); diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index f6e3b5035be2..ca077389b629 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -255,6 +255,7 @@ LOCAL_SRC_FILES += \ ifeq (true, $(HWUI_NEW_OPS)) LOCAL_SRC_FILES += \ tests/unit/BakedOpDispatcherTests.cpp \ + tests/unit/BakedOpRendererTests.cpp \ tests/unit/BakedOpStateTests.cpp \ tests/unit/FrameBuilderTests.cpp \ tests/unit/LeakCheckTests.cpp \ diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp index da5eccaf1c12..bb3ea3fa6b54 100644 --- a/libs/hwui/BakedOpRenderer.cpp +++ b/libs/hwui/BakedOpRenderer.cpp @@ -40,6 +40,16 @@ OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t h void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) { LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); + // subtract repaintRect from region, since it will be regenerated + if (repaintRect.contains(0, 0, + offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight)) { + // repaint full layer, so throw away entire region + offscreenBuffer->region.clear(); + } else { + offscreenBuffer->region.subtractSelf(android::Rect(repaintRect.left, repaintRect.top, + repaintRect.right, repaintRect.bottom)); + } + mRenderTarget.offscreenBuffer = offscreenBuffer; // create and bind framebuffer diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 330dc2951ec9..eac9359beab3 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -92,6 +92,8 @@ public: */ bool init(); + bool isInitialized() { return mInitialized; } + /** * Flush the cache. * diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp index afe980712d81..f886dda86deb 100644 --- a/libs/hwui/ClipArea.cpp +++ b/libs/hwui/ClipArea.cpp @@ -41,6 +41,10 @@ Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform) { return transformedBounds; } +void ClipBase::dump() const { + ALOGD("mode %d" RECT_STRING, mode, RECT_ARGS(rect)); +} + /* * TransformedRectangle */ diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h index 479796db042a..1654eb8f02e4 100644 --- a/libs/hwui/ClipArea.h +++ b/libs/hwui/ClipArea.h @@ -106,6 +106,8 @@ struct ClipBase { // Bounds of the clipping area, used to define the scissor, and define which // portion of the stencil is updated/used Rect rect; + + void dump() const; }; struct ClipRect : ClipBase { diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp index fd5856a1c1de..50b21a40d7c3 100644 --- a/libs/hwui/FrameBuilder.cpp +++ b/libs/hwui/FrameBuilder.cpp @@ -646,7 +646,9 @@ static batchid_t textBatchId(const SkPaint& paint) { } void FrameBuilder::deferTextOp(const TextOp& op) { - BakedOpState* bakedState = tryBakeOpState(op); + BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct( + mAllocator, *mCanvasState.writableSnapshot(), op, + BakedOpState::StrokeBehavior::StyleDefined); if (!bakedState) return; // quick rejected batchid_t batchId = textBatchId(*(op.paint)); diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 45fc16cc3136..2799def16b98 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -676,8 +676,11 @@ void GlopBuilder::dump(const Glop& glop) { fill.skiaShaderData.skiaShaderType); ALOGD("Glop transform"); - glop.transform.modelView.dump("model view"); - glop.transform.canvas.dump("canvas"); + glop.transform.modelView.dump(" model view"); + glop.transform.canvas.dump(" canvas"); + ALOGD_IF(glop.transform.transformFlags, " transformFlags 0x%x", glop.transform.transformFlags); + + ALOGD_IF(glop.roundRectClipState, "Glop RRCS %p", glop.roundRectClipState); ALOGD("Glop blend %d %d", glop.blend.src, glop.blend.dst); ALOGD("Glop bounds " RECT_STRING, RECT_ARGS(glop.bounds)); diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 114347d94357..cdbbbab7730d 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -197,7 +197,12 @@ void Layer::generateTexture() { } void Layer::clearTexture() { - caches.textureState().unbindTexture(texture.mId); + // There's a rare possibility that Caches could have been destroyed already + // since this method is queued up as a task. + // Since this is a reset method, treat this as non-fatal. + if (caches.isInitialized()) { + caches.textureState().unbindTexture(texture.mId); + } texture.mId = 0; } diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp index c5af279653d9..e6a95ff177a4 100644 --- a/libs/hwui/LayerBuilder.cpp +++ b/libs/hwui/LayerBuilder.cpp @@ -349,8 +349,9 @@ void LayerBuilder::replayBakedOpsImpl(void* arg, } void LayerBuilder::dump() const { - ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p", - this, width, height, offscreenBuffer, beginLayerOp, renderNode); + ALOGD("LayerBuilder %p, %ux%u buffer %p, blo %p, rn %p (%s)", + this, width, height, offscreenBuffer, beginLayerOp, + renderNode, renderNode ? renderNode->getName() : "-"); for (const BatchBase* batch : mBatches) { batch->dump(); } diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index f0c79d7b2dd7..11eb825a56b0 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -356,11 +356,15 @@ void RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { } void RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, const SkPaint& paint) { - addOp(alloc().create_trivial<RoundRectOp>( - Rect(left, top, right, bottom), - *(mState.currentSnapshot()->transform), - getRecordedClip(), - refPaint(&paint), rx, ry)); + if (CC_LIKELY(MathUtils::isPositive(rx) || MathUtils::isPositive(ry))) { + addOp(alloc().create_trivial<RoundRectOp>( + Rect(left, top, right, bottom), + *(mState.currentSnapshot()->transform), + getRecordedClip(), + refPaint(&paint), rx, ry)); + } else { + drawRect(left, top, right, bottom, paint); + } } void RecordingCanvas::drawRoundRect( diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 2e3856fafb60..d35f76485bd1 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -158,7 +158,8 @@ const SkPath& FullPath::getUpdatedPath() { void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha, SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, - float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) { + float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, + int fillType) { mProperties.strokeWidth = strokeWidth; mProperties.strokeColor = strokeColor; mProperties.strokeAlpha = strokeAlpha; @@ -167,6 +168,7 @@ void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float st mProperties.strokeMiterLimit = strokeMiterLimit; mProperties.strokeLineCap = strokeLineCap; mProperties.strokeLineJoin = strokeLineJoin; + mProperties.fillType = fillType; // If any trim property changes, mark trim dirty and update the trim path setTrimPathStart(trimPathStart); @@ -179,7 +181,7 @@ inline SkColor applyAlpha(SkColor color, float alpha) { return SkColorSetA(color, alphaBytes * alpha); } -void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale, +void FullPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix){ // Draw path's fill, if fill color or gradient is valid bool needsFill = false; @@ -196,6 +198,8 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str if (needsFill) { mPaint.setStyle(SkPaint::Style::kFill_Style); mPaint.setAntiAlias(true); + SkPath::FillType ft = static_cast<SkPath::FillType>(mProperties.fillType); + renderPath.setFillType(ft); outCanvas->drawPath(renderPath, mPaint); } @@ -229,19 +233,25 @@ void FullPath::applyTrim() { // No trimming necessary. return; } + mTrimDirty = false; + mTrimmedSkPath.reset(); + if (mProperties.trimPathStart == mProperties.trimPathEnd) { + // Trimmed path should be empty. + return; + } SkPathMeasure measure(mSkPath, false); float len = SkScalarToFloat(measure.getLength()); float start = len * fmod((mProperties.trimPathStart + mProperties.trimPathOffset), 1.0f); float end = len * fmod((mProperties.trimPathEnd + mProperties.trimPathOffset), 1.0f); - mTrimmedSkPath.reset(); if (start > end) { measure.getSegment(start, len, &mTrimmedSkPath, true); - measure.getSegment(0, end, &mTrimmedSkPath, true); + if (end > 0) { + measure.getSegment(0, end, &mTrimmedSkPath, true); + } } else { measure.getSegment(start, end, &mTrimmedSkPath, true); } - mTrimDirty = false; } REQUIRE_COMPATIBLE_LAYOUT(FullPath::Properties); @@ -300,7 +310,7 @@ void FullPath::setPropertyValue(int propertyId, float value) { } } -void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, +void ClipPath::drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix){ outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op); } diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index 36a8aebeaa33..4d2fed096adf 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -96,7 +96,7 @@ public: protected: virtual const SkPath& getUpdatedPath(); - virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath, + virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix) = 0; Data mData; SkPath mSkPath; @@ -118,6 +118,7 @@ struct Properties { int32_t strokeLineCap = SkPaint::Cap::kButt_Cap; int32_t strokeLineJoin = SkPaint::Join::kMiter_Join; float strokeMiterLimit = 4; + int fillType = 0; /* non-zero or kWinding_FillType in Skia */ }; FullPath(const FullPath& path); // for cloning @@ -133,7 +134,7 @@ struct Properties { void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha, SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, - float strokeMiterLimit, int strokeLineCap, int strokeLineJoin); + float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType); // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI float getStrokeWidth() { return mProperties.strokeWidth; @@ -197,7 +198,7 @@ struct Properties { protected: const SkPath& getUpdatedPath() override; - void drawPath(SkCanvas* outCanvas, const SkPath& renderPath, + void drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix) override; private: @@ -213,6 +214,7 @@ private: StrokeLineCap, StrokeLineJoin, StrokeMiterLimit, + FillType, Count, }; // Applies trimming to the specified path. @@ -233,7 +235,7 @@ public: ClipPath(const Data& nodes) : Path(nodes) {} protected: - void drawPath(SkCanvas* outCanvas, const SkPath& renderPath, + void drawPath(SkCanvas* outCanvas, SkPath& renderPath, float strokeScale, const SkMatrix& matrix) override; }; diff --git a/libs/hwui/debug/nullgles.cpp b/libs/hwui/debug/nullgles.cpp index ffb064942911..8689f9814f7b 100644 --- a/libs/hwui/debug/nullgles.cpp +++ b/libs/hwui/debug/nullgles.cpp @@ -133,6 +133,15 @@ void glGetIntegerv(GLenum pname, GLint *data) { } } +GLenum glCheckFramebufferStatus(GLenum target) { + switch (target) { + case GL_FRAMEBUFFER: + return GL_FRAMEBUFFER_COMPLETE; + default: + return 0; // error case + } +} + const char* getString(GLenum name) { switch (name) { case GL_VENDOR: diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp index 5f984b59ebd9..bb1a044a8369 100644 --- a/libs/hwui/renderstate/OffscreenBufferPool.cpp +++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp @@ -164,6 +164,9 @@ OffscreenBuffer* OffscreenBufferPool::resize(OffscreenBuffer* layer, // resize in place layer->viewportWidth = width; layer->viewportHeight = height; + + // entire area will be repainted (and may be smaller) so clear usage region + layer->region.clear(); return layer; } putOrDelete(layer); diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index a496b4966456..c539d63daed3 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -484,6 +484,8 @@ void CanvasContext::draw() { bool drew = mCanvas->finish(); #endif + waitOnFences(); + GL_CHECKPOINT(LOW); // Even if we decided to cancel the frame, from the perspective of jank @@ -726,6 +728,37 @@ void CanvasContext::serializeDisplayListTree() { #endif } +void CanvasContext::waitOnFences() { + if (mFrameFences.size()) { + ATRACE_CALL(); + for (auto& fence : mFrameFences) { + fence->getResult(); + } + mFrameFences.clear(); + } +} + +class CanvasContext::FuncTaskProcessor : public TaskProcessor<bool> { +public: + FuncTaskProcessor(Caches& caches) + : TaskProcessor<bool>(&caches.tasks) {} + + virtual void onProcess(const sp<Task<bool> >& task) override { + FuncTask* t = static_cast<FuncTask*>(task.get()); + t->func(); + task->setResult(true); + } +}; + +void CanvasContext::enqueueFrameWork(std::function<void()>&& func) { + if (!mFrameWorkProcessor.get()) { + mFrameWorkProcessor = new FuncTaskProcessor(Caches::getInstance()); + } + sp<FuncTask> task(new FuncTask()); + task->func = func; + mFrameWorkProcessor->add(task); +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index cb61e51a2158..6706c30f148b 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -24,6 +24,8 @@ #include "IContextFactory.h" #include "LayerUpdateQueue.h" #include "RenderNode.h" +#include "thread/Task.h" +#include "thread/TaskProcessor.h" #include "utils/RingBuffer.h" #include "renderthread/RenderTask.h" #include "renderthread/RenderThread.h" @@ -41,6 +43,7 @@ #include <utils/Functor.h> #include <gui/Surface.h> +#include <functional> #include <set> #include <string> #include <vector> @@ -159,6 +162,9 @@ public: } } + // Used to queue up work that needs to be completed before this frame completes + ANDROID_API void enqueueFrameWork(std::function<void()>&& func); + private: friend class RegisterFrameCallbackTask; // TODO: Replace with something better for layer & other GL object @@ -170,6 +176,8 @@ private: void freePrefetechedLayers(); + void waitOnFences(); + EGLint mLastFrameWidth = 0; EGLint mLastFrameHeight = 0; @@ -213,6 +221,16 @@ private: // Stores the bounds of the main content. Rect mContentDrawBounds; + + // TODO: This is really a Task<void> but that doesn't really work + // when Future<> expects to be able to get/set a value + struct FuncTask : public Task<bool> { + std::function<void()> func; + }; + class FuncTaskProcessor; + + std::vector< sp<FuncTask> > mFrameFences; + sp<TaskProcessor<bool> > mFrameWorkProcessor; }; } /* namespace renderthread */ diff --git a/libs/hwui/tests/scripts/prep_volantis.sh b/libs/hwui/tests/scripts/prep_volantis.sh index 09d4869523ba..0572ee55c9b9 100755 --- a/libs/hwui/tests/scripts/prep_volantis.sh +++ b/libs/hwui/tests/scripts/prep_volantis.sh @@ -49,6 +49,6 @@ adb shell "echo 0 > /sys/devices/system/cpu/cpuquiet/tegra_cpuquiet/enable" # 684000 708000 756000 804000 852000 (kHz) S=324000000 -echo "set gpu to $s hz" +echo "set gpu to $S hz" adb shell "echo 1 > /d/clock/override.gbus/state" adb shell "echo $S > /d/clock/override.gbus/rate" diff --git a/libs/hwui/tests/unit/BakedOpRendererTests.cpp b/libs/hwui/tests/unit/BakedOpRendererTests.cpp new file mode 100644 index 000000000000..59bd75ef6f62 --- /dev/null +++ b/libs/hwui/tests/unit/BakedOpRendererTests.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include <BakedOpRenderer.h> +#include <tests/common/TestUtils.h> + +using namespace android::uirenderer; + +const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 }; + +RENDERTHREAD_TEST(BakedOpRenderer, startRepaintLayer_clear) { + BakedOpRenderer renderer(Caches::getInstance(), renderThread.renderState(), true, sLightInfo); + OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200u, 200u); + + layer.dirty(Rect(200, 200)); + { + renderer.startRepaintLayer(&layer, Rect(200, 200)); + EXPECT_TRUE(layer.region.isEmpty()) << "Repaint full layer should clear region"; + renderer.endLayer(); + } + + layer.dirty(Rect(200, 200)); + { + renderer.startRepaintLayer(&layer, Rect(100, 200)); // repainting left side + EXPECT_TRUE(layer.region.isRect()); + //ALOGD("bounds %d %d %d %d", RECT_ARGS(layer.region.getBounds())); + EXPECT_EQ(android::Rect(100, 0, 200, 200), layer.region.getBounds()) + << "Left side being repainted, so right side should be clear"; + renderer.endLayer(); + } + + // right side is now only dirty portion + { + renderer.startRepaintLayer(&layer, Rect(100, 0, 200, 200)); // repainting right side + EXPECT_TRUE(layer.region.isEmpty()) + << "Now right side being repainted, so region should be entirely clear"; + renderer.endLayer(); + } +} diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp index f147fd4be80e..31555f2f86ec 100644 --- a/libs/hwui/tests/unit/FrameBuilderTests.cpp +++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp @@ -316,6 +316,61 @@ TEST(FrameBuilder, textStrikethrough) { << "Expect number of ops = 2 * loop count"; } +static auto styles = { + SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style }; + +TEST(FrameBuilder, textStyle) { + class TextStyleTestRenderer : public TestRendererBase { + public: + void onMergedTextOps(const MergedBakedOpList& opList) override { + ASSERT_EQ(0, mIndex); + ASSERT_EQ(3u, opList.count); + mIndex += opList.count; + + int index = 0; + for (auto style : styles) { + auto state = opList.states[index++]; + ASSERT_EQ(style, state->op->paint->getStyle()) + << "Remainder of validation relies upon stable merged order"; + ASSERT_EQ(0, state->computedState.clipSideFlags) + << "Clipped bounds validation requires unclipped ops"; + } + + Rect fill = opList.states[0]->computedState.clippedBounds; + Rect stroke = opList.states[1]->computedState.clippedBounds; + EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds) + << "Stroke+Fill should be same as stroke"; + + EXPECT_TRUE(stroke.contains(fill)); + EXPECT_FALSE(fill.contains(stroke)); + + Rect outsetFill(fill); + outsetFill.outset(10); + EXPECT_EQ(stroke, outsetFill); + } + }; + auto node = TestUtils::createNode(0, 0, 400, 400, + [](RenderProperties& props, TestCanvas& canvas) { + SkPaint paint; + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + paint.setAntiAlias(true); + paint.setTextSize(50); + paint.setStrokeWidth(10); + + // draw 3 copies of the same text overlapping, each with a different style. + // They'll get merged, but with + for (auto style : styles) { + paint.setStyle(style); + TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); + } + }); + FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, + TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); + TextStyleTestRenderer renderer; + frameBuilder.replayBakedOps<TestDispatcher>(renderer); + EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; +} + RENDERTHREAD_TEST(FrameBuilder, textureLayer) { class TextureLayerTestRenderer : public TestRendererBase { public: diff --git a/libs/hwui/tests/unit/GlopBuilderTests.cpp b/libs/hwui/tests/unit/GlopBuilderTests.cpp index 949c541830df..454011fa47f0 100644 --- a/libs/hwui/tests/unit/GlopBuilderTests.cpp +++ b/libs/hwui/tests/unit/GlopBuilderTests.cpp @@ -16,7 +16,6 @@ #include <gtest/gtest.h> -#include "BakedOpRenderer.h" #include "Glop.h" #include "GlopBuilder.h" #include "Rect.h" diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp index 0c6eb571b9b4..37a485e3a9ac 100644 --- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp +++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp @@ -103,9 +103,11 @@ TEST(OffscreenBufferPool, resize) { OffscreenBufferPool pool; auto layer = pool.get(thread.renderState(), 64u, 64u); + layer->dirty(Rect(64, 64)); // resize in place ASSERT_EQ(layer, pool.resize(layer, 60u, 55u)); + EXPECT_TRUE(layer->region.isEmpty()) << "In place resize should clear usage region"; EXPECT_EQ(60u, layer->viewportWidth); EXPECT_EQ(55u, layer->viewportHeight); EXPECT_EQ(64u, layer->texture.width()); @@ -113,9 +115,13 @@ TEST(OffscreenBufferPool, resize) { // resized to use different object in pool auto layer2 = pool.get(thread.renderState(), 128u, 128u); + layer2->dirty(Rect(128, 128)); + EXPECT_FALSE(layer2->region.isEmpty()); pool.putOrDelete(layer2); ASSERT_EQ(1u, pool.getCount()); + ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u)); + EXPECT_TRUE(layer2->region.isEmpty()) << "Swap resize should clear usage region"; EXPECT_EQ(120u, layer2->viewportWidth); EXPECT_EQ(125u, layer2->viewportHeight); EXPECT_EQ(128u, layer2->texture.width()); diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp index c3165bbe9c1f..5e613fd50c3e 100644 --- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp +++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp @@ -114,6 +114,23 @@ TEST(RecordingCanvas, drawRect) { EXPECT_EQ(Rect(10, 20, 90, 180), op.unmappedBounds); } +TEST(RecordingCanvas, drawRoundRect) { + // Round case - stays rounded + auto dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) { + canvas.drawRoundRect(0, 0, 100, 100, 10, 10, SkPaint()); + }); + ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op"; + ASSERT_EQ(RecordedOpId::RoundRectOp, dl->getOps()[0]->opId); + + // Non-rounded case - turned into drawRect + dl = TestUtils::createDisplayList<RecordingCanvas>(100, 200, [](RecordingCanvas& canvas) { + canvas.drawRoundRect(0, 0, 100, 100, 0, -1, SkPaint()); + }); + ASSERT_EQ(1u, dl->getOps().size()) << "Must be exactly one op"; + ASSERT_EQ(RecordedOpId::RectOp, dl->getOps()[0]->opId) + << "Non-rounded rects should be converted"; +} + TEST(RecordingCanvas, drawText) { auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) { SkPaint paint; diff --git a/libs/hwui/thread/Barrier.h b/libs/hwui/thread/Barrier.h index 6cb23e54943b..0a7acb0fbbfd 100644 --- a/libs/hwui/thread/Barrier.h +++ b/libs/hwui/thread/Barrier.h @@ -33,11 +33,6 @@ public: mCondition.signal(mType); } - void close() { - Mutex::Autolock l(mLock); - mOpened = false; - } - void wait() const { Mutex::Autolock l(mLock); while (!mOpened) { diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java index 11fecfb7d201..a7eb73f0b0bf 100644 --- a/location/java/android/location/GnssMeasurement.java +++ b/location/java/android/location/GnssMeasurement.java @@ -47,7 +47,6 @@ public final class GnssMeasurement implements Parcelable { private double mCarrierPhaseUncertainty; private int mMultipathIndicator; private double mSnrInDb; - private boolean mPseudorangeRateCorrected; // The following enumerations must be in sync with the values declared in gps.h @@ -440,25 +439,6 @@ public final class GnssMeasurement implements Parcelable { } /** - * See {@link #getPseudorangeRateMetersPerSecond()} for more details. - * - * @return {@code true} if {@link #getPseudorangeRateMetersPerSecond()} contains a corrected - * value, {@code false} if it contains an uncorrected value. - */ - public boolean isPseudorangeRateCorrected() { - return mPseudorangeRateCorrected; - } - - /** - * Sets whether the pseudorange corrected. - * @hide - */ - @TestApi - public void setPseudorangeRateCorrected(boolean value) { - mPseudorangeRateCorrected = value; - } - - /** * Gets the pseudorange's rate uncertainty (1-Sigma) in m/s. * The uncertainty is represented as an absolute (single sided) value. */ @@ -813,7 +793,6 @@ public final class GnssMeasurement implements Parcelable { gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble(); gnssMeasurement.mMultipathIndicator = parcel.readInt(); gnssMeasurement.mSnrInDb = parcel.readDouble(); - gnssMeasurement.mPseudorangeRateCorrected = (parcel.readByte() != 0); return gnssMeasurement; } @@ -845,7 +824,6 @@ public final class GnssMeasurement implements Parcelable { parcel.writeDouble(mCarrierPhaseUncertainty); parcel.writeInt(mMultipathIndicator); parcel.writeDouble(mSnrInDb); - parcel.writeByte((byte) (mPseudorangeRateCorrected ? 1 : 0)); } @Override @@ -880,10 +858,6 @@ public final class GnssMeasurement implements Parcelable { mPseudorangeRateMetersPerSecond, "PseudorangeRateUncertaintyMetersPerSecond", mPseudorangeRateUncertaintyMetersPerSecond)); - builder.append(String.format( - format, - "PseudorangeRateIsCorrected", - isPseudorangeRateCorrected())); builder.append(String.format( format, @@ -943,7 +917,6 @@ public final class GnssMeasurement implements Parcelable { resetCarrierPhaseUncertainty(); setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN); resetSnrInDb(); - setPseudorangeRateCorrected(false); } private void setFlag(int flag) { diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java index ac255c8e823f..e5c0f276b142 100644 --- a/location/java/android/location/GnssNavigationMessage.java +++ b/location/java/android/location/GnssNavigationMessage.java @@ -286,18 +286,11 @@ public final class GnssNavigationMessage implements Parcelable { navigationMessage.setSvid(parcel.readInt()); navigationMessage.setMessageId(parcel.readInt()); navigationMessage.setSubmessageId(parcel.readInt()); - int dataLength = parcel.readInt(); byte[] data = new byte[dataLength]; parcel.readByteArray(data); navigationMessage.setData(data); - - if (parcel.dataAvail() >= Integer.SIZE) { - int status = parcel.readInt(); - navigationMessage.setStatus(status); - } else { - navigationMessage.setStatus(STATUS_UNKNOWN); - } + navigationMessage.setStatus(parcel.readInt()); return navigationMessage; } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 69d44872d86e..3c4216164328 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; +import android.app.NotificationManager; import android.app.PendingIntent; import android.bluetooth.BluetoothDevice; import android.content.ComponentName; @@ -1004,6 +1005,9 @@ public class AudioManager { * according to user settings. * <p>This method has no effect if the device implements a fixed volume policy * as indicated by {@link #isVolumeFixed()}. + * * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed + * unless the app has been granted Do Not Disturb Access. + * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL}, * {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}. * @see #getRingerMode() @@ -1025,6 +1029,9 @@ public class AudioManager { * Sets the volume index for a particular stream. * <p>This method has no effect if the device implements a fixed volume policy * as indicated by {@link #isVolumeFixed()}. + * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless + * the app has been granted Do Not Disturb Access. + * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. * @param streamType The stream whose volume index should be set. * @param index The volume index to set. See * {@link #getStreamMaxVolume(int)} for the largest valid value. diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 37714746ae69..ca306cc7127c 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -228,7 +228,7 @@ public class AudioRecord implements AudioRouting /** * Audio session ID */ - private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE; + private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; /** * AudioAttributes */ @@ -394,30 +394,48 @@ public class AudioRecord implements AudioRouting * value here as no error checking is or can be done. */ /*package*/ AudioRecord(long nativeRecordInJavaObj) { - int[] session = { 0 }; - int[] rates = { 0 }; - //TODO: update native initialization when information about hardware init failure - // due to capture device already open is available. - // Note that for this native_setup, we are providing an already created/initialized - // *Native* AudioRecord, so the attributes parameters to native_setup() are ignored. - int initResult = native_setup(new WeakReference<AudioRecord>(this), - null /*mAudioAttributes*/, - rates /*mSampleRates*/, - 0 /*mChannelMask*/, - 0 /*mChannelIndexMask*/, - 0 /*mAudioFormat*/, - 0 /*mNativeBufferSizeInBytes*/, - session, - ActivityThread.currentOpPackageName(), - nativeRecordInJavaObj); - if (initResult != SUCCESS) { - loge("Error code "+initResult+" when initializing native AudioRecord object."); - return; // with mState == STATE_UNINITIALIZED + mNativeRecorderInJavaObj = 0; + mNativeCallbackCookie = 0; + mNativeDeviceCallback = 0; + + // other initialization... + if (nativeRecordInJavaObj != 0) { + deferred_connect(nativeRecordInJavaObj); + } else { + mState = STATE_UNINITIALIZED; } + } - mSessionId = session[0]; + /** + * @hide + */ + /* package */ void deferred_connect(long nativeRecordInJavaObj) { + if (mState != STATE_INITIALIZED) { + int[] session = { 0 }; + int[] rates = { 0 }; + //TODO: update native initialization when information about hardware init failure + // due to capture device already open is available. + // Note that for this native_setup, we are providing an already created/initialized + // *Native* AudioRecord, so the attributes parameters to native_setup() are ignored. + int initResult = native_setup(new WeakReference<AudioRecord>(this), + null /*mAudioAttributes*/, + rates /*mSampleRates*/, + 0 /*mChannelMask*/, + 0 /*mChannelIndexMask*/, + 0 /*mAudioFormat*/, + 0 /*mNativeBufferSizeInBytes*/, + session, + ActivityThread.currentOpPackageName(), + nativeRecordInJavaObj); + if (initResult != SUCCESS) { + loge("Error code "+initResult+" when initializing native AudioRecord object."); + return; // with mState == STATE_UNINITIALIZED + } - mState = STATE_INITIALIZED; + mSessionId = session[0]; + + mState = STATE_INITIALIZED; + } } /** diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 2aac2b32bc62..e1dab092a3f7 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -295,7 +295,7 @@ public class AudioTrack implements AudioRouting /** * Audio session ID */ - private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE; + private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE; /** * Reference to the app-ops service. */ @@ -368,7 +368,7 @@ public class AudioTrack implements AudioRouting int bufferSizeInBytes, int mode) throws IllegalArgumentException { this(streamType, sampleRateInHz, channelConfig, audioFormat, - bufferSizeInBytes, mode, AudioSystem.AUDIO_SESSION_ALLOCATE); + bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE); } /** @@ -526,11 +526,18 @@ public class AudioTrack implements AudioRouting * the AudioTrackRoutingProxy subclass. * @param nativeTrackInJavaObj a C/C++ pointer to a native AudioTrack * (associated with an OpenSL ES player). + * IMPORTANT: For "N", this method is ONLY called to setup a Java routing proxy, + * i.e. IAndroidConfiguration::AcquireJavaProxy(). If we call with a 0 in nativeTrackInJavaObj + * it means that the OpenSL player interface hasn't been realized, so there is no native + * Audiotrack to connect to. In this case wait to call deferred_connect() until the + * OpenSLES interface is realized. */ /*package*/ AudioTrack(long nativeTrackInJavaObj) { // "final"s mAttributes = null; mAppOps = null; + mNativeTrackInJavaObj = 0; + mJniData = 0; // remember which looper is associated with the AudioTrack instantiation Looper looper; @@ -540,28 +547,41 @@ public class AudioTrack implements AudioRouting mInitializationLooper = looper; // other initialization... - // Note that for this native_setup, we are providing an already created/initialized - // *Native* AudioTrack, so the attributes parameters to native_setup() are ignored. - int[] session = { 0 }; - int[] rates = { 0 }; - int initResult = native_setup(new WeakReference<AudioTrack>(this), - null /*mAttributes - NA*/, - rates /*sampleRate - NA*/, - 0 /*mChannelMask - NA*/, - 0 /*mChannelIndexMask - NA*/, - 0 /*mAudioFormat - NA*/, - 0 /*mNativeBufferSizeInBytes - NA*/, - 0 /*mDataLoadMode - NA*/, - session, - nativeTrackInJavaObj); - if (initResult != SUCCESS) { - loge("Error code "+initResult+" when initializing AudioTrack."); - return; // with mState == STATE_UNINITIALIZED + if (nativeTrackInJavaObj != 0) { + deferred_connect(nativeTrackInJavaObj); + } else { + mState = STATE_UNINITIALIZED; } + } - mSessionId = session[0]; + /** + * @hide + */ + /* package */ void deferred_connect(long nativeTrackInJavaObj) { + if (mState != STATE_INITIALIZED) { + // Note that for this native_setup, we are providing an already created/initialized + // *Native* AudioTrack, so the attributes parameters to native_setup() are ignored. + int[] session = { 0 }; + int[] rates = { 0 }; + int initResult = native_setup(new WeakReference<AudioTrack>(this), + null /*mAttributes - NA*/, + rates /*sampleRate - NA*/, + 0 /*mChannelMask - NA*/, + 0 /*mChannelIndexMask - NA*/, + 0 /*mAudioFormat - NA*/, + 0 /*mNativeBufferSizeInBytes - NA*/, + 0 /*mDataLoadMode - NA*/, + session, + nativeTrackInJavaObj); + if (initResult != SUCCESS) { + loge("Error code "+initResult+" when initializing AudioTrack."); + return; // with mState == STATE_UNINITIALIZED + } - mState = STATE_INITIALIZED; + mSessionId = session[0]; + + mState = STATE_INITIALIZED; + } } /** diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index ce12e76b6588..1fc236a2a6d3 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -824,7 +824,13 @@ public class ExifInterface { } // Process JPEG input stream - getJpegAttributes(in); + try { + getJpegAttributes(in); + } catch (IOException e) { + // Ignore exceptions in order to keep the compatibility with the old versions of + // ExifInterface. + Log.w(TAG, "Invalid JPEG", e); + } if (DEBUG) { printAttributes(); @@ -1197,8 +1203,9 @@ public class ExifInterface { } bytesRead += 2; int length = dataInputStream.readUnsignedShort() - 2; - if (length < 0) + if (length < 0) { throw new IOException("Invalid length"); + } bytesRead += length; switch (marker) { case MARKER_APP1: { @@ -1221,6 +1228,9 @@ public class ExifInterface { if (length <= 0) { throw new IOException("Invalid exif"); } + if (DEBUG) { + Log.d(TAG, "readExifSegment with a byte array (length: " + length + ")"); + } byte[] bytes = new byte[length]; if (dataInputStream.read(bytes) != length) { throw new IOException("Invalid exif"); @@ -1309,8 +1319,9 @@ public class ExifInterface { case MARKER_APP1: { // Rewrite EXIF segment int length = dataInputStream.readUnsignedShort() - 2; - if (length < 0) + if (length < 0) { throw new IOException("Invalid length"); + } bytesRead += 2; int read; while ((read = dataInputStream.read( @@ -1331,8 +1342,9 @@ public class ExifInterface { // Copy JPEG segment int length = dataInputStream.readUnsignedShort(); dataOutputStream.writeUnsignedShort(length); - if (length < 0) + if (length < 0) { throw new IOException("Invalid length"); + } length -= 2; bytesRead += 2; int read; @@ -1385,8 +1397,9 @@ public class ExifInterface { } firstIfdOffset -= 8; if (firstIfdOffset > 0) { - if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset) + if (dataInputStream.skip(firstIfdOffset) != firstIfdOffset) { throw new IOException("Couldn't jump to first Ifd: " + firstIfdOffset); + } } // Read primary image TIFF image file directory. @@ -1582,8 +1595,16 @@ public class ExifInterface { // Reads image file directory, which is a tag group in EXIF. private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint) throws IOException { + if (dataInputStream.peek() + 2 > dataInputStream.mLength) { + // Return if there is no data from the offset. + return; + } // See JEITA CP-3451 Figure 5. page 9. short numberOfDirectoryEntry = dataInputStream.readShort(); + if (dataInputStream.peek() + 12 * numberOfDirectoryEntry > dataInputStream.mLength) { + // Return if the size of entries is too big. + return; + } if (DEBUG) { Log.d(TAG, "numberOfDirectoryEntry: " + numberOfDirectoryEntry); @@ -1595,10 +1616,25 @@ public class ExifInterface { int numberOfComponents = dataInputStream.readInt(); long nextEntryOffset = dataInputStream.peek() + 4; // next four bytes is for data // offset or value. + // Look up a corresponding tag from tag number + String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber); if (DEBUG) { - Log.d(TAG, String.format("tagNumber: %d, dataFormat: %d, numberOfComponents: %d", - tagNumber, dataFormat, numberOfComponents)); + Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d," + + "numberOfComponents: %d", hint, tagNumber, tagName, dataFormat, + numberOfComponents)); + } + + if (tagName == null || dataFormat <= 0 || + dataFormat >= IFD_FORMAT_BYTES_PER_FORMAT.length) { + // Skip if the parsed tag number is not defined or invalid data format. + if (tagName == null) { + Log.w(TAG, "Skip the tag entry since tag number is not defined: " + tagNumber); + } else { + Log.w(TAG, "Skip the tag entry since data format is invalid: " + dataFormat); + } + dataInputStream.seek(nextEntryOffset); + continue; } // Read a value from data field or seek to the value offset which is stored in data @@ -1609,19 +1645,21 @@ public class ExifInterface { if (DEBUG) { Log.d(TAG, "seek to data offset: " + offset); } - dataInputStream.seek(offset); - } - - // Look up a corresponding tag from tag number - String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber); - // Skip if the parsed tag number is not defined. - if (tagName == null) { - dataInputStream.seek(nextEntryOffset); - continue; + if (offset + byteCount <= dataInputStream.mLength) { + dataInputStream.seek(offset); + } else { + // Skip if invalid data offset. + Log.w(TAG, "Skip the tag entry since data offset is invalid: " + offset); + dataInputStream.seek(nextEntryOffset); + continue; + } } // Recursively parse IFD when a IFD pointer tag appears. int innerIfdHint = getIfdHintFromTagNumber(tagNumber); + if (DEBUG) { + Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount); + } if (innerIfdHint >= 0) { long offset = -1L; // Get offset from data field @@ -1650,9 +1688,11 @@ public class ExifInterface { if (DEBUG) { Log.d(TAG, String.format("Offset: %d, tagName: %s", offset, tagName)); } - if (offset > 0L) { + if (offset > 0L && offset < dataInputStream.mLength) { dataInputStream.seek(offset); readImageFileDirectory(dataInputStream, innerIfdHint); + } else { + Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset); } dataInputStream.seek(nextEntryOffset); @@ -1683,14 +1723,17 @@ public class ExifInterface { } } - long nextIfdOffset = dataInputStream.readUnsignedInt(); - if (DEBUG) { - Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset)); - } - // The next IFD offset needs to be bigger than 8 since the first IFD offset is at least 8. - if (nextIfdOffset > 8) { - dataInputStream.seek(nextIfdOffset); - readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT); + if (dataInputStream.peek() + 4 <= dataInputStream.mLength) { + long nextIfdOffset = dataInputStream.readUnsignedInt(); + if (DEBUG) { + Log.d(TAG, String.format("nextIfdOffset: %d", nextIfdOffset)); + } + // The next IFD offset needs to be bigger than 8 + // since the first IFD offset is at least 8. + if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) { + dataInputStream.seek(nextIfdOffset); + readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT); + } } } @@ -1748,17 +1791,18 @@ public class ExifInterface { } StringBuilder stringBuilder = new StringBuilder(); - while (true) { + while (index < numberOfComponents) { int ch = bytes[index]; - if (ch == 0) + if (ch == 0) { break; - if (ch >= 32) + } + if (ch >= 32) { stringBuilder.append((char) ch); - else + } + else { stringBuilder.append('?'); + } ++index; - if (index == numberOfComponents) - break; } return stringBuilder.toString(); } @@ -1772,8 +1816,9 @@ public class ExifInterface { // Gets the corresponding IFD group index of the given tag number for writing Exif Tags. private static int getIfdHintFromTagNumber(int tagNumber) { for (int i = 0; i < IFD_POINTER_TAG_HINTS.length; ++i) { - if (IFD_POINTER_TAGS[i].number == tagNumber) + if (IFD_POINTER_TAGS[i].number == tagNumber) { return IFD_POINTER_TAG_HINTS[i]; + } } return -1; } @@ -2076,8 +2121,9 @@ public class ExifInterface { public void seek(long byteCount) throws IOException { mPosition = 0L; reset(); - if (skip(byteCount) != byteCount) + if (skip(byteCount) != byteCount) { throw new IOException("Couldn't seek up to the byteCount"); + } } public long peek() { @@ -2086,8 +2132,9 @@ public class ExifInterface { public void readFully(byte[] buffer) throws IOException { mPosition += buffer.length; - if (mPosition > mLength) + if (mPosition > mLength) { throw new EOFException(); + } if (super.read(buffer, 0, buffer.length) != buffer.length) { throw new IOException("Couldn't read up to the length of buffer"); } @@ -2095,22 +2142,26 @@ public class ExifInterface { public byte readByte() throws IOException { ++mPosition; - if (mPosition > mLength) + if (mPosition > mLength) { throw new EOFException(); + } int ch = super.read(); - if (ch < 0) + if (ch < 0) { throw new EOFException(); + } return (byte) ch; } public short readShort() throws IOException { mPosition += 2; - if (mPosition > mLength) + if (mPosition > mLength) { throw new EOFException(); + } int ch1 = super.read(); int ch2 = super.read(); - if ((ch1 | ch2) < 0) + if ((ch1 | ch2) < 0) { throw new EOFException(); + } if (mByteOrder == LITTLE_ENDIAN) { return (short) ((ch2 << 8) + (ch1)); } else if (mByteOrder == BIG_ENDIAN) { @@ -2121,14 +2172,16 @@ public class ExifInterface { public int readInt() throws IOException { mPosition += 4; - if (mPosition > mLength) + if (mPosition > mLength) { throw new EOFException(); + } int ch1 = super.read(); int ch2 = super.read(); int ch3 = super.read(); int ch4 = super.read(); - if ((ch1 | ch2 | ch3 | ch4) < 0) + if ((ch1 | ch2 | ch3 | ch4) < 0) { throw new EOFException(); + } if (mByteOrder == LITTLE_ENDIAN) { return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + ch1); } else if (mByteOrder == BIG_ENDIAN) { @@ -2146,12 +2199,14 @@ public class ExifInterface { public int readUnsignedShort() throws IOException { mPosition += 2; - if (mPosition > mLength) + if (mPosition > mLength) { throw new EOFException(); + } int ch1 = super.read(); int ch2 = super.read(); - if ((ch1 | ch2) < 0) + if ((ch1 | ch2) < 0) { throw new EOFException(); + } if (mByteOrder == LITTLE_ENDIAN) { return ((ch2 << 8) + (ch1)); } else if (mByteOrder == BIG_ENDIAN) { @@ -2166,8 +2221,9 @@ public class ExifInterface { public long readLong() throws IOException { mPosition += 8; - if (mPosition > mLength) + if (mPosition > mLength) { throw new EOFException(); + } int ch1 = super.read(); int ch2 = super.read(); int ch3 = super.read(); @@ -2176,8 +2232,9 @@ public class ExifInterface { int ch6 = super.read(); int ch7 = super.read(); int ch8 = super.read(); - if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) + if ((ch1 | ch2 | ch3 | ch4 | ch5 | ch6 | ch7 | ch8) < 0) { throw new EOFException(); + } if (mByteOrder == LITTLE_ENDIAN) { return (((long) ch8 << 56) + ((long) ch7 << 48) + ((long) ch6 << 40) + ((long) ch5 << 32) + ((long) ch4 << 24) + ((long) ch3 << 16) diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java index db0c5bbf42d8..2650ee0ee3b3 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -1070,16 +1070,15 @@ public final class MediaDrm { * A CryptoSession is obtained using {@link #getCryptoSession} */ public final class CryptoSession { - private MediaDrm mDrm; private byte[] mSessionId; - CryptoSession(@NonNull MediaDrm drm, @NonNull byte[] sessionId, - @NonNull String cipherAlgorithm, @NonNull String macAlgorithm) + CryptoSession(@NonNull byte[] sessionId, + @NonNull String cipherAlgorithm, + @NonNull String macAlgorithm) { mSessionId = sessionId; - mDrm = drm; - setCipherAlgorithmNative(drm, sessionId, cipherAlgorithm); - setMacAlgorithmNative(drm, sessionId, macAlgorithm); + setCipherAlgorithmNative(MediaDrm.this, sessionId, cipherAlgorithm); + setMacAlgorithmNative(MediaDrm.this, sessionId, macAlgorithm); } /** @@ -1092,7 +1091,7 @@ public final class MediaDrm { @NonNull public byte[] encrypt( @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) { - return encryptNative(mDrm, mSessionId, keyid, input, iv); + return encryptNative(MediaDrm.this, mSessionId, keyid, input, iv); } /** @@ -1105,7 +1104,7 @@ public final class MediaDrm { @NonNull public byte[] decrypt( @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) { - return decryptNative(mDrm, mSessionId, keyid, input, iv); + return decryptNative(MediaDrm.this, mSessionId, keyid, input, iv); } /** @@ -1116,7 +1115,7 @@ public final class MediaDrm { */ @NonNull public byte[] sign(@NonNull byte[] keyid, @NonNull byte[] message) { - return signNative(mDrm, mSessionId, keyid, message); + return signNative(MediaDrm.this, mSessionId, keyid, message); } /** @@ -1130,7 +1129,7 @@ public final class MediaDrm { */ public boolean verify( @NonNull byte[] keyid, @NonNull byte[] message, @NonNull byte[] signature) { - return verifyNative(mDrm, mSessionId, keyid, message, signature); + return verifyNative(MediaDrm.this, mSessionId, keyid, message, signature); } }; @@ -1158,7 +1157,7 @@ public final class MediaDrm { @NonNull byte[] sessionId, @NonNull String cipherAlgorithm, @NonNull String macAlgorithm) { - return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm); + return new CryptoSession(sessionId, cipherAlgorithm, macAlgorithm); } /** diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index 26061e450e83..346f083f696b 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -508,7 +508,8 @@ public final class MediaFormat { * The associated value is an integer. * Constants are declared in {@link MediaCodecInfo.CodecProfileLevel}. * This key is used as a hint, and is only supported for codecs - * that specify a profile. + * that specify a profile. Note: Codecs are free to use all the available + * coding tools at the specified profile. * * @see MediaCodecInfo.CodecCapabilities#profileLevels */ diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index 56d3c9987bc1..adeb8348fc06 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -36,30 +36,28 @@ public class AudioMix { private AudioMixingRule mRule; private AudioFormat mFormat; private int mRouteFlags; - private String mRegistrationId; private int mMixType = MIX_TYPE_INVALID; // written by AudioPolicy int mMixState = MIX_STATE_DISABLED; int mCallbackFlags; + String mDeviceAddress; // initialized in constructor, read by AudioPolicyConfig - final int mDeviceId; - final String mDeviceAddress; + final int mDeviceSystemType; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* /** * All parameters are guaranteed valid through the Builder. */ private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags, - int deviceId, String deviceAddress) { + int deviceType, String deviceAddress) { mRule = rule; mFormat = format; mRouteFlags = routeFlags; - mRegistrationId = null; mMixType = rule.getTargetMixType(); mCallbackFlags = callbackFlags; - mDeviceId = deviceId; - mDeviceAddress = deviceAddress; + mDeviceSystemType = deviceType; + mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress; } // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined @@ -155,12 +153,12 @@ public class AudioMix { } void setRegistration(String regId) { - mRegistrationId = regId; + mDeviceAddress = regId; } /** @hide */ public String getRegistration() { - return mRegistrationId; + return mDeviceAddress; } /** @hide */ @@ -185,7 +183,8 @@ public class AudioMix { private AudioFormat mFormat = null; private int mRouteFlags = 0; private int mCallbackFlags = 0; - private int mDeviceId = -1; + // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* + private int mDeviceSystemType = AudioSystem.DEVICE_NONE; private String mDeviceAddress = null; /** @@ -243,12 +242,12 @@ public class AudioMix { /** * @hide * Only used by AudioPolicyConfig, not a public API. - * @param deviceId + * @param deviceType an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_* * @param address * @return the same Builder instance. */ - Builder setDevice(int deviceId, String address) { - mDeviceId = deviceId; + Builder setDevice(int deviceType, String address) { + mDeviceSystemType = deviceType; mDeviceAddress = address; return this; } @@ -312,7 +311,7 @@ public class AudioMix { if (!device.isSink()) { throw new IllegalArgumentException("Unsupported device type on mix, not a sink"); } - mDeviceId = device.getId(); + mDeviceSystemType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType()); mDeviceAddress = device.getAddress(); return this; } @@ -344,7 +343,9 @@ public class AudioMix { } mFormat = new AudioFormat.Builder().setSampleRate(rate).build(); } - if (mDeviceId != -1) { + if ((mDeviceSystemType != AudioSystem.DEVICE_NONE) + && (mDeviceSystemType != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) + && (mDeviceSystemType != AudioSystem.DEVICE_IN_REMOTE_SUBMIX)) { if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) { throw new IllegalArgumentException( "Can't have audio device without flag ROUTE_FLAG_RENDER"); @@ -357,8 +358,17 @@ public class AudioMix { throw new IllegalArgumentException( "Can't have flag ROUTE_FLAG_RENDER without an audio device"); } + if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_LOOP_BACK) { + if (mRule.getTargetMixType() == MIX_TYPE_PLAYERS) { + mDeviceSystemType = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; + } else if (mRule.getTargetMixType() == MIX_TYPE_RECORDERS) { + mDeviceSystemType = AudioSystem.DEVICE_IN_REMOTE_SUBMIX; + } else { + throw new IllegalArgumentException("Unknown mixing rule type"); + } + } } - return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceId, + return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType, mDeviceAddress); } } diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java index 3af3ae71a734..cafa5a8c5183 100644 --- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java +++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java @@ -84,7 +84,7 @@ public class AudioPolicyConfig implements Parcelable { // write callback flags dest.writeInt(mix.mCallbackFlags); // write device information - dest.writeInt(mix.mDeviceId); + dest.writeInt(mix.mDeviceSystemType); dest.writeString(mix.mDeviceAddress); // write mix format dest.writeInt(mix.getFormat().getSampleRate()); diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 0b0306c2c4fa..89e45772981c 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -19,6 +19,7 @@ package android.media.tv; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.graphics.Rect; import android.media.PlaybackParams; @@ -1241,6 +1242,7 @@ public final class TvInputManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void setParentalControlsEnabled(boolean enabled) { try { mService.setParentalControlsEnabled(enabled, mUserId); @@ -1292,6 +1294,7 @@ public final class TvInputManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull TvContentRating rating) { Preconditions.checkNotNull(rating); try { @@ -1310,6 +1313,7 @@ public final class TvInputManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void removeBlockedRating(@NonNull TvContentRating rating) { Preconditions.checkNotNull(rating); try { @@ -1444,6 +1448,7 @@ public final class TvInputManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public List<TvInputHardwareInfo> getHardwareList() { try { return mService.getHardwareList(); @@ -1462,6 +1467,7 @@ public final class TvInputManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public Hardware acquireTvInputHardware(int deviceId, final HardwareCallback callback, TvInputInfo info) { try { @@ -1488,6 +1494,7 @@ public final class TvInputManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public void releaseTvInputHardware(int deviceId, Hardware hardware) { try { mService.releaseTvInputHardware(deviceId, hardware.getInterface(), mUserId); diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index bc20c1790de2..88be68609597 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -904,9 +904,7 @@ public abstract class TvInputService extends Service { * i.e. prefixed with a package name you own, so that different developers will * not create conflicting commands. * @param data Any data to include with the command. - * @hide */ - @SystemApi public void onAppPrivateCommand(@NonNull String action, Bundle data) { } @@ -1755,9 +1753,7 @@ public abstract class TvInputService extends Service { * i.e. prefixed with a package name you own, so that different developers will * not create conflicting commands. * @param data Any data to include with the command. - * @hide */ - @SystemApi public void onAppPrivateCommand(@NonNull String action, Bundle data) { } diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java index d48ea21e07d9..da1002d650e7 100644 --- a/media/java/android/media/tv/TvRecordingClient.java +++ b/media/java/android/media/tv/TvRecordingClient.java @@ -200,16 +200,14 @@ public class TvRecordingClient { } /** - * Calls {@link TvInputService.RecordingSession#appPrivateCommand(String, Bundle)} for the - * current recording session. + * Sends a private command to the underlying TV input. This can be used to provide + * domain-specific features that are only known between certain clients and their TV inputs. * * @param action The name of the private command to send. This <em>must</em> be a scoped name, * i.e. prefixed with a package name you own, so that different developers will not * create conflicting commands. * @param data An optional bundle to send with the command. - * @hide */ - @SystemApi public void sendAppPrivateCommand(@NonNull String action, Bundle data) { if (TextUtils.isEmpty(action)) { throw new IllegalArgumentException("action cannot be null or an empty string"); diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index 96230769762c..6ca6193cb0be 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -293,7 +293,7 @@ public class TvView extends ViewGroup { /** * Tunes to a given channel. This can be used to provide domain-specific features that are only - * known between certain TvView applications and their TV inputs. + * known between certain clients and their TV inputs. * * @param inputId The ID of TV input for the given channel. * @param channelUri The URI of a channel. @@ -550,16 +550,14 @@ public class TvView extends ViewGroup { } /** - * Calls {@link TvInputService.Session#onAppPrivateCommand(String, Bundle)} for the current - * session. + * Sends a private command to the underlying TV input. This can be used to provide + * domain-specific features that are only known between certain clients and their TV inputs. * * @param action The name of the private command to send. This <em>must</em> be a scoped name, * i.e. prefixed with a package name you own, so that different developers will not * create conflicting commands. * @param data An optional bundle to send with the command. - * @hide */ - @SystemApi public void sendAppPrivateCommand(@NonNull String action, Bundle data) { if (TextUtils.isEmpty(action)) { throw new IllegalArgumentException("action cannot be null or an empty string"); diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index e9d62dec80a4..2fb1a3b9fbcf 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -906,14 +906,16 @@ android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz) android_media_MediaPlayer_release(env, thiz); } -static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, jint sessionId) { +static void android_media_MediaPlayer_set_audio_session_id(JNIEnv *env, jobject thiz, + jint sessionId) { ALOGV("set_session_id(): %d", sessionId); sp<MediaPlayer> mp = getMediaPlayer(env, thiz); if (mp == NULL ) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } - process_media_player_call( env, thiz, mp->setAudioSessionId(sessionId), NULL, NULL ); + process_media_player_call( env, thiz, mp->setAudioSessionId((audio_session_t) sessionId), NULL, + NULL); } static jint android_media_MediaPlayer_get_audio_session_id(JNIEnv *env, jobject thiz) { diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp index 527e6c2210d6..62685c94453c 100644 --- a/media/jni/android_media_Utils.cpp +++ b/media/jni/android_media_Utils.cpp @@ -307,6 +307,11 @@ status_t ConvertMessageToMap( AMessage::Type valueType; const char *key = msg->getEntryNameAt(i, &valueType); + if (!strncmp(key, "android._", 9)) { + // don't expose private keys (starting with android._) + continue; + } + jobject valueObj = NULL; switch (valueType) { @@ -460,6 +465,11 @@ status_t ConvertKeyValueArraysToMessage( env->ReleaseStringUTFChars((jstring)keyObj, tmp); tmp = NULL; + if (key.startsWith("android._")) { + // don't propagate private keys (starting with android._) + continue; + } + jobject valueObj = env->GetObjectArrayElement(values, i); if (env->IsInstanceOf(valueObj, stringClass.get())) { @@ -735,8 +745,15 @@ status_t getLockedImageInfo(LockedImage* buffer, int idx, case HAL_PIXEL_FORMAT_BLOB: // Used for JPEG data, height must be 1, width == size, single plane. LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx); - LOG_ALWAYS_FATAL_IF(buffer->height != 1, - "BLOB format buffer should has height value %d", buffer->height); + // When RGBA override is being used, buffer height will be equal to width + if (usingRGBAOverride) { + LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width, + "RGBA override BLOB format buffer should have height == width"); + } else { + LOG_ALWAYS_FATAL_IF(buffer->height != 1, + "BLOB format buffer should have height value 1"); + } + pData = buffer->data; dataSize = Image_getJpegSize(buffer, usingRGBAOverride); diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp index fa6913573add..10efe188ad59 100644 --- a/media/jni/audioeffect/android_media_AudioEffect.cpp +++ b/media/jni/audioeffect/android_media_AudioEffect.cpp @@ -351,7 +351,7 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t priority, effectCallback, &lpJniStorage->mCallbackData, - sessionId, + (audio_session_t) sessionId, 0); if (lpAudioEffect == 0) { ALOGE("Error creating AudioEffect"); @@ -819,7 +819,7 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _ effect_descriptor_t *descriptors = new effect_descriptor_t[AudioEffect::kMaxPreProcessing]; uint32_t numEffects = AudioEffect::kMaxPreProcessing; - status_t status = AudioEffect::queryDefaultPreProcessing(audioSession, + status_t status = AudioEffect::queryDefaultPreProcessing((audio_session_t) audioSession, descriptors, &numEffects); if (status != NO_ERROR || numEffects == 0) { diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp index 3d3adba609c0..f1a8c6fbdb29 100644 --- a/media/jni/audioeffect/android_media_Visualizer.cpp +++ b/media/jni/audioeffect/android_media_Visualizer.cpp @@ -388,7 +388,7 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th 0, android_media_visualizer_effect_callback, lpJniStorage, - sessionId); + (audio_session_t) sessionId); if (lpVisualizer == 0) { ALOGE("Error creating Visualizer"); goto setup_failure; diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp index 76c701a5b8ce..5cfe3004514c 100644 --- a/native/android/sensor.cpp +++ b/native/android/sensor.cpp @@ -105,6 +105,14 @@ int ASensorManager_destroyEventQueue(ASensorManager* manager, /*****************************************************************************/ +int ASensorEventQueue_registerSensor(ASensorEventQueue* queue, ASensor const* sensor, + int32_t samplingPeriodUs, int maxBatchReportLatencyUs) +{ + return static_cast<SensorEventQueue*>(queue)->enableSensor( + static_cast<Sensor const*>(sensor)->getHandle(), samplingPeriodUs, + maxBatchReportLatencyUs, 0); +} + int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor) { return static_cast<SensorEventQueue*>(queue)->enableSensor( diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml index 6f38e25e7158..6fe239e400dc 100644 --- a/packages/DocumentsUI/AndroidManifest.xml +++ b/packages/DocumentsUI/AndroidManifest.xml @@ -5,6 +5,8 @@ <uses-permission android:name="android.permission.MANAGE_DOCUMENTS" /> <uses-permission android:name="android.permission.REMOVE_TASKS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> + <uses-permission android:name="android.permission.CACHE_CONTENT" /> + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <application android:name=".DocumentsApplication" @@ -105,6 +107,12 @@ </intent-filter> </receiver> + <receiver android:name=".BootReceiver"> + <intent-filter> + <action android:name="android.intent.action.BOOT_COMPLETED" /> + </intent-filter> + </receiver> + <service android:name=".services.FileOperationService" android:exported="false"> diff --git a/packages/DocumentsUI/app-perf-tests/Android.mk b/packages/DocumentsUI/app-perf-tests/Android.mk new file mode 100644 index 000000000000..3f12906b7f62 --- /dev/null +++ b/packages/DocumentsUI/app-perf-tests/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests +#LOCAL_SDK_VERSION := current + +LOCAL_SRC_FILES := $(call all-java-files-under, src) \ + +LOCAL_JAVA_LIBRARIES := android-support-v4 android.test.runner +LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ub-uiautomator + +LOCAL_PACKAGE_NAME := DocumentsUIAppPerfTests +LOCAL_INSTRUMENTATION_FOR := DocumentsUI + +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) + diff --git a/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml new file mode 100644 index 000000000000..1c3ed80adc2f --- /dev/null +++ b/packages/DocumentsUI/app-perf-tests/AndroidManifest.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.documentsui.appperftests"> + + <application> + <uses-library android:name="android.test.runner" /> + + <activity + android:name="com.android.documentsui.LauncherActivity" /> + </application> + + <!-- This package instrumentates itself, so the DocumentsUI process can be killed without + killing the testing package. --> + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.documentsui.appperftests" + android:label="App performance tests for DocumentsUI" /> + +</manifest> diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java new file mode 100644 index 000000000000..d6e8a96f3ad1 --- /dev/null +++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/FilesAppPerfTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2016 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.documentsui; + +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.os.Bundle; +import android.provider.DocumentsContract; +import android.support.test.uiautomator.UiDevice; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; + +@LargeTest +public class FilesAppPerfTest extends InstrumentationTestCase { + + // Keys used to report metrics to APCT. + private static final String KEY_FILES_COLD_START_PERFORMANCE_MEDIAN = + "files-cold-start-performance-median"; + private static final String KEY_FILES_WARM_START_PERFORMANCE_MEDIAN = + "files-warm-start-performance-median"; + + private static final String TARGET_PACKAGE = "com.android.documentsui"; + + private static final int NUM_MEASUREMENTS = 10; + + private LauncherActivity mActivity; + private UiDevice mDevice; + + @Override + public void setUp() { + mDevice = UiDevice.getInstance(getInstrumentation()); + } + + public void testFilesColdStartPerformance() throws Exception { + runFilesStartPerformanceTest(true); + } + + public void testFilesWarmStartPerformance() throws Exception { + runFilesStartPerformanceTest(false); + } + + public void runFilesStartPerformanceTest(boolean cold) throws Exception { + long[] measurements = new long[NUM_MEASUREMENTS]; + for (int i = 0; i < NUM_MEASUREMENTS; i++) { + if (cold) { + // Kill all providers, as well as DocumentsUI to measure a cold start. + killProviders(); + mDevice.executeShellCommand("am force-stop " + TARGET_PACKAGE); + } + mDevice.waitForIdle(); + + LauncherActivity.testCaseLatch = new CountDownLatch(1); + mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(), + LauncherActivity.class, null); + LauncherActivity.testCaseLatch.await(); + measurements[i] = LauncherActivity.measurement; + } + + reportMetrics(cold ? KEY_FILES_COLD_START_PERFORMANCE_MEDIAN + : KEY_FILES_WARM_START_PERFORMANCE_MEDIAN, measurements); + } + + private void reportMetrics(String key, long[] measurements) { + final Bundle status = new Bundle(); + Arrays.sort(measurements); + final long median = measurements[NUM_MEASUREMENTS / 2 - 1]; + status.putDouble(key, median); + + getInstrumentation().sendStatus(Activity.RESULT_OK, status); + } + + private void killProviders() throws Exception { + final PackageManager pm = getInstrumentation().getContext().getPackageManager(); + final Intent intent = new Intent(DocumentsContract.PROVIDER_INTERFACE); + final List<ResolveInfo> providers = pm.queryIntentContentProviders(intent, 0); + for (ResolveInfo info : providers) { + final String packageName = info.providerInfo.packageName; + mDevice.executeShellCommand("am force-stop " + packageName); + } + } +} diff --git a/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java new file mode 100644 index 000000000000..21fc52e006b7 --- /dev/null +++ b/packages/DocumentsUI/app-perf-tests/src/com/android/documentsui/LauncherActivity.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 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.documentsui; + +import static com.android.documentsui.Shared.EXTRA_BENCHMARK; + +import android.app.Activity; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; + +import java.util.concurrent.CountDownLatch; + +public class LauncherActivity extends Activity { + private static final String TARGET_PACKAGE = "com.android.documentsui"; + private static final int BENCHMARK_REQUEST_CODE = 1986; + + public static CountDownLatch testCaseLatch = null; + public static long measurement = -1; + + private long mStartTime = -1; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + new Handler().post(new Runnable() { + @Override public void run() { + final Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT"); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.putExtra(EXTRA_BENCHMARK, true); + intent.setType("*/*"); + + mStartTime = System.currentTimeMillis(); + startActivityForResult(intent, BENCHMARK_REQUEST_CODE); + } + }); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == BENCHMARK_REQUEST_CODE) { + measurement = System.currentTimeMillis() - mStartTime; + testCaseLatch.countDown(); + finish(); + } + } +} diff --git a/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml b/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml new file mode 100644 index 000000000000..bfb027149333 --- /dev/null +++ b/packages/DocumentsUI/res/layout/dialog_open_scoped_directory.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2016 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:theme="@style/Theme.AppCompat.Light.Dialog.Alert" + android:orientation="vertical" + android:paddingEnd="24dp" + android:paddingStart="24dp" > + + <TextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/message" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingEnd="24dp" + android:paddingStart="32dp" + android:paddingTop="24dp"> + </TextView> + + <CheckBox + android:id="@+id/do_not_ask_checkbox" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginTop="16dip" + android:text="@string/never_ask_again" + android:textColor="?android:attr/textColorSecondary" + android:visibility="gone" /> +</LinearLayout>
\ No newline at end of file diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml index 6fff804f12dc..17e2c31aa6fb 100644 --- a/packages/DocumentsUI/res/values-af/strings.xml +++ b/packages/DocumentsUI/res/values-af/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Hernoem"</string> <string name="rename_error" msgid="4203041674883412606">"Kon nie dokument hernoem nie"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige lêers is omgeskakel"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Laat toe"</string> <string name="deny" msgid="2081879885755434506">"Weier"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml index c61db57b42ad..0cb68de1b21e 100644 --- a/packages/DocumentsUI/res/values-am/strings.xml +++ b/packages/DocumentsUI/res/values-am/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"እንደገና ሰይም"</string> <string name="rename_error" msgid="4203041674883412606">"ሰነዱን ዳግም መሰየም አልተሳካም"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"አንዳንድ ፋይሎች ተለውጠዋል"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"ይፍቀዱ"</string> <string name="deny" msgid="2081879885755434506">"ያስተባብሉ"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml index dcfef2ac6534..4a30257754b4 100644 --- a/packages/DocumentsUI/res/values-ar/strings.xml +++ b/packages/DocumentsUI/res/values-ar/strings.xml @@ -138,6 +138,10 @@ <string name="menu_rename" msgid="7678802479104285353">"إعادة تسمية"</string> <string name="rename_error" msgid="4203041674883412606">"أخفقت إعادة تسمية المستند."</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"تم تحويل بعض الملفات"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"السماح"</string> <string name="deny" msgid="2081879885755434506">"رفض"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-az-rAZ/strings.xml b/packages/DocumentsUI/res/values-az-rAZ/strings.xml index e1505f8531cf..b4326803975f 100644 --- a/packages/DocumentsUI/res/values-az-rAZ/strings.xml +++ b/packages/DocumentsUI/res/values-az-rAZ/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Adını dəyişdirin"</string> <string name="rename_error" msgid="4203041674883412606">"Sənəd adını dəyişmək uğursuz oldu"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bəzi fayllar konvertasiya edilib"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"İcazə verin"</string> <string name="deny" msgid="2081879885755434506">"Rədd et"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml index b884a19a8c38..3e365036ed8c 100644 --- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml +++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml @@ -117,6 +117,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string> <string name="rename_error" msgid="4203041674883412606">"Preimenovanje dokumenta nije uspelo"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke datoteke su konvertovane"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Dozvoli"</string> <string name="deny" msgid="2081879885755434506">"Odbij"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml index 94c34bdb93ae..a1ac5c95eeac 100644 --- a/packages/DocumentsUI/res/values-bg/strings.xml +++ b/packages/DocumentsUI/res/values-bg/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Преименуване"</string> <string name="rename_error" msgid="4203041674883412606">"Преименуването на документа не бе успешно"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Някои файлове бяха преобразувани"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Разрешаване"</string> <string name="deny" msgid="2081879885755434506">"Отказване"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml index 215904429482..7b881949d062 100644 --- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml +++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"পুনঃনামকরণ"</string> <string name="rename_error" msgid="4203041674883412606">"দস্তাবেজের পুনঃনামকরণ ব্যর্থ হয়েছে৷"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"কিছু ফাইল রূপান্তরিত হয়েছে"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"অনুমতি দিন"</string> <string name="deny" msgid="2081879885755434506">"আস্বীকার করুন"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml index f366ce8cf9d2..9daa80affdc8 100644 --- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml +++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml @@ -117,6 +117,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string> <string name="rename_error" msgid="4203041674883412606">"Nije uspjelo preimenovanje dokumenta"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke od datoteka su pretvorene"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Dozvoli"</string> <string name="deny" msgid="2081879885755434506">"Odbijte"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml index 5af86b122a72..b7d887e64f1f 100644 --- a/packages/DocumentsUI/res/values-ca/strings.xml +++ b/packages/DocumentsUI/res/values-ca/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Canvia el nom"</string> <string name="rename_error" msgid="4203041674883412606">"No s\'ha pogut canviar el nom del document"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"S\'han convertit alguns fitxers"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Permet"</string> <string name="deny" msgid="2081879885755434506">"Denega"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml index 4e8b4403433a..d58615d2dbd4 100644 --- a/packages/DocumentsUI/res/values-cs/strings.xml +++ b/packages/DocumentsUI/res/values-cs/strings.xml @@ -124,6 +124,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Přejmenovat"</string> <string name="rename_error" msgid="4203041674883412606">"Dokument se nepodařilo přejmenovat."</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Některé soubory byly převedeny"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Povolit"</string> <string name="deny" msgid="2081879885755434506">"Odepřít"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml index ee5ba49a5426..99338f6c9d85 100644 --- a/packages/DocumentsUI/res/values-da/strings.xml +++ b/packages/DocumentsUI/res/values-da/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Omdøb"</string> <string name="rename_error" msgid="4203041674883412606">"Dokumentet kunne ikke omdøbes"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nogle filer er konverteret"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Tillad"</string> <string name="deny" msgid="2081879885755434506">"Afvis"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml index a42e9554acd2..373b05825d8a 100644 --- a/packages/DocumentsUI/res/values-de/strings.xml +++ b/packages/DocumentsUI/res/values-de/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Umbenennen"</string> <string name="rename_error" msgid="4203041674883412606">"Dokument konnte nicht umbenannt werden"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Einige Dateien wurden konvertiert"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Zulassen"</string> <string name="deny" msgid="2081879885755434506">"Ablehnen"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml index e6839de1455f..539a7c632ad8 100644 --- a/packages/DocumentsUI/res/values-el/strings.xml +++ b/packages/DocumentsUI/res/values-el/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Μετονομασία"</string> <string name="rename_error" msgid="4203041674883412606">"Αποτυχία μετονομασίας εγγράφου"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Ορισμένα αρχεία μετατράπηκαν"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Να επιτρέπεται"</string> <string name="deny" msgid="2081879885755434506">"Άρνηση"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-en-rAU/strings.xml b/packages/DocumentsUI/res/values-en-rAU/strings.xml index 8b46660b2329..1693bdb7984e 100644 --- a/packages/DocumentsUI/res/values-en-rAU/strings.xml +++ b/packages/DocumentsUI/res/values-en-rAU/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"rename"</string> <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Allow"</string> <string name="deny" msgid="2081879885755434506">"Deny"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml index 8b46660b2329..1693bdb7984e 100644 --- a/packages/DocumentsUI/res/values-en-rGB/strings.xml +++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"rename"</string> <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Allow"</string> <string name="deny" msgid="2081879885755434506">"Deny"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml index 8b46660b2329..1693bdb7984e 100644 --- a/packages/DocumentsUI/res/values-en-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"rename"</string> <string name="rename_error" msgid="4203041674883412606">"Failed to rename document"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Some files were converted"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Allow"</string> <string name="deny" msgid="2081879885755434506">"Deny"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml index 8fd8381d8f18..8ad0439f9561 100644 --- a/packages/DocumentsUI/res/values-es-rUS/strings.xml +++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Cambiar nombre"</string> <string name="rename_error" msgid="4203041674883412606">"No se pudo cambiar el nombre del documento"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se convirtieron algunos archivos"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Permitir"</string> <string name="deny" msgid="2081879885755434506">"Denegar"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml index 81fc59abb936..c3a4648aedf5 100644 --- a/packages/DocumentsUI/res/values-es/strings.xml +++ b/packages/DocumentsUI/res/values-es/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Cambiar nombre"</string> <string name="rename_error" msgid="4203041674883412606">"Error al cambiar el nombre del documento"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se han convertido algunos archivos"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Permitir"</string> <string name="deny" msgid="2081879885755434506">"Denegar"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml index 7cf134e3ebd7..76f1ef79291f 100644 --- a/packages/DocumentsUI/res/values-et-rEE/strings.xml +++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Nimeta ümber"</string> <string name="rename_error" msgid="4203041674883412606">"Dokumendi ümbernimetamine ebaõnnestus"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Mõned failid teisendati"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Luba"</string> <string name="deny" msgid="2081879885755434506">"Keela"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml index 23e407912120..ea776576c5e7 100644 --- a/packages/DocumentsUI/res/values-eu-rES/strings.xml +++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Aldatu izena"</string> <string name="rename_error" msgid="4203041674883412606">"Ezin izan zaio aldatu izena dokumentuari"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Artxibo batzuk bihurtu dira"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Onartu"</string> <string name="deny" msgid="2081879885755434506">"Ukatu"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml index 6aa56263126c..4c2a34211314 100644 --- a/packages/DocumentsUI/res/values-fa/strings.xml +++ b/packages/DocumentsUI/res/values-fa/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"تغییر نام"</string> <string name="rename_error" msgid="4203041674883412606">"نام سند تغییر نکرد"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"بعضی از فایلها تبدیل شدند"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"ارزیابیشده"</string> <string name="deny" msgid="2081879885755434506">"اجازه ندارد"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml index 8be6d6115883..a586f7c60d8b 100644 --- a/packages/DocumentsUI/res/values-fi/strings.xml +++ b/packages/DocumentsUI/res/values-fi/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Nimeä uudelleen"</string> <string name="rename_error" msgid="4203041674883412606">"Dokumentin nimen muuttaminen epäonnistui."</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Joitakin tiedostoja muunnettiin."</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Salli"</string> <string name="deny" msgid="2081879885755434506">"Kiellä"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml index 0a3357076722..cb3a1236b676 100644 --- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml +++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Renommer"</string> <string name="rename_error" msgid="4203041674883412606">"Impossible de renommer le document"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Autoriser"</string> <string name="deny" msgid="2081879885755434506">"Refuser"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml index 478ea46b83ca..0cbc14153c2e 100644 --- a/packages/DocumentsUI/res/values-fr/strings.xml +++ b/packages/DocumentsUI/res/values-fr/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Renommer"</string> <string name="rename_error" msgid="4203041674883412606">"Échec du changement de nom du document."</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Autoriser"</string> <string name="deny" msgid="2081879885755434506">"Refuser"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml index c933faaf082e..1f8ecadf6d8e 100644 --- a/packages/DocumentsUI/res/values-gl-rES/strings.xml +++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Cambiar nome"</string> <string name="rename_error" msgid="4203041674883412606">"Non se puido cambiar o nome do documento"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Convertéronse algúns ficheiros"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Permitir"</string> <string name="deny" msgid="2081879885755434506">"Rexeitar"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml index e9fda199d091..7fc21b6bbf89 100644 --- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"નામ બદલો"</string> <string name="rename_error" msgid="4203041674883412606">"દસ્તાવેજનું નામ બદલવામાં નિષ્ફળ થયાં"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"કેટલીક ફાઇલો રૂપાંતરિત કરી હતી"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"મંજૂરી આપો"</string> <string name="deny" msgid="2081879885755434506">"નકારો"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml index 489bb98d34e8..87dfb5fc8246 100644 --- a/packages/DocumentsUI/res/values-hi/strings.xml +++ b/packages/DocumentsUI/res/values-hi/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"नाम बदलें"</string> <string name="rename_error" msgid="4203041674883412606">"दस्तावेज़ का नाम बदलना विफल रहा"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"कुछ फ़ाइलें रूपांतरित हो गई थीं"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"अनुमति दें"</string> <string name="deny" msgid="2081879885755434506">"अस्वीकारें"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml index 51b8673a9a91..f86877e67c6f 100644 --- a/packages/DocumentsUI/res/values-hr/strings.xml +++ b/packages/DocumentsUI/res/values-hr/strings.xml @@ -117,6 +117,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Promijeni naziv"</string> <string name="rename_error" msgid="4203041674883412606">"Naziv dokumenta nije promijenjen"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke su datoteke konvertirane"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Dopusti"</string> <string name="deny" msgid="2081879885755434506">"Odbij"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml index b7e74e024a87..14662ad377b0 100644 --- a/packages/DocumentsUI/res/values-hu/strings.xml +++ b/packages/DocumentsUI/res/values-hu/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Átnevezés"</string> <string name="rename_error" msgid="4203041674883412606">"Nem sikerült átnevezni a dokumentumot"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Egyes fájlokat konvertált a rendszer"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Engedélyezés"</string> <string name="deny" msgid="2081879885755434506">"Elutasítás"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml index 4dbae9de21bd..ecd7669c1d2a 100644 --- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml +++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Վերանվանել"</string> <string name="rename_error" msgid="4203041674883412606">"Չհաջողվեց վերանվանել փաստաթուղթը"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Որոշ ֆայլեր փոխարկվել են"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Թույլատրել"</string> <string name="deny" msgid="2081879885755434506">"Մերժել"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml index 73ed8bcd1c8e..b27674e4d82b 100644 --- a/packages/DocumentsUI/res/values-in/strings.xml +++ b/packages/DocumentsUI/res/values-in/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Ganti nama"</string> <string name="rename_error" msgid="4203041674883412606">"Gagal mengganti nama dokumen"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Beberapa file dikonversi"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Izinkan"</string> <string name="deny" msgid="2081879885755434506">"Tolak"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml index 75831ed055d9..f351cb807ae7 100644 --- a/packages/DocumentsUI/res/values-is-rIS/strings.xml +++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Endurnefna"</string> <string name="rename_error" msgid="4203041674883412606">"Ekki tókst að endurnefna skjalið"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sumum skrám var umbreytt"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Leyfa"</string> <string name="deny" msgid="2081879885755434506">"Hafna"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml index cfd5611f345e..3eb14c0ee6ee 100644 --- a/packages/DocumentsUI/res/values-it/strings.xml +++ b/packages/DocumentsUI/res/values-it/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Rinomina"</string> <string name="rename_error" msgid="4203041674883412606">"Ridenominazione documento non riuscita"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alcuni file sono stati convertiti"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Consenti"</string> <string name="deny" msgid="2081879885755434506">"Nega"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml index 7d4cb9e99ee0..3b0aef8a56e9 100644 --- a/packages/DocumentsUI/res/values-iw/strings.xml +++ b/packages/DocumentsUI/res/values-iw/strings.xml @@ -124,6 +124,10 @@ <string name="menu_rename" msgid="7678802479104285353">"שנה שם"</string> <string name="rename_error" msgid="4203041674883412606">"ניסיון שינוי שם המסמך נכשל"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"קבצים מסוימים הומרו"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"אפשר"</string> <string name="deny" msgid="2081879885755434506">"דחה"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml index 9618d36b363e..23b7ab67ee5b 100644 --- a/packages/DocumentsUI/res/values-ja/strings.xml +++ b/packages/DocumentsUI/res/values-ja/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"名前を変更"</string> <string name="rename_error" msgid="4203041674883412606">"ドキュメントの名前を変更できませんでした"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"一部のファイルが変換されました"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"許可"</string> <string name="deny" msgid="2081879885755434506">"拒否"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml index ac8d267009ff..fc36bdbc868e 100644 --- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml +++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"გადარქმევა"</string> <string name="rename_error" msgid="4203041674883412606">"დოკუმენტის გადარქმევა ვერ მოხერხდა"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ზოგიერთი ფაილი გარდაქმნილია"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"უფლების მიცემა"</string> <string name="deny" msgid="2081879885755434506">"აკრძალვა"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml index 759506b34939..101392d3ab99 100644 --- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml +++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Атын өзгерту"</string> <string name="rename_error" msgid="4203041674883412606">"Құжат қайта аталмады"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Кейбір файлдар түрлендірілді"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Рұқсат беру"</string> <string name="deny" msgid="2081879885755434506">"Бас тарту"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml index d83c1d391c5a..2ee35fe45fd7 100644 --- a/packages/DocumentsUI/res/values-km-rKH/strings.xml +++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"ប្ដូរឈ្មោះ"</string> <string name="rename_error" msgid="4203041674883412606">"បានបរាជ័យក្នុងការប្តូរឈ្មោះឯកសារ"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ឯកសារមួយចំនួនត្រូវបានបម្លែង"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត"</string> <string name="deny" msgid="2081879885755434506">"បដិសេធ"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-kn-rIN/strings.xml b/packages/DocumentsUI/res/values-kn-rIN/strings.xml index 57ddd0b5ebb3..b74d6a20431b 100644 --- a/packages/DocumentsUI/res/values-kn-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-kn-rIN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"ಮರುಹೆಸರಿಸು"</string> <string name="rename_error" msgid="4203041674883412606">"ಡಾಕ್ಯುಮೆಂಟ್ ಮರುಹೆಸರಿಸಲು ವಿಫಲವಾಗಿದೆ"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ಕೆಲವು ಫೈಲ್ಗಳನ್ನು ಪರಿವರ್ತಿಸಲಾಗಿದೆ"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"ಅನುಮತಿಸು"</string> <string name="deny" msgid="2081879885755434506">"ನಿರಾಕರಿಸು"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml index 907802df36b4..3c2da975504c 100644 --- a/packages/DocumentsUI/res/values-ko/strings.xml +++ b/packages/DocumentsUI/res/values-ko/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"이름 바꾸기"</string> <string name="rename_error" msgid="4203041674883412606">"문서 이름을 변경하지 못했습니다."</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"일부 파일이 변환되었습니다."</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"허용"</string> <string name="deny" msgid="2081879885755434506">"거부"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml index 699e76a277bd..865e717ced16 100644 --- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml +++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Аталышын өзгөртүү"</string> <string name="rename_error" msgid="4203041674883412606">"Документтин аталышы өзгөртүлбөй калды"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Айрым файлдардын форматы өзгөртүлдү"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Уруксат берүү"</string> <string name="deny" msgid="2081879885755434506">"Жок"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml index 468853b99a9c..4f4a3753995a 100644 --- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml +++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"ປ່ຽນຊື່"</string> <string name="rename_error" msgid="4203041674883412606">"ປ່ຽນຊື່ເອກະສານບໍ່ສຳເລັດ"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ປ່ຽນແປງບາງໄຟລ໌ແລ້ວ"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"ອະນຸຍາດ"</string> <string name="deny" msgid="2081879885755434506">"ປະຕິເສດ"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml index a6297bec65dd..fa653fc96392 100644 --- a/packages/DocumentsUI/res/values-lt/strings.xml +++ b/packages/DocumentsUI/res/values-lt/strings.xml @@ -124,6 +124,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Pervardyti"</string> <string name="rename_error" msgid="4203041674883412606">"Nepavyko pervardyti dokumento"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Kai kurie failai buvo konvertuoti"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Leisti"</string> <string name="deny" msgid="2081879885755434506">"Atmesti"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml index 1a9b77c065d7..8fd73e4dd412 100644 --- a/packages/DocumentsUI/res/values-lv/strings.xml +++ b/packages/DocumentsUI/res/values-lv/strings.xml @@ -117,6 +117,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Pārdēvēt"</string> <string name="rename_error" msgid="4203041674883412606">"Neizdevās pārdēvēt dokumentu"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Daži faili tika pārveidoti."</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Atļaut"</string> <string name="deny" msgid="2081879885755434506">"Noraidīt"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml index 5bbf8c5d5ee9..12455da1e7f6 100644 --- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml +++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Преименувај"</string> <string name="rename_error" msgid="4203041674883412606">"Не успеа да се преименува документот"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Некои датотеки беа конвертирани"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Дозволи"</string> <string name="deny" msgid="2081879885755434506">"Одбиј"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ml-rIN/strings.xml b/packages/DocumentsUI/res/values-ml-rIN/strings.xml index 264d196df594..0c0420d568fa 100644 --- a/packages/DocumentsUI/res/values-ml-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-ml-rIN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"പേരുമാറ്റുക"</string> <string name="rename_error" msgid="4203041674883412606">"ഡോക്യുമെന്റിന്റെ പേരുമാറ്റുന്നത് പരാജയപ്പെട്ടു"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ചില ഫയലുകൾ പരിവർത്തനം ചെയ്യപ്പെട്ടു"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"അനുവദിക്കുക"</string> <string name="deny" msgid="2081879885755434506">"നിരസിക്കുക"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml index 02c818b66590..2af8556ebd39 100644 --- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml +++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Нэр өөрчлөх"</string> <string name="rename_error" msgid="4203041674883412606">"Баримт бичгийн нэрийн өөрчилж чадсангүй"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Зарим файлыг хөрвүүлсэн"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Зөвшөөрөх"</string> <string name="deny" msgid="2081879885755434506">"Татгалзах"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml index 6fae5787212e..6256a9954380 100644 --- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"पुनर्नामित करा"</string> <string name="rename_error" msgid="4203041674883412606">"दस्तऐवज पुनर्नामित करण्यात अयशस्वी झाले"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"काही फायली रूपांतरित केल्या होत्या"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"अनुमती द्या"</string> <string name="deny" msgid="2081879885755434506">"नकार द्या"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml index 6f7c5256c8a2..df896a20bb99 100644 --- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml +++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Namakan semula"</string> <string name="rename_error" msgid="4203041674883412606">"Gagal menamakan semula dokumen"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sesetengah fail telah ditukarkan"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Benarkan"</string> <string name="deny" msgid="2081879885755434506">"Nafi"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-my-rMM/strings.xml b/packages/DocumentsUI/res/values-my-rMM/strings.xml index 9fb7f84cbdd7..14193b22f346 100644 --- a/packages/DocumentsUI/res/values-my-rMM/strings.xml +++ b/packages/DocumentsUI/res/values-my-rMM/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"အမည်ပြောင်းရန်"</string> <string name="rename_error" msgid="4203041674883412606">"စာရွက်စာတမ်းကို အမည်ပြောင်းခြင်း မအောင်မြင်ပါ"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"အချို့ဖိုင်များကို ပြောင်းလဲထားသည်"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"ခွင့်ပြုသည်"</string> <string name="deny" msgid="2081879885755434506">"ငြင်းပယ်သည်"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml index 0e48f0f29360..7d37078e11d1 100644 --- a/packages/DocumentsUI/res/values-nb/strings.xml +++ b/packages/DocumentsUI/res/values-nb/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Gi nytt navn"</string> <string name="rename_error" msgid="4203041674883412606">"Kunne ikke gi dokumentet nytt navn"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Noen filer er konvertert"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Tillat"</string> <string name="deny" msgid="2081879885755434506">"Avslå"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ne-rNP/strings.xml b/packages/DocumentsUI/res/values-ne-rNP/strings.xml index cc70c91d36f8..5a06cd266f17 100644 --- a/packages/DocumentsUI/res/values-ne-rNP/strings.xml +++ b/packages/DocumentsUI/res/values-ne-rNP/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"पुन: नामाकरण गर्नुहोस्"</string> <string name="rename_error" msgid="4203041674883412606">"कागजात पुन: नामाकरण गर्न असफल भयो"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"केही फाइलहरू परिवर्तन गरिएका थिए"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"अनुमति दिनुहोस्"</string> <string name="deny" msgid="2081879885755434506">"अस्वीकार गर्नुहोस्"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml index ebddf54cc27c..0e022af1ba2d 100644 --- a/packages/DocumentsUI/res/values-nl/strings.xml +++ b/packages/DocumentsUI/res/values-nl/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Naam wijzigen"</string> <string name="rename_error" msgid="4203041674883412606">"Kan naam van document niet wijzigen"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige bestanden zijn geconverteerd"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Toestaan"</string> <string name="deny" msgid="2081879885755434506">"Weigeren"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml index a8c65e74e6ba..4cfe638860b6 100644 --- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"ਮੁੜ-ਨਾਮਕਰਨ ਕਰੋ"</string> <string name="rename_error" msgid="4203041674883412606">"ਦਸਤਾਵੇਜ਼ ਦਾ ਮੁੜ-ਨਾਮਕਰਨ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ਕੁਝ ਫ਼ਾਈਲਾਂ ਤਬਦੀਲ ਕੀਤੀਆਂ ਗਈਆਂ ਸਨ"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"ਆਗਿਆ ਦਿਓ"</string> <string name="deny" msgid="2081879885755434506">"ਅਸਵੀਕਾਰ ਕਰੋ"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml index e888fd7b4482..b10d8a25152c 100644 --- a/packages/DocumentsUI/res/values-pl/strings.xml +++ b/packages/DocumentsUI/res/values-pl/strings.xml @@ -124,6 +124,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Zmień nazwę"</string> <string name="rename_error" msgid="4203041674883412606">"Nie udało się zmienić nazwy dokumentu"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektóre pliki zostały przekonwertowane"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Zezwól"</string> <string name="deny" msgid="2081879885755434506">"Odmów"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml index 213e76a5ed7d..26ec421e21b8 100644 --- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml +++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Renomear"</string> <string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Permitir"</string> <string name="deny" msgid="2081879885755434506">"Negar"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml index 2c74e6776e1b..490c4d71e75c 100644 --- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml +++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Mudar o nome"</string> <string name="rename_error" msgid="4203041674883412606">"Falha ao mudar o nome do documento"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns ficheiros foram convertidos"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Permitir"</string> <string name="deny" msgid="2081879885755434506">"Recusar"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml index 213e76a5ed7d..26ec421e21b8 100644 --- a/packages/DocumentsUI/res/values-pt/strings.xml +++ b/packages/DocumentsUI/res/values-pt/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Renomear"</string> <string name="rename_error" msgid="4203041674883412606">"Falha ao renomear documento"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Permitir"</string> <string name="deny" msgid="2081879885755434506">"Negar"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml index e57d1ab47e32..ef34f3a20097 100644 --- a/packages/DocumentsUI/res/values-ro/strings.xml +++ b/packages/DocumentsUI/res/values-ro/strings.xml @@ -117,6 +117,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Redenumiți"</string> <string name="rename_error" msgid="4203041674883412606">"Documentul nu a putut fi redenumit"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Unele fișiere au fost convertite"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Permiteți"</string> <string name="deny" msgid="2081879885755434506">"Refuzați"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml index 9c0f03140eac..b94b2a5e7cdf 100644 --- a/packages/DocumentsUI/res/values-ru/strings.xml +++ b/packages/DocumentsUI/res/values-ru/strings.xml @@ -124,6 +124,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Переименовать"</string> <string name="rename_error" msgid="4203041674883412606">"Не удалось переименовать документ"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Формат некоторых файлов изменен"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Разрешить"</string> <string name="deny" msgid="2081879885755434506">"Отклонить"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-si-rLK/strings.xml b/packages/DocumentsUI/res/values-si-rLK/strings.xml index a34aa88dc692..a0d764e336b9 100644 --- a/packages/DocumentsUI/res/values-si-rLK/strings.xml +++ b/packages/DocumentsUI/res/values-si-rLK/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"යළි නම් කරන්න"</string> <string name="rename_error" msgid="4203041674883412606">"ලේඛනය යළි නම් කිරීම අසාර්ථක විය"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"සමහර ගොනු පරිවර්තනය කරන ලදී"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"අවසර දෙන්න"</string> <string name="deny" msgid="2081879885755434506">"ප්රතික්ෂේප කරන්න"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml index 113381511ff6..06b7a10b482a 100644 --- a/packages/DocumentsUI/res/values-sk/strings.xml +++ b/packages/DocumentsUI/res/values-sk/strings.xml @@ -124,6 +124,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Premenovať"</string> <string name="rename_error" msgid="4203041674883412606">"Premenovanie dokumentu zlyhalo"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektoré súbory boli konvertované"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Povoliť"</string> <string name="deny" msgid="2081879885755434506">"Zamietnuť"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml index f2c691dfebc2..ee7bdc9aec91 100644 --- a/packages/DocumentsUI/res/values-sl/strings.xml +++ b/packages/DocumentsUI/res/values-sl/strings.xml @@ -124,6 +124,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Preimenuj"</string> <string name="rename_error" msgid="4203041674883412606">"Dokumenta ni bilo mogoče preimenovati"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nekatere datoteke so bile pretvorjene"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Dovoli"</string> <string name="deny" msgid="2081879885755434506">"Zavrni"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml index 80ae0007af2f..352da58dda7b 100644 --- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml +++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Riemërto"</string> <string name="rename_error" msgid="4203041674883412606">"Riemërtimi i dokumentit dështoi"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Disa skedarë u konvertuan"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Lejo"</string> <string name="deny" msgid="2081879885755434506">"Moho"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml index be96db60e581..0ba3da1f8c30 100644 --- a/packages/DocumentsUI/res/values-sr/strings.xml +++ b/packages/DocumentsUI/res/values-sr/strings.xml @@ -117,6 +117,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Преименуј"</string> <string name="rename_error" msgid="4203041674883412606">"Преименовање документа није успело"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Неке датотеке су конвертоване"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Дозволи"</string> <string name="deny" msgid="2081879885755434506">"Одбиј"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml index 7fd4be072d8b..081c331e2ea7 100644 --- a/packages/DocumentsUI/res/values-sv/strings.xml +++ b/packages/DocumentsUI/res/values-sv/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Byt namn"</string> <string name="rename_error" msgid="4203041674883412606">"Det gick inte att byta namn på dokumentet"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Vissa filer konverterades"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Tillåt"</string> <string name="deny" msgid="2081879885755434506">"Neka"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml index 2730ce9b6c7d..fc4d555208e2 100644 --- a/packages/DocumentsUI/res/values-sw/strings.xml +++ b/packages/DocumentsUI/res/values-sw/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Badilisha jina"</string> <string name="rename_error" msgid="4203041674883412606">"Imeshindwa kubadilisha jina la hati"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Baadhi ya faili zimebadilishwa muundo"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Ruhusu"</string> <string name="deny" msgid="2081879885755434506">"Kataza"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml index 881e05a8305a..30bdc9dd588e 100644 --- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"மறுபெயரிடு"</string> <string name="rename_error" msgid="4203041674883412606">"ஆவணத்திற்கு மறுபெயரிடுவதில் தோல்வி"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"சில கோப்புகள் மாற்றப்பட்டன"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"அனுமதி"</string> <string name="deny" msgid="2081879885755434506">"நிராகரி"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-te-rIN/strings.xml b/packages/DocumentsUI/res/values-te-rIN/strings.xml index 0043ddc55e37..c11840a22201 100644 --- a/packages/DocumentsUI/res/values-te-rIN/strings.xml +++ b/packages/DocumentsUI/res/values-te-rIN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"పేరు మార్చు"</string> <string name="rename_error" msgid="4203041674883412606">"పత్రం పేరు మార్చడంలో విఫలమైంది"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"కొన్ని పైల్లు మార్చబడ్డాయి"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"అనుమతించండి"</string> <string name="deny" msgid="2081879885755434506">"తిరస్కరించండి"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml index 8b24210dfe30..aba869c42895 100644 --- a/packages/DocumentsUI/res/values-th/strings.xml +++ b/packages/DocumentsUI/res/values-th/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"เปลี่ยนชื่อ"</string> <string name="rename_error" msgid="4203041674883412606">"ไม่สามารถเปลี่ยนชื่อเอกสาร"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"แปลงบางไฟล์แล้ว"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"อนุญาต"</string> <string name="deny" msgid="2081879885755434506">"ปฏิเสธ"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml index 9849b8597367..a76a30623ac7 100644 --- a/packages/DocumentsUI/res/values-tl/strings.xml +++ b/packages/DocumentsUI/res/values-tl/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Palitan ang pangalan"</string> <string name="rename_error" msgid="4203041674883412606">"Hindi napalitan ang pangalan ng dokumento"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Na-convert ang ilang file"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Payagan"</string> <string name="deny" msgid="2081879885755434506">"Tanggihan"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml index 8df52d205f56..f5e6258d88a6 100644 --- a/packages/DocumentsUI/res/values-tr/strings.xml +++ b/packages/DocumentsUI/res/values-tr/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Yeniden Adlandır"</string> <string name="rename_error" msgid="4203041674883412606">"Dokümanın adı değiştirilemedi"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bazı dosyalar dönüştürüldü"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"İzin Ver"</string> <string name="deny" msgid="2081879885755434506">"Reddet"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml index d5a1fcd36429..9c4b054406be 100644 --- a/packages/DocumentsUI/res/values-uk/strings.xml +++ b/packages/DocumentsUI/res/values-uk/strings.xml @@ -124,6 +124,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Перейменувати"</string> <string name="rename_error" msgid="4203041674883412606">"Не вдалося перейменувати документ"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Деякі файли конвертовано"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Дозвол."</string> <string name="deny" msgid="2081879885755434506">"Забор."</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml index 846555a5721a..2d4804c4b14c 100644 --- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml +++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"نام تبدیل کریں"</string> <string name="rename_error" msgid="4203041674883412606">"دستاویز کا نام تبدیل کرنے میں ناکام"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"کچھ فائلوں کو تبدیل کیا گیا تھا"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"اجازت دیں"</string> <string name="deny" msgid="2081879885755434506">"مسترد کریں"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml index 0e1ac5aee187..0a0992176461 100644 --- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml +++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Qayta nomlash"</string> <string name="rename_error" msgid="4203041674883412606">"Hujjatni qayta nomlab bo‘lmadi"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bir nechta fayllar o‘girildi"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Ruxsat berish"</string> <string name="deny" msgid="2081879885755434506">"Rad qilish"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> @@ -117,7 +121,7 @@ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta fayl o‘chirilsinmi?</item> </plurals> <plurals name="elements_selected" formatted="false" msgid="1376955402452875047"> - <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta tanlandi</item> - <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta tanlandi</item> + <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta belgilandi</item> + <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta belgilandi</item> </plurals> </resources> diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml index c3c16f44d4d1..9aca29f27acc 100644 --- a/packages/DocumentsUI/res/values-vi/strings.xml +++ b/packages/DocumentsUI/res/values-vi/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Đổi tên"</string> <string name="rename_error" msgid="4203041674883412606">"Không đổi được tên tài liệu"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Đã chuyển đổi một số tệp"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Cho phép"</string> <string name="deny" msgid="2081879885755434506">"Từ chối"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml index 7f479ff7646f..75dcfbc0aa10 100644 --- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml +++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"重命名"</string> <string name="rename_error" msgid="4203041674883412606">"无法重命名文档"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"允许"</string> <string name="deny" msgid="2081879885755434506">"拒绝"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml index f22e27e7458a..b834a11e5c4d 100644 --- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml +++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"重新命名"</string> <string name="rename_error" msgid="4203041674883412606">"無法重新命名文件"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"允許"</string> <string name="deny" msgid="2081879885755434506">"拒絕"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml index a5ede47a5fab..d6e270afb3b0 100644 --- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml +++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"重新命名"</string> <string name="rename_error" msgid="4203041674883412606">"無法重新命名文件"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"允許"</string> <string name="deny" msgid="2081879885755434506">"拒絕"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml index b99ab8c173c6..35864a7cb4e4 100644 --- a/packages/DocumentsUI/res/values-zu/strings.xml +++ b/packages/DocumentsUI/res/values-zu/strings.xml @@ -110,6 +110,10 @@ <string name="menu_rename" msgid="7678802479104285353">"Qamba kabusha"</string> <string name="rename_error" msgid="4203041674883412606">"Yehlulekile ukuqamba kabusha idokhumenti"</string> <string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Amanye amafayela aguqulelwe"</string> + <!-- no translation found for open_external_dialog_request (5789329484285817629) --> + <skip /> + <!-- no translation found for never_ask_again (4295278542972859268) --> + <skip /> <string name="allow" msgid="7225948811296386551">"Vumela"</string> <string name="deny" msgid="2081879885755434506">"Yala"</string> <plurals name="delete_confirmation_message" formatted="false" msgid="3519107568984207772"> diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml index e2d1870cb122..e7406e68302d 100644 --- a/packages/DocumentsUI/res/values/strings.xml +++ b/packages/DocumentsUI/res/values/strings.xml @@ -200,10 +200,12 @@ during a copy. [CHAR LIMIT=48] --> <string name="notification_copy_files_converted_title">Some files were converted</string> - <!-- DO NOT TRANSLATE - final phrase has not been decided yet (b/26750152) --> + <!-- Text in an alert dialog asking user to grant app access to a given directory in an external storage volume --> <string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g> - access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> folder on + access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory on <xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string> + <!-- Checkbox that allows user to not be questioned about the directory access request again --> + <string name="never_ask_again">Don\'t ask again</string> <!-- Text in the button asking user to allow access to a given directory. --> <string name="allow">Allow</string> <!-- Text in the button asking user to deny access to a given directory. --> diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml index 21bdfd9ec53c..a548d89838f1 100644 --- a/packages/DocumentsUI/res/values/styles.xml +++ b/packages/DocumentsUI/res/values/styles.xml @@ -46,8 +46,4 @@ <item name="android:maxHeight">3dp</item> </style> - <!-- TODO: use the proper dialog and/or inline if not overriding --> - <style name="AlertDialogTheme" parent="@style/Theme.AppCompat.Light.Dialog.Alert"> - </style> - </resources> diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java index 1a8ce18ce03d..fe61094e56d4 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java @@ -17,6 +17,7 @@ package com.android.documentsui; import static com.android.documentsui.Shared.DEBUG; +import static com.android.documentsui.Shared.EXTRA_BENCHMARK; import static com.android.documentsui.State.MODE_GRID; import android.app.Activity; @@ -30,6 +31,9 @@ import android.content.pm.ProviderInfo; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; +import android.os.Handler; +import android.os.MessageQueue; +import android.os.MessageQueue.IdleHandler; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Root; import android.support.annotation.CallSuper; @@ -60,6 +64,8 @@ import java.util.concurrent.Executor; public abstract class BaseActivity extends Activity implements SearchManagerListener, NavigationView.Environment { + private static final String BENCHMARK_TESTING_PACKAGE = "com.android.documentsui.appperftests"; + State mState; RootsCache mRoots; SearchViewManager mSearchManager; @@ -92,11 +98,20 @@ public abstract class BaseActivity extends Activity public void onCreate(Bundle icicle) { super.onCreate(icicle); + final Intent intent = getIntent(); + + // If startup benchmark is requested by a whitelisted testing package, then close the + // activity once idle, and notify the testing activity. + if (intent.getBooleanExtra(EXTRA_BENCHMARK, false) && + BENCHMARK_TESTING_PACKAGE.equals(getCallingPackage())) { + closeOnIdleForTesting(); + } + setContentView(mLayoutId); mDrawer = DrawerController.create(this); mState = getState(icicle); - Metrics.logActivityLaunch(this, mState, getIntent()); + Metrics.logActivityLaunch(this, mState, intent); mRoots = DocumentsApplication.getRootsCache(this); @@ -668,9 +683,36 @@ public abstract class BaseActivity extends Activity } } + /** + * Closes the activity when it's idle. Used only for tests. + */ + private void closeOnIdleForTesting() { + addEventListener(new EventListener() { + @Override + public void onDirectoryNavigated(Uri uri) { + } + + @Override + public void onDirectoryLoaded(Uri uri) { + getMainLooper().getQueue().addIdleHandler(new IdleHandler() { + @Override + public boolean queueIdle() { + setResult(RESULT_OK); + finish(); + return false; + } + }); + new Handler().post(new Runnable() { + @Override public void run() { + } + }); + } + }); + } + private static final class HandleRootsChangedTask extends PairedTask<BaseActivity, RootInfo, RootInfo> { - DocumentInfo mHome; + DocumentInfo mDownloadsDocument; public HandleRootsChangedTask(BaseActivity activity) { super(activity); @@ -682,28 +724,28 @@ public abstract class BaseActivity extends Activity final RootInfo currentRoot = roots[0]; final Collection<RootInfo> cachedRoots = mOwner.mRoots.getRootsBlocking(); - RootInfo homeRoot = null; + RootInfo downloadsRoot = null; for (final RootInfo root : cachedRoots) { - if (root.isHome()) { - homeRoot = root; + if (root.isDownloads()) { + downloadsRoot = root; } if (root.getUri().equals(currentRoot.getUri())) { // We don't need to change the current root as the current root was not removed. return null; } } - assert(homeRoot != null); - mHome = mOwner.getRootDocumentBlocking(homeRoot); - return homeRoot; + assert(downloadsRoot != null); + mDownloadsDocument = mOwner.getRootDocumentBlocking(downloadsRoot); + return downloadsRoot; } @Override - protected void finish(RootInfo homeRoot) { - if (homeRoot != null && mHome != null) { + protected void finish(RootInfo downloadsRoot) { + if (downloadsRoot != null && mDownloadsDocument != null) { // Clear entire backstack and start in new root - mOwner.mState.onRootChanged(homeRoot); - mOwner.mSearchManager.update(homeRoot); - mOwner.openContainerDocument(mHome); + mOwner.mState.onRootChanged(downloadsRoot); + mOwner.mSearchManager.update(downloadsRoot); + mOwner.openContainerDocument(mDownloadsDocument); } } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/BootReceiver.java b/packages/DocumentsUI/src/com/android/documentsui/BootReceiver.java new file mode 100644 index 000000000000..cdea9d75fd82 --- /dev/null +++ b/packages/DocumentsUI/src/com/android/documentsui/BootReceiver.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016 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.documentsui; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +/** + * Prime {@link RootsCache} when the system is booted. + */ +public class BootReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + // We already spun up our application object before getting here, which + // kicked off a task to load roots, so this broadcast is finished once + // that first pass is done. + DocumentsApplication.getRootsCache(context).setBootCompletedResult(goAsync()); + } +} diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java index c7c61c3189ac..8c4859f52a02 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java +++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java @@ -16,10 +16,20 @@ package com.android.documentsui; +import static com.android.documentsui.Shared.DEBUG; +import static com.android.documentsui.Shared.TAG; import static com.android.documentsui.State.MODE_UNKNOWN; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import android.annotation.IntDef; +import android.annotation.Nullable; import android.content.Context; +import android.content.SharedPreferences; +import android.os.UserHandle; import android.preference.PreferenceManager; +import android.util.Log; import com.android.documentsui.State.ViewMode; import com.android.documentsui.model.RootInfo; @@ -29,29 +39,73 @@ public class LocalPreferences { private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-"; public static boolean getDisplayFileSize(Context context) { - return PreferenceManager.getDefaultSharedPreferences(context) - .getBoolean(KEY_FILE_SIZE, false); + return getPrefs(context).getBoolean(KEY_FILE_SIZE, false); } - public static @ViewMode int getViewMode( - Context context, RootInfo root, @ViewMode int fallback) { - return PreferenceManager.getDefaultSharedPreferences(context) - .getInt(createKey(root), fallback); + public static @ViewMode int getViewMode(Context context, RootInfo root, + @ViewMode int fallback) { + return getPrefs(context).getInt(createKey(root), fallback); } public static void setDisplayFileSize(Context context, boolean display) { - PreferenceManager.getDefaultSharedPreferences(context).edit() - .putBoolean(KEY_FILE_SIZE, display).apply(); + getPrefs(context).edit().putBoolean(KEY_FILE_SIZE, display).apply(); } public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) { assert(viewMode != MODE_UNKNOWN); - PreferenceManager.getDefaultSharedPreferences(context).edit() - .putInt(createKey(root), viewMode).apply(); + getPrefs(context).edit().putInt(createKey(root), viewMode).apply(); + } + + private static SharedPreferences getPrefs(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context); } private static String createKey(RootInfo root) { return ROOT_VIEW_MODE_PREFIX + root.authority + root.rootId; } + + public static final int PERMISSION_ASK = 0; + public static final int PERMISSION_ASK_AGAIN = 1; + public static final int PERMISSION_NEVER_ASK = -1; + + @IntDef(flag = true, value = { + PERMISSION_ASK, + PERMISSION_ASK_AGAIN, + PERMISSION_NEVER_ASK, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PermissionStatus {} + + /** + * Methods below are used to keep track of denied user requests on scoped directory access so + * the dialog is not offered when user checked the 'Do not ask again' box + * + * <p>It uses a shared preferences, whose key is: + * <ol> + * <li>{@code USER_ID|PACKAGE_NAME|VOLUME_UUID|DIRECTORY} for storage volumes that have a UUID + * (typically physical volumes like SD cards). + * <li>{@code USER_ID|PACKAGE_NAME||DIRECTORY} for storage volumes that do not have a UUID + * (typically the emulated volume used for primary storage + * </ol> + */ + static @PermissionStatus int getScopedAccessPermissionStatus(Context context, + String packageName, @Nullable String uuid, String directory) { + final String key = getScopedAccessDenialsKey(packageName, uuid, directory); + return getPrefs(context).getInt(key, PERMISSION_ASK); + } + + static void setScopedAccessPermissionStatus(Context context, String packageName, + @Nullable String uuid, String directory, @PermissionStatus int status) { + final String key = getScopedAccessDenialsKey(packageName, uuid, directory); + getPrefs(context).edit().putInt(key, status).apply(); + } + + private static String getScopedAccessDenialsKey(String packageName, String uuid, + String directory) { + final int userId = UserHandle.myUserId(); + return uuid == null + ? userId + "|" + packageName + "||" + directory + : userId + "|" + packageName + "|" + uuid + "|" + directory; + } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java index afd308cc97a7..deef1c278e63 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java @@ -411,11 +411,15 @@ public final class Metrics { public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0; public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1; public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2; + public static final int SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST = 3; + public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED = 4; @IntDef(flag = true, value = { SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED, SCOPED_DIRECTORY_ACCESS_GRANTED, - SCOPED_DIRECTORY_ACCESS_DENIED + SCOPED_DIRECTORY_ACCESS_DENIED, + SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST, + SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED }) @Retention(RetentionPolicy.SOURCE) public @interface ScopedAccessGrant {} @@ -432,23 +436,34 @@ public final class Metrics { final String packageName = activity.getCallingPackage(); switch (type) { case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED: - MetricsLogger.action(activity, - MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE, - packageName); - MetricsLogger.action(activity, - MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index); + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE, packageName); + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index); break; case SCOPED_DIRECTORY_ACCESS_GRANTED: - MetricsLogger.action(activity, - MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName); - MetricsLogger.action(activity, - MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index); + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName); + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index); break; case SCOPED_DIRECTORY_ACCESS_DENIED: - MetricsLogger.action(activity, - MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName); - MetricsLogger.action(activity, - MetricsEvent.ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index); + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName); + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index); + break; + case SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST: + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE, packageName); + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER, index); + break; + case SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED: + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE, packageName); + MetricsLogger.action(activity, MetricsEvent + .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER, index); break; default: Log.wtf(TAG, "invalid ScopedAccessGrant: " + type); diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java index dc529ceb18ec..2b6f3968e203 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java +++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java @@ -20,16 +20,24 @@ import static android.os.Environment.isStandardDirectory; import static android.os.Environment.STANDARD_DIRECTORIES; import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME; import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME; -import static com.android.documentsui.Shared.DEBUG; -import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest; -import static com.android.documentsui.Metrics.logValidScopedAccessRequest; +import static com.android.documentsui.LocalPreferences.getScopedAccessPermissionStatus; +import static com.android.documentsui.LocalPreferences.PERMISSION_ASK; +import static com.android.documentsui.LocalPreferences.PERMISSION_ASK_AGAIN; +import static com.android.documentsui.LocalPreferences.PERMISSION_NEVER_ASK; +import static com.android.documentsui.LocalPreferences.setScopedAccessPermissionStatus; +import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED; import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED; import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED; +import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST; import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_ERROR; import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_GRANTED; import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS; import static com.android.documentsui.Metrics.SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY; +import static com.android.documentsui.Metrics.logInvalidScopedAccessRequest; +import static com.android.documentsui.Metrics.logValidScopedAccessRequest; +import static com.android.documentsui.Shared.DEBUG; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; @@ -38,7 +46,6 @@ import android.app.DialogFragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.ContentProviderClient; -import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; @@ -57,6 +64,11 @@ import android.os.storage.VolumeInfo; import android.provider.DocumentsContract; import android.text.TextUtils; import android.util.Log; +import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.TextView; import java.io.File; import java.io.IOException; @@ -72,12 +84,17 @@ public class OpenExternalDirectoryActivity extends Activity { private static final String EXTRA_FILE = "com.android.documentsui.FILE"; private static final String EXTRA_APP_LABEL = "com.android.documentsui.APP_LABEL"; private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL"; + private static final String EXTRA_VOLUME_UUID = "com.android.documentsui.VOLUME_UUID"; private ContentProviderClient mExternalStorageClient; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (savedInstanceState != null) { + if (DEBUG) Log.d(TAG, "activity.onCreateDialog(): reusing instance"); + return; + } final Intent intent = getIntent(); if (intent == null) { @@ -105,9 +122,18 @@ public class OpenExternalDirectoryActivity extends Activity { finish(); return; } + final StorageVolume volume = (StorageVolume) storageVolume; + if (getScopedAccessPermissionStatus(getApplicationContext(), getCallingPackage(), + volume.getUuid(), directoryName) == PERMISSION_NEVER_ASK) { + logValidScopedAccessRequest(this, directoryName, + SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED); + setResult(RESULT_CANCELED); + finish(); + return; + } final int userId = UserHandle.myUserId(); - if (!showFragment(this, userId, (StorageVolume) storageVolume, directoryName)) { + if (!showFragment(this, userId, volume, directoryName)) { setResult(RESULT_CANCELED); finish(); return; @@ -157,6 +183,7 @@ public class OpenExternalDirectoryActivity extends Activity { // Gets volume label and converted path. String volumeLabel = null; + String volumeUuid = null; final List<VolumeInfo> volumes = sm.getVolumes(); if (DEBUG) Log.d(TAG, "Number of volumes: " + volumes.size()); for (VolumeInfo volume : volumes) { @@ -166,6 +193,7 @@ public class OpenExternalDirectoryActivity extends Activity { if (DEBUG) Log.d(TAG, "Converting " + root + " to " + internalRoot); file = new File(internalRoot, directory); volumeLabel = sm.getBestVolumeDescription(volume); + volumeUuid = volume.getFsUuid(); break; } } @@ -197,6 +225,7 @@ public class OpenExternalDirectoryActivity extends Activity { final Bundle args = new Bundle(); args.putString(EXTRA_FILE, file.getAbsolutePath()); args.putString(EXTRA_VOLUME_LABEL, volumeLabel); + args.putString(EXTRA_VOLUME_UUID, volumeUuid); args.putString(EXTRA_APP_LABEL, appLabel); final FragmentManager fm = activity.getFragmentManager(); @@ -303,16 +332,21 @@ public class OpenExternalDirectoryActivity extends Activity { public static class OpenExternalDirectoryDialogFragment extends DialogFragment { private File mFile; + private String mVolumeUuid; private String mVolumeLabel; private String mAppLabel; + private CheckBox mDontAskAgain; private OpenExternalDirectoryActivity mActivity; + private AlertDialog mDialog; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setRetainInstance(true); final Bundle args = getArguments(); if (args != null) { mFile = new File(args.getString(EXTRA_FILE)); + mVolumeUuid = args.getString(EXTRA_VOLUME_UUID); mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL); mAppLabel = args.getString(EXTRA_APP_LABEL); } @@ -320,9 +354,28 @@ public class OpenExternalDirectoryActivity extends Activity { } @Override + public void onDestroyView() { + // Workaround for https://code.google.com/p/android/issues/detail?id=17423 + if (mDialog != null && getRetainInstance()) { + mDialog.setDismissMessage(null); + } + super.onDestroyView(); + } + + @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + if (mDialog != null) { + if (DEBUG) Log.d(TAG, "fragment.onCreateDialog(): reusing dialog"); + return mDialog; + } + if (mActivity != getActivity()) { + // Sanity check. + Log.wtf(TAG, "activity references don't match on onCreateDialog(): mActivity = " + + mActivity + " , getActivity() = " + getActivity()); + mActivity = (OpenExternalDirectoryActivity) getActivity(); + } final String directory = mFile.getName(); - final Activity activity = getActivity(); + final Context context = mActivity.getApplicationContext(); final OnClickListener listener = new OnClickListener() { @Override @@ -333,15 +386,25 @@ public class OpenExternalDirectoryActivity extends Activity { mActivity.getExternalStorageClient(), mFile); } if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) { - logValidScopedAccessRequest(activity, directory, + logValidScopedAccessRequest(mActivity, directory, SCOPED_DIRECTORY_ACCESS_DENIED); - activity.setResult(RESULT_CANCELED); + final boolean checked = mDontAskAgain.isChecked(); + if (checked) { + logValidScopedAccessRequest(mActivity, directory, + SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST); + setScopedAccessPermissionStatus(context, mActivity.getCallingPackage(), + mVolumeUuid, directory, PERMISSION_NEVER_ASK); + } else { + setScopedAccessPermissionStatus(context, mActivity.getCallingPackage(), + mVolumeUuid, directory, PERMISSION_ASK_AGAIN); + } + mActivity.setResult(RESULT_CANCELED); } else { - logValidScopedAccessRequest(activity, directory, + logValidScopedAccessRequest(mActivity, directory, SCOPED_DIRECTORY_ACCESS_GRANTED); - activity.setResult(RESULT_OK, intent); + mActivity.setResult(RESULT_OK, intent); } - activity.finish(); + mActivity.finish(); } }; @@ -349,11 +412,31 @@ public class OpenExternalDirectoryActivity extends Activity { .expandTemplate( getText(R.string.open_external_dialog_request), mAppLabel, directory, mVolumeLabel); - return new AlertDialog.Builder(activity, R.style.AlertDialogTheme) - .setMessage(message) + @SuppressLint("InflateParams") + // It's ok pass null ViewRoot on AlertDialogs. + final View view = View.inflate(mActivity, R.layout.dialog_open_scoped_directory, null); + final TextView messageField = (TextView) view.findViewById(R.id.message); + messageField.setText(message); + mDialog = new AlertDialog.Builder(mActivity, R.style.Theme_AppCompat_Light_Dialog_Alert) + .setView(view) .setPositiveButton(R.string.allow, listener) .setNegativeButton(R.string.deny, listener) .create(); + + mDontAskAgain = (CheckBox) view.findViewById(R.id.do_not_ask_checkbox); + if (getScopedAccessPermissionStatus(context, mActivity.getCallingPackage(), + mVolumeUuid, directory) == PERMISSION_ASK_AGAIN) { + mDontAskAgain.setVisibility(View.VISIBLE); + mDontAskAgain.setOnCheckedChangeListener(new OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(!isChecked); + } + }); + } + + return mDialog; } @Override diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java index 2b7294a6e6d8..6efe9c8fae83 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java +++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java @@ -18,6 +18,7 @@ package com.android.documentsui; import static com.android.documentsui.Shared.DEBUG; +import android.content.BroadcastReceiver.PendingResult; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; @@ -30,6 +31,7 @@ import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; +import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; import android.provider.DocumentsContract; @@ -40,11 +42,11 @@ import android.util.Log; import com.android.documentsui.model.RootInfo; import com.android.internal.annotations.GuardedBy; +import libcore.io.IoUtils; + import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; -import libcore.io.IoUtils; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -63,6 +65,8 @@ public class RootsCache { private static final String TAG = "RootsCache"; + private static final boolean ENABLE_SYSTEM_CACHE = true; + private final Context mContext; private final ContentObserver mObserver; private OnCacheUpdateListener mCacheUpdateListener; @@ -73,6 +77,11 @@ public class RootsCache { private final CountDownLatch mFirstLoad = new CountDownLatch(1); @GuardedBy("mLock") + private boolean mFirstLoadDone; + @GuardedBy("mLock") + private PendingResult mBootCompletedResult; + + @GuardedBy("mLock") private Multimap<String, RootInfo> mRoots = ArrayListMultimap.create(); @GuardedBy("mLock") private HashSet<String> mStoppedAuthorities = new HashSet<>(); @@ -118,7 +127,7 @@ public class RootsCache { public void updateAsync() { // NOTE: This method is called when the UI language changes. - // For that reason we upadte our RecentsRoot to reflect + // For that reason we update our RecentsRoot to reflect // the current language. mRecentsRoot.title = mContext.getString(R.string.root_recent); @@ -152,7 +161,25 @@ public class RootsCache { } } - private void waitForFirstLoad() { + public void setBootCompletedResult(PendingResult result) { + synchronized (mLock) { + // Quickly check if we've already finished loading, otherwise hang + // out until first pass is finished. + if (mFirstLoadDone) { + result.finish(); + } else { + mBootCompletedResult = result; + } + } + } + + /** + * Block until the first {@link UpdateTask} pass has finished. + * + * @return {@code true} if cached roots is ready to roll, otherwise + * {@code false} if we timed out while waiting. + */ + private boolean waitForFirstLoad() { boolean success = false; try { success = mFirstLoad.await(15, TimeUnit.SECONDS); @@ -161,6 +188,7 @@ public class RootsCache { if (!success) { Log.w(TAG, "Timeout waiting for first update"); } + return success; } /** @@ -222,9 +250,11 @@ public class RootsCache { final long start = SystemClock.elapsedRealtime(); if (mFilterPackage != null) { - // Need at least first load, since we're going to be using - // previously cached values for non-matching packages. - waitForFirstLoad(); + // We must have previously cached values to fill in non-matching + // packages, so wait around for successful first load. + if (!waitForFirstLoad()) { + return null; + } } mTaskRoots.put(mRecentsRoot.authority, mRecentsRoot); @@ -243,6 +273,11 @@ public class RootsCache { if (DEBUG) Log.d(TAG, "Update found " + mTaskRoots.size() + " roots in " + delta + "ms"); synchronized (mLock) { + mFirstLoadDone = true; + if (mBootCompletedResult != null) { + mBootCompletedResult.finish(); + mBootCompletedResult = null; + } mRoots = mTaskRoots; mStoppedAuthorities = mTaskStoppedAuthorities; } @@ -300,9 +335,18 @@ public class RootsCache { } } - final List<RootInfo> roots = new ArrayList<>(); final Uri rootsUri = DocumentsContract.buildRootsUri(authority); + if (ENABLE_SYSTEM_CACHE) { + // Look for roots data that we might have cached for ourselves in the + // long-lived system process. + final Bundle systemCache = resolver.getCache(rootsUri); + if (systemCache != null) { + if (DEBUG) Log.d(TAG, "System cache hit for " + authority); + return systemCache.getParcelableArrayList(TAG); + } + } + final ArrayList<RootInfo> roots = new ArrayList<>(); ContentProviderClient client = null; Cursor cursor = null; try { @@ -318,6 +362,16 @@ public class RootsCache { IoUtils.closeQuietly(cursor); ContentProviderClient.releaseQuietly(client); } + + if (ENABLE_SYSTEM_CACHE) { + // Cache these freshly parsed roots over in the long-lived system + // process, in case our process goes away. The system takes care of + // invalidating the cache if the package or Uri changes. + final Bundle systemCache = new Bundle(); + systemCache.putParcelableArrayList(TAG, roots); + resolver.putCache(rootsUri, systemCache); + } + return roots; } diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java index 26900a70fc06..c32bbff0c911 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java +++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java @@ -86,11 +86,10 @@ public final class Shared { */ public static final String EXTRA_IGNORE_STATE = "ignoreState"; - /** - * String prefix used to indicate the document is a directory. + * Extra for an Intent for enabling performance benchmark. Used only by tests. */ - public static final char DIR_PREFIX = '\001'; + public static final String EXTRA_BENCHMARK = "com.android.documentsui.benchmark"; private static final Collator sCollator; @@ -139,8 +138,7 @@ public final class Shared { /** * Compare two strings against each other using system default collator in a - * case-insensitive mode. Clusters strings prefixed with {@link DIR_PREFIX} - * before other items. + * case-insensitive mode. */ public static int compareToIgnoreCaseNullable(String lhs, String rhs) { final boolean leftEmpty = TextUtils.isEmpty(lhs); @@ -150,12 +148,6 @@ public final class Shared { if (leftEmpty) return -1; if (rightEmpty) return 1; - final boolean leftDir = (lhs.charAt(0) == DIR_PREFIX); - final boolean rightDir = (rhs.charAt(0) == DIR_PREFIX); - - if (leftDir && !rightDir) return -1; - if (rightDir && !leftDir) return 1; - return sCollator.compare(lhs, rhs); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java index bfc8d71c3fdf..63a834f85274 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -98,7 +98,6 @@ import com.android.documentsui.model.RootInfo; import com.android.documentsui.services.FileOperationService; import com.android.documentsui.services.FileOperationService.OpType; import com.android.documentsui.services.FileOperations; - import com.google.common.collect.Lists; import java.lang.annotation.Retention; @@ -165,6 +164,7 @@ public class DirectoryFragment extends Fragment private String mQuery = null; private Selection mSelection = null; private boolean mSearchMode = false; + private @Nullable ActionMode mActionMode; @Override public View onCreateView( @@ -406,9 +406,9 @@ public class DirectoryFragment extends Fragment int cellMargin = 2 * getResources().getDimensionPixelSize(R.dimen.grid_item_margin); int viewPadding = mRecView.getPaddingLeft() + mRecView.getPaddingRight(); - assert(mRecView.getWidth() > 0); - - int columnCount = Math.max(1, + // RecyclerView sometimes gets a width of 0 (see b/27150284). Clamp so that we always lay + // out the grid with at least 2 columns. + int columnCount = Math.max(2, (mRecView.getWidth() - viewPadding) / (cellWidth + cellMargin)); return columnCount; @@ -439,7 +439,7 @@ public class DirectoryFragment extends Fragment implements MultiSelectManager.Callback, ActionMode.Callback { private Selection mSelected = new Selection(); - private ActionMode mActionMode; + private int mNoCopyCount = 0; private int mNoDeleteCount = 0; private int mNoRenameCount = -1; private Menu mMenu; @@ -471,6 +471,9 @@ public class DirectoryFragment extends Fragment // triggered on "silent" selection updates (i.e. we might be reacting to unfinalized // selection changes here) final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS); + if ((docFlags & Document.FLAG_PARTIAL) != 0) { + mNoCopyCount += selected ? 1 : -1; + } if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0 && (docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) { mNoDeleteCount += selected ? 1 : -1; @@ -537,19 +540,24 @@ public class DirectoryFragment extends Fragment return true; } - boolean canRenameSelection() { - return mNoRenameCount == 0 && mSelectionManager.getSelection().size() == 1; + boolean canCopySelection() { + return mNoCopyCount == 0; } boolean canDeleteSelection() { return mNoDeleteCount == 0; } + boolean canRenameSelection() { + return mNoRenameCount == 0 && mSelectionManager.getSelection().size() == 1; + } + private void updateActionMenu() { assert(mMenu != null); // Delegate update logic to our owning action, since specialized logic is desired. - mTuner.updateActionMenu(mMenu, mType, canDeleteSelection(), canRenameSelection()); + mTuner.updateActionMenu( + mMenu, mType, canCopySelection(), canDeleteSelection(), canRenameSelection()); Menus.disableHiddenItems(mMenu); } @@ -569,10 +577,9 @@ public class DirectoryFragment extends Fragment return true; case R.id.menu_delete: - // Pass mode along to the delete function so it can - // end action mode when documents are deleted. + // deleteDocuments will end action mode if the documents are deleted. // It won't end action mode if user cancels the delete. - deleteDocuments(selection, mode); + deleteDocuments(selection); return true; case R.id.menu_copy_to: @@ -681,7 +688,7 @@ public class DirectoryFragment extends Fragment }.execute(selected); } - private void deleteDocuments(final Selection selected, final ActionMode mode) { + private void deleteDocuments(final Selection selected) { assert(!selected.isEmpty()); final DocumentInfo srcParent = getDisplayState().stack.peek(); @@ -718,7 +725,9 @@ public class DirectoryFragment extends Fragment // This is done here, rather in the onActionItemClicked // so we can avoid de-selecting items in the case where // the user cancels the delete. - mode.finish(); + if (mActionMode != null) { + mActionMode.finish(); + } // Hide the files in the UI...since the operation // might be queued up on FileOperationService. // We're walking a line here. @@ -1254,12 +1263,25 @@ public class DirectoryFragment extends Fragment } // Handle enter key events - if (keyCode == KeyEvent.KEYCODE_ENTER) { - if (event.isShiftPressed()) { - return onSelect(doc); - } else { + switch (keyCode) { + case KeyEvent.KEYCODE_ENTER: + if (event.isShiftPressed()) { + return onSelect(doc); + } + // For non-shifted enter keypresses, fall through. + case KeyEvent.KEYCODE_DPAD_CENTER: + case KeyEvent.KEYCODE_BUTTON_A: return onActivate(doc); - } + case KeyEvent.KEYCODE_FORWARD_DEL: + // This has to be handled here instead of in a keyboard shortcut, because + // keyboard shortcuts all have to be modified with the 'Ctrl' key. + if (mSelectionManager.hasSelection()) { + deleteDocuments(mSelectionManager.getSelection()); + } + // Always handle the key, even if there was nothing to delete. This is a + // precaution to prevent other handlers from potentially picking up the event + // and triggering extra behaviours. + return true; } return false; diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java index 5edda3866d5c..450341f9d4fc 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java @@ -77,10 +77,18 @@ public abstract class DocumentHolder /** * Makes the associated item view appear selected. Note that this merely affects the appearance * of the view, it doesn't actually select the item. + * TODO: Use the DirectoryItemAnimator instead of manually controlling animation using a boolean + * flag. * * @param selected + * @param animate Whether or not to animate the change. Only selection changes initiated by the + * selection manager should be animated. See + * {@link ModelBackedDocumentsAdapter#onBindViewHolder(DocumentHolder, int, java.util.List)} */ - public void setSelected(boolean selected) { + public void setSelected(boolean selected, boolean animate) { + // Note: the animate param doesn't apply for this base implementation, because the + // DirectoryItemAnimator takes care of it. It's required by subclasses, which perform their + // own animation. itemView.setActivated(selected); itemView.setBackgroundColor(selected ? mSelectedBgColor : mDefaultBgColor); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java index 0ee7623a3fe3..ea1deb4cdcdb 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java @@ -58,9 +58,9 @@ public abstract class FragmentTuner { } } - public abstract void updateActionMenu( - Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename); + Menu menu, @ResultType int dirType, + boolean canCopy, boolean canDelete, boolean canRename); // Subtly different from isDocumentEnabled. The reason may be illuminated as follows. // A folder is enabled such that it may be double clicked, even in settings @@ -104,7 +104,8 @@ public abstract class FragmentTuner { return false; } - if (mState.action == ACTION_OPEN_TREE) { + if (mState.action == ACTION_OPEN_TREE + || mState.action == ACTION_PICK_COPY_DESTINATION) { // In this case nothing *ever* is selectable...the expected user behavior is // they navigate *into* a folder, then click a confirmation button indicating // that the current directory is the directory they are picking. @@ -140,7 +141,8 @@ public abstract class FragmentTuner { @Override public void updateActionMenu( - Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename) { + Menu menu, @ResultType int dirType, + boolean canCopy, boolean canDelete, boolean canRename) { MenuItem open = menu.findItem(R.id.menu_open); MenuItem share = menu.findItem(R.id.menu_share); @@ -198,22 +200,28 @@ public abstract class FragmentTuner { @Override public void updateActionMenu( - Menu menu, @ResultType int dirType, boolean canDelete, boolean canRename) { + Menu menu, @ResultType int dirType, + boolean canCopy, boolean canDelete, boolean canRename) { MenuItem copy = menu.findItem(R.id.menu_copy_to_clipboard); MenuItem paste = menu.findItem(R.id.menu_paste_from_clipboard); - copy.setEnabled(dirType != DirectoryFragment.TYPE_RECENT_OPEN); + copy.setEnabled(canCopy); MenuItem rename = menu.findItem(R.id.menu_rename); + MenuItem moveTo = menu.findItem(R.id.menu_move_to); + MenuItem copyTo = menu.findItem(R.id.menu_copy_to); + + copyTo.setVisible(true); + moveTo.setVisible(true); rename.setVisible(true); + + copyTo.setEnabled(canCopy); + moveTo.setEnabled(canCopy && canDelete); rename.setEnabled(canRename); menu.findItem(R.id.menu_share).setVisible(true); menu.findItem(R.id.menu_delete).setVisible(canDelete); menu.findItem(R.id.menu_open).setVisible(false); - menu.findItem(R.id.menu_copy_to).setVisible(true); - menu.findItem(R.id.menu_move_to).setVisible(true); - menu.findItem(R.id.menu_move_to).setEnabled(canDelete); Menus.disableHiddenItems(menu, copy, paste); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java index 90b23419fcd3..ce5bcb199454 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDirectoryHolder.java @@ -42,12 +42,17 @@ final class GridDirectoryHolder extends DocumentHolder { } @Override - public void setSelected(boolean selected) { - super.setSelected(selected); + public void setSelected(boolean selected, boolean animate) { + super.setSelected(selected, animate); float checkAlpha = selected ? 1f : 0f; - mIconCheck.animate().alpha(checkAlpha).start(); - mIconMime.animate().alpha(1f - checkAlpha).start(); + if (animate) { + mIconCheck.animate().alpha(checkAlpha).start(); + mIconMime.animate().alpha(1f - checkAlpha).start(); + } else { + mIconCheck.setAlpha(checkAlpha); + mIconMime.setAlpha(1f - checkAlpha); + } } /** diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java index c8641a8000f5..c4f6f11b31c9 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/GridDocumentHolder.java @@ -69,12 +69,16 @@ final class GridDocumentHolder extends DocumentHolder { } @Override - public void setSelected(boolean selected) { + public void setSelected(boolean selected, boolean animate) { // We always want to make sure our check box disappears if we're not selected, // even if the item is disabled. This is because this object can be reused // and this method will be called to setup initial state. float checkAlpha = selected ? 1f : 0f; - mIconCheck.animate().alpha(checkAlpha).start(); + if (animate) { + mIconCheck.animate().alpha(checkAlpha).start(); + } else { + mIconCheck.setAlpha(checkAlpha); + } // But it should be an error to be set to selected && be disabled. if (!itemView.isEnabled()) { @@ -82,9 +86,13 @@ final class GridDocumentHolder extends DocumentHolder { return; } - super.setSelected(selected); + super.setSelected(selected, animate); - mIconMimeSm.animate().alpha(1f - checkAlpha).start(); + if (animate) { + mIconMimeSm.animate().alpha(1f - checkAlpha).start(); + } else { + mIconMimeSm.setAlpha(1f - checkAlpha); + } } public void setEnabled(boolean enabled) { diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java index 3a1be119896b..ace53e0b5f4e 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java @@ -65,22 +65,31 @@ final class ListDocumentHolder extends DocumentHolder { } @Override - public void setSelected(boolean selected) { + public void setSelected(boolean selected, boolean animate) { // We always want to make sure our check box disappears if we're not selected, // even if the item is disabled. But it should be an error (see assert below) // to be set to selected && be disabled. float checkAlpha = selected ? 1f : 0f; - mIconCheck.animate().alpha(checkAlpha).start(); + if (animate) { + mIconCheck.animate().alpha(checkAlpha).start(); + } else { + mIconCheck.setAlpha(checkAlpha); + } if (!itemView.isEnabled()) { assert(!selected); return; } - super.setSelected(selected); + super.setSelected(selected, animate); - mIconMime.animate().alpha(1f - checkAlpha).start(); - mIconThumb.animate().alpha(1f - checkAlpha).start(); + if (animate) { + mIconMime.animate().alpha(1f - checkAlpha).start(); + mIconThumb.animate().alpha(1f - checkAlpha).start(); + } else { + mIconMime.setAlpha(1f - checkAlpha); + mIconThumb.setAlpha(1f - checkAlpha); + } } @Override diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java index ab4f5c4f90ad..c5ee59237fb0 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java @@ -153,48 +153,53 @@ public class Model { private void updateModelData() { int[] positions = new int[mCursorCount]; mIds = new String[mCursorCount]; - String[] stringValues = new String[mCursorCount]; + boolean[] isDirs = new boolean[mCursorCount]; + String[] displayNames = null; long[] longValues = null; - if (mSortOrder == SORT_ORDER_LAST_MODIFIED || mSortOrder == SORT_ORDER_SIZE) { - longValues = new long[mCursorCount]; + switch (mSortOrder) { + case SORT_ORDER_DISPLAY_NAME: + displayNames = new String[mCursorCount]; + break; + case SORT_ORDER_LAST_MODIFIED: + case SORT_ORDER_SIZE: + longValues = new long[mCursorCount]; + break; } + String mimeType; + mCursor.moveToPosition(-1); for (int pos = 0; pos < mCursorCount; ++pos) { mCursor.moveToNext(); positions[pos] = pos; mIds[pos] = createModelId(mCursor); + mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE); + isDirs[pos] = Document.MIME_TYPE_DIR.equals(mimeType); + switch(mSortOrder) { case SORT_ORDER_DISPLAY_NAME: - final String mimeType = getCursorString(mCursor, Document.COLUMN_MIME_TYPE); final String displayName = getCursorString( mCursor, Document.COLUMN_DISPLAY_NAME); - if (Document.MIME_TYPE_DIR.equals(mimeType)) { - stringValues[pos] = Shared.DIR_PREFIX + displayName; - } else { - stringValues[pos] = displayName; - } + displayNames[pos] = displayName; break; case SORT_ORDER_LAST_MODIFIED: longValues[pos] = getLastModified(mCursor); - stringValues[pos] = getCursorString(mCursor, Document.COLUMN_MIME_TYPE); break; case SORT_ORDER_SIZE: longValues[pos] = getCursorLong(mCursor, Document.COLUMN_SIZE); - stringValues[pos] = getCursorString(mCursor, Document.COLUMN_MIME_TYPE); break; } } switch (mSortOrder) { case SORT_ORDER_DISPLAY_NAME: - binarySort(stringValues, positions, mIds); + binarySort(displayNames, isDirs, positions, mIds); break; case SORT_ORDER_LAST_MODIFIED: case SORT_ORDER_SIZE: - binarySort(longValues, stringValues, positions, mIds); + binarySort(longValues, isDirs, positions, mIds); break; } @@ -207,18 +212,20 @@ public class Model { /** * Sorts model data. Takes three columns of index-corresponded data. The first column is the - * sort key. Rows are sorted in ascending alphabetical order on the sort key. This code is based - * on TimSort.binarySort(). + * sort key. Rows are sorted in ascending alphabetical order on the sort key. + * Directories are always shown first. This code is based on TimSort.binarySort(). * * @param sortKey Data is sorted in ascending alphabetical order. + * @param isDirs Array saying whether an item is a directory or not. * @param positions Cursor positions to be sorted. * @param ids Model IDs to be sorted. */ - private static void binarySort(String[] sortKey, int[] positions, String[] ids) { + private static void binarySort(String[] sortKey, boolean[] isDirs, int[] positions, String[] ids) { final int count = positions.length; for (int start = 1; start < count; start++) { final int pivotPosition = positions[start]; final String pivotValue = sortKey[start]; + final boolean pivotIsDir = isDirs[start]; final String pivotId = ids[start]; int left = 0; @@ -227,9 +234,18 @@ public class Model { while (left < right) { int mid = (left + right) >>> 1; - final String lhs = pivotValue; - final String rhs = sortKey[mid]; - final int compare = Shared.compareToIgnoreCaseNullable(lhs, rhs); + // Directories always go in front. + int compare = 0; + final boolean rhsIsDir = isDirs[mid]; + if (pivotIsDir && !rhsIsDir) { + compare = -1; + } else if (!pivotIsDir && rhsIsDir) { + compare = 1; + } else { + final String lhs = pivotValue; + final String rhs = sortKey[mid]; + compare = Shared.compareToIgnoreCaseNullable(lhs, rhs); + } if (compare < 0) { right = mid; @@ -243,20 +259,24 @@ public class Model { case 2: positions[left + 2] = positions[left + 1]; sortKey[left + 2] = sortKey[left + 1]; + isDirs[left + 2] = isDirs[left + 1]; ids[left + 2] = ids[left + 1]; case 1: positions[left + 1] = positions[left]; sortKey[left + 1] = sortKey[left]; + isDirs[left + 1] = isDirs[left]; ids[left + 1] = ids[left]; break; default: System.arraycopy(positions, left, positions, left + 1, n); System.arraycopy(sortKey, left, sortKey, left + 1, n); + System.arraycopy(isDirs, left, isDirs, left + 1, n); System.arraycopy(ids, left, ids, left + 1, n); } positions[left] = pivotPosition; sortKey[left] = pivotValue; + isDirs[left] = pivotIsDir; ids[left] = pivotId; } } @@ -268,17 +288,17 @@ public class Model { * numerical order on the sort key. This code is based on TimSort.binarySort(). * * @param sortKey Data is sorted in descending numerical order. - * @param mimeTypes Corresponding mime types. Directories will be sorted ahead of documents. + * @param isDirs Array saying whether an item is a directory or not. * @param positions Cursor positions to be sorted. * @param ids Model IDs to be sorted. */ private static void binarySort( - long[] sortKey, String[] mimeTypes, int[] positions, String[] ids) { + long[] sortKey, boolean[] isDirs, int[] positions, String[] ids) { final int count = positions.length; for (int start = 1; start < count; start++) { final int pivotPosition = positions[start]; final long pivotValue = sortKey[start]; - final String pivotMime = mimeTypes[start]; + final boolean pivotIsDir = isDirs[start]; final String pivotId = ids[start]; int left = 0; @@ -287,13 +307,12 @@ public class Model { while (left < right) { int mid = ((left + right) >>> 1); - // First bucket by mime type. Directories always go in front. + // Directories always go in front. int compare = 0; - final boolean lhsIsDir = Document.MIME_TYPE_DIR.equals(pivotMime); - final boolean rhsIsDir = Document.MIME_TYPE_DIR.equals(mimeTypes[mid]); - if (lhsIsDir && !rhsIsDir) { + final boolean rhsIsDir = isDirs[mid]; + if (pivotIsDir && !rhsIsDir) { compare = -1; - } else if (!lhsIsDir && rhsIsDir) { + } else if (!pivotIsDir && rhsIsDir) { compare = 1; } else { final long lhs = pivotValue; @@ -323,24 +342,24 @@ public class Model { case 2: positions[left + 2] = positions[left + 1]; sortKey[left + 2] = sortKey[left + 1]; - mimeTypes[left + 2] = mimeTypes[left + 1]; + isDirs[left + 2] = isDirs[left + 1]; ids[left + 2] = ids[left + 1]; case 1: positions[left + 1] = positions[left]; sortKey[left + 1] = sortKey[left]; - mimeTypes[left + 1] = mimeTypes[left]; + isDirs[left + 1] = isDirs[left]; ids[left + 1] = ids[left]; break; default: System.arraycopy(positions, left, positions, left + 1, n); System.arraycopy(sortKey, left, sortKey, left + 1, n); - System.arraycopy(mimeTypes, left, mimeTypes, left + 1, n); + System.arraycopy(isDirs, left, isDirs, left + 1, n); System.arraycopy(ids, left, ids, left + 1, n); } positions[left] = pivotPosition; sortKey[left] = pivotValue; - mimeTypes[left] = pivotMime; + isDirs[left] = pivotIsDir; ids[left] = pivotId; } } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java index 149ecdd58565..ca3b2e23648b 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java @@ -29,7 +29,6 @@ import android.util.SparseArray; import android.view.ViewGroup; import com.android.documentsui.State; - import com.google.common.collect.Sets; import java.util.ArrayList; @@ -103,7 +102,7 @@ final class ModelBackedDocumentsAdapter extends DocumentsAdapter { public void onBindViewHolder(DocumentHolder holder, int position, List<Object> payload) { if (payload.contains(SELECTION_CHANGED_MARKER)) { final boolean selected = mEnv.isSelected(mModelIds.get(position)); - holder.setSelected(selected); + holder.setSelected(selected, true); } else { onBindViewHolder(holder, position); } @@ -124,7 +123,7 @@ final class ModelBackedDocumentsAdapter extends DocumentsAdapter { assert(!selected); } holder.setEnabled(enabled); - holder.setSelected(mEnv.isSelected(modelId)); + holder.setSelected(mEnv.isSelected(modelId), false); mEnv.onBindDocumentHolder(holder, cursor); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java index b0cc09a134f9..b80486dd8fc0 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java +++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java @@ -903,7 +903,7 @@ public final class MultiSelectManager { public Selection createFromParcel(Parcel in, ClassLoader loader) { return new Selection( in.readString(), - (ArrayList<String>) in.readArrayList(loader)); + in.readArrayList(loader)); } @Override @@ -931,7 +931,6 @@ public final class MultiSelectManager { Rect getAbsoluteRectForChildViewAt(int index); int getAdapterPositionAt(int index); int getColumnCount(); - int getRowCount(); int getChildCount(); int getVisibleChildCount(); /** @@ -1008,13 +1007,6 @@ public final class MultiSelectManager { } @Override - public int getRowCount() { - int numFullColumns = getChildCount() / getColumnCount(); - boolean hasPartiallyFullColumn = getChildCount() % getColumnCount() != 0; - return numFullColumns + (hasPartiallyFullColumn ? 1 : 0); - } - - @Override public int getHeight() { return mView.getHeight(); } @@ -1202,6 +1194,7 @@ public final class MultiSelectManager { } mCurrentPosition = input.getOrigin(); + mModel.resizeSelection(input.getOrigin()); scrollViewIfNecessary(); resizeBandSelectRectangle(); } @@ -1549,11 +1542,7 @@ public final class MultiSelectManager { mColumnBounds, new Limits(absoluteChildRect.left, absoluteChildRect.right)); } - if (mRowBounds.size() != mHelper.getRowCount()) { - // If not all y-limits have been recorded, record this one. - recordLimits( - mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom)); - } + recordLimits(mRowBounds, new Limits(absoluteChildRect.top, absoluteChildRect.bottom)); SparseIntArray columnList = mColumns.get(absoluteChildRect.left); if (columnList == null) { @@ -1747,6 +1736,11 @@ public final class MultiSelectManager { return ((Limits) other).lowerLimit == lowerLimit && ((Limits) other).upperLimit == upperLimit; } + + @Override + public String toString() { + return "(" + lowerLimit + ", " + upperLimit + ")"; + } } /** diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java index d5327f916bed..31ce8377ec76 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java @@ -74,7 +74,6 @@ public class DocumentInfo implements Durable, Parcelable { summary = null; size = -1; icon = 0; - derivedUri = null; } @@ -210,6 +209,7 @@ public class DocumentInfo implements Durable, Parcelable { + ", isContainer=" + isContainer() + ", isDirectory=" + isDirectory() + ", isArchive=" + isArchive() + + ", isPartial=" + isPartial() + ", isVirtualDocument=" + isVirtualDocument() + ", isDeleteSupported=" + isDeleteSupported() + ", isCreateSupported=" + isCreateSupported() @@ -249,6 +249,10 @@ public class DocumentInfo implements Durable, Parcelable { return (flags & Document.FLAG_ARCHIVE) != 0; } + public boolean isPartial() { + return (flags & Document.FLAG_PARTIAL) != 0; + } + public boolean isContainer() { return isDirectory() || isArchive(); } diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java index 3eaf10a18a0f..3960475f5ecd 100644 --- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java +++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java @@ -55,7 +55,7 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> { private static final int VERSION_DROP_TYPE = 2; // The values of these constants determine the sort order of various roots in the RootsFragment. - @IntDef(flag = true, value = { + @IntDef(flag = false, value = { TYPE_IMAGES, TYPE_VIDEO, TYPE_AUDIO, diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java index 59dc2328efa5..e4afc3d8199c 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java @@ -183,6 +183,7 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> { // We don't really need to test the entirety of download support // since downloads is (almost) just another provider. + @Suppress public void testDownload_Queued() throws Exception { DownloadManager dm = (DownloadManager) context.getSystemService( Context.DOWNLOAD_SERVICE); @@ -194,6 +195,7 @@ public class FilesActivityUiTest extends ActivityTest<FilesActivity> { bots.directory.assertDocumentsPresent("Queued"); } + @Suppress public void testDownload_RetryUnsuccessful() throws Exception { DownloadManager dm = (DownloadManager) context.getSystemService( Context.DOWNLOAD_SERVICE); diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java index 353d4bdfb0b1..0c0e0b7133dd 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java @@ -27,6 +27,7 @@ import android.test.suitebuilder.annotation.SmallTest; import com.android.documentsui.dirlist.MultiSelectManager.GridModel; import java.util.ArrayList; +import java.util.List; import java.util.Set; @SmallTest @@ -42,6 +43,17 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { private Set<String> lastSelection; private int viewWidth; + // TLDR: Don't call model.{start|resize}Selection; use the local #startSelection and + // #resizeSelection methods instead. + // + // The reason for this is that selection is stateful and involves operations that take the + // current UI state (e.g scrolling) into account. This test maintains its own copy of the + // selection bounds as control data for verifying selections. Keep this data in sync by calling + // #startSelection and + // #resizeSelection. + private Point mSelectionOrigin; + private Point mSelectionPoint; + private void initData(final int numChildren, int numColumns) { env = new TestEnvironment(numChildren, numColumns); adapter = new TestDocumentsAdapter(new ArrayList<String>()) { @@ -76,139 +88,241 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { public void testSelectionLeftOfItems() { initData(20, 5); - model.startSelection(new Point(0, 10)); - model.resizeSelection(new Point(1, 11)); - assertSelected(); + startSelection(new Point(0, 10)); + resizeSelection(new Point(1, 11)); + assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionRightOfItems() { initData(20, 4); - model.startSelection(new Point(viewWidth - 1, 10)); - model.resizeSelection(new Point(viewWidth - 2, 11)); - assertSelected(); + startSelection(new Point(viewWidth - 1, 10)); + resizeSelection(new Point(viewWidth - 2, 11)); + assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionAboveItems() { initData(20, 4); - model.startSelection(new Point(10, 0)); - model.resizeSelection(new Point(11, 1)); - assertSelected(); + startSelection(new Point(10, 0)); + resizeSelection(new Point(11, 1)); + assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionBelowItems() { initData(5, 4); - model.startSelection(new Point(10, VIEWPORT_HEIGHT - 1)); - model.resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2)); - assertSelected(); + startSelection(new Point(10, VIEWPORT_HEIGHT - 1)); + resizeSelection(new Point(11, VIEWPORT_HEIGHT - 2)); + assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testVerticalSelectionBetweenItems() { initData(20, 4); - model.startSelection(new Point(106, 0)); - model.resizeSelection(new Point(107, 200)); - assertSelected(); + startSelection(new Point(106, 0)); + resizeSelection(new Point(107, 200)); + assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testHorizontalSelectionBetweenItems() { initData(20, 4); - model.startSelection(new Point(0, 105)); - model.resizeSelection(new Point(200, 106)); - assertSelected(); + startSelection(new Point(0, 105)); + resizeSelection(new Point(200, 106)); + assertNoSelection(); assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testGrowingAndShrinkingSelection() { initData(20, 4); - model.startSelection(new Point(0, 0)); - model.resizeSelection(new Point(5, 5)); - assertSelected(0); - model.resizeSelection(new Point(109, 109)); - assertSelected(0); - model.resizeSelection(new Point(110, 109)); - assertSelected(0, 1); - model.resizeSelection(new Point(110, 110)); - assertSelected(0, 1, 4, 5); - model.resizeSelection(new Point(214, 214)); - assertSelected(0, 1, 4, 5); - model.resizeSelection(new Point(215, 214)); - assertSelected(0, 1, 2, 4, 5, 6); - model.resizeSelection(new Point(214, 214)); - assertSelected(0, 1, 4, 5); - model.resizeSelection(new Point(110, 110)); - assertSelected(0, 1, 4, 5); - model.resizeSelection(new Point(110, 109)); - assertSelected(0, 1); - model.resizeSelection(new Point(109, 109)); - assertSelected(0); - model.resizeSelection(new Point(5, 5)); - assertSelected(0); - model.resizeSelection(new Point(0, 0)); - assertSelected(); + startSelection(new Point(0, 0)); + + resizeSelection(new Point(5, 5)); + verifySelection(); + + resizeSelection(new Point(109, 109)); + verifySelection(); + + resizeSelection(new Point(110, 109)); + verifySelection(); + + resizeSelection(new Point(110, 110)); + verifySelection(); + + resizeSelection(new Point(214, 214)); + verifySelection(); + + resizeSelection(new Point(215, 214)); + verifySelection(); + + resizeSelection(new Point(214, 214)); + verifySelection(); + + resizeSelection(new Point(110, 110)); + verifySelection(); + + resizeSelection(new Point(110, 109)); + verifySelection(); + + resizeSelection(new Point(109, 109)); + verifySelection(); + + resizeSelection(new Point(5, 5)); + verifySelection(); + + resizeSelection(new Point(0, 0)); + verifySelection(); + assertEquals(NOT_SET, model.getPositionNearestOrigin()); } public void testSelectionMovingAroundOrigin() { initData(16, 4); - model.startSelection(new Point(210, 210)); - model.resizeSelection(new Point(viewWidth - 1, 0)); - assertSelected(2, 3, 6, 7); - model.resizeSelection(new Point(0, 0)); - assertSelected(0, 1, 4, 5); - model.resizeSelection(new Point(0, 420)); - assertSelected(8, 9, 12, 13); - model.resizeSelection(new Point(viewWidth - 1, 420)); - assertSelected(10, 11, 14, 15); - assertEquals(10, model.getPositionNearestOrigin()); + + startSelection(new Point(210, 210)); + resizeSelection(new Point(viewWidth - 1, 0)); + verifySelection(); + + resizeSelection(new Point(0, 0)); + verifySelection(); + + resizeSelection(new Point(0, 420)); + verifySelection(); + + resizeSelection(new Point(viewWidth - 1, 420)); + verifySelection(); + + // This is manually figured and will need to be adjusted if the separator position is + // changed. + assertEquals(7, model.getPositionNearestOrigin()); } public void testScrollingBandSelect() { initData(40, 4); - model.startSelection(new Point(0, 0)); - model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); - assertSelected(0, 4, 8, 12, 16); + + startSelection(new Point(0, 0)); + resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); + verifySelection(); + scroll(CHILD_VIEW_EDGE_PX); - assertSelected(0, 4, 8, 12, 16, 20); - model.resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1)); - assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21); + verifySelection(); + + resizeSelection(new Point(200, VIEWPORT_HEIGHT - 1)); + verifySelection(); + scroll(CHILD_VIEW_EDGE_PX); - assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21, 24, 25); + verifySelection(); + scroll(-2 * CHILD_VIEW_EDGE_PX); - assertSelected(0, 1, 4, 5, 8, 9, 12, 13, 16, 17); - model.resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); - assertSelected(0, 4, 8, 12, 16); + verifySelection(); + + resizeSelection(new Point(100, VIEWPORT_HEIGHT - 1)); + verifySelection(); + assertEquals(0, model.getPositionNearestOrigin()); } - private void assertSelected(int... selectedPositions) { - assertEquals(selectedPositions.length, lastSelection.size()); - for (int position : selectedPositions) { - assertTrue(lastSelection.contains(Integer.toString(position))); + /** Returns the current selection area as a Rect. */ + private Rect getSelectionArea() { + // Construct a rect from the two selection points. + Rect selectionArea = new Rect( + mSelectionOrigin.x, mSelectionOrigin.y, mSelectionOrigin.x, mSelectionOrigin.y); + selectionArea.union(mSelectionPoint.x, mSelectionPoint.y); + // Rect intersection tests are exclusive of bounds, while the MSM's selection code is + // inclusive. Expand the rect by 1 pixel in all directions to account for this. + selectionArea.inset(-1, -1); + + return selectionArea; + } + + /** Asserts that the selection is currently empty. */ + private void assertNoSelection() { + assertEquals("Unexpected items " + lastSelection + " in selection " + getSelectionArea(), + 0, lastSelection.size()); + } + + /** Verifies the selection using actual bbox checks. */ + private void verifySelection() { + Rect selectionArea = getSelectionArea(); + for (TestEnvironment.Item item: env.items) { + if (Rect.intersects(selectionArea, item.rect)) { + assertTrue("Expected item " + item + " was not in selection " + selectionArea, + lastSelection.contains(item.name)); + } else { + assertFalse("Unexpected item " + item + " in selection" + selectionArea, + lastSelection.contains(item.name)); + } } } + private void startSelection(Point p) { + model.startSelection(p); + mSelectionOrigin = env.createAbsolutePoint(p); + } + + private void resizeSelection(Point p) { + model.resizeSelection(p); + mSelectionPoint = env.createAbsolutePoint(p); + } + private void scroll(int dy) { assertTrue(env.verticalOffset + VIEWPORT_HEIGHT + dy <= env.getTotalHeight()); env.verticalOffset += dy; + // Correct the cached selection point as well. + mSelectionPoint.y += dy; model.onScrolled(null, 0, dy); } private static final class TestEnvironment implements MultiSelectManager.SelectionEnvironment { - public int horizontalOffset = 0; - public int verticalOffset = 0; private final int mNumColumns; private final int mNumRows; private final int mNumChildren; + private final int mSeparatorPosition; + + public int horizontalOffset = 0; + public int verticalOffset = 0; + private List<Item> items = new ArrayList<>(); public TestEnvironment(int numChildren, int numColumns) { mNumChildren = numChildren; mNumColumns = numColumns; - mNumRows = (int) Math.ceil((double) numChildren / mNumColumns); + mSeparatorPosition = mNumColumns + 1; + mNumRows = setupGrid(); + } + + private int setupGrid() { + // Split the input set into folders and documents. Do this such that there is a + // partially-populated row in the middle of the grid, to test corner cases in layout + // code. + int y = VIEW_PADDING_PX; + int i = 0; + int numRows = 0; + while (i < mNumChildren) { + int top = y; + int height = CHILD_VIEW_EDGE_PX; + int width = CHILD_VIEW_EDGE_PX; + for (int j = 0; j < mNumColumns && i < mNumChildren; j++) { + int left = VIEW_PADDING_PX + (j * (width + VIEW_PADDING_PX)); + items.add(new Item( + Integer.toString(i), + new Rect( + left, + top, + left + width - 1, + top + height - 1))); + + // Create a partially populated row at the separator position. + if (++i == mSeparatorPosition) { + break; + } + } + y += height + VIEW_PADDING_PX; + numRows++; + } + + return numRows; } private int getTotalHeight() { @@ -227,8 +341,16 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { private int getNumItemsInRow(int index) { assertTrue(index >= 0 && index < mNumRows); - if (index == mNumRows - 1 && mNumChildren % mNumColumns != 0) { - return mNumChildren % mNumColumns; + int mod = mSeparatorPosition % mNumColumns; + if (index == (mSeparatorPosition / mNumColumns)) { + // The row containing the separator may be incomplete + return mod > 0 ? mod : mNumColumns; + } + // Account for the partial separator row in the final row tally. + if (index == mNumRows - 1) { + // The last row may be incomplete + int finalRowCount = (mNumChildren - mod) % mNumColumns; + return finalRowCount > 0 ? finalRowCount : mNumColumns; } return mNumColumns; @@ -257,21 +379,18 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { @Override public int getAdapterPositionAt(int index) { - return index + mNumColumns * (getFirstVisibleRowIndex()); + // Account for partial rows by actually tallying up the items in hidden rows. + int hiddenCount = 0; + for (int i = 0; i < getFirstVisibleRowIndex(); i++) { + hiddenCount += getNumItemsInRow(i); + } + return index + hiddenCount; } @Override public Rect getAbsoluteRectForChildViewAt(int index) { - int adapterPosition = (getFirstVisibleRowIndex() * mNumColumns) + index; - int rowIndex = adapterPosition / mNumColumns; - int columnIndex = adapterPosition % mNumColumns; - - Rect rect = new Rect(); - rect.top = VIEW_PADDING_PX + rowIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX); - rect.bottom = rect.top + CHILD_VIEW_EDGE_PX - 1; - rect.left = VIEW_PADDING_PX + columnIndex * (CHILD_VIEW_EDGE_PX + VIEW_PADDING_PX); - rect.right = rect.left + CHILD_VIEW_EDGE_PX - 1; - return rect; + int adapterPosition = getAdapterPositionAt(index); + return items.get(adapterPosition).rect; } @Override @@ -285,11 +404,6 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { } @Override - public int getRowCount() { - return mNumRows; - } - - @Override public void showBand(Rect rect) { throw new UnsupportedOperationException(); } @@ -328,5 +442,19 @@ public class MultiSelectManager_GridModelTest extends AndroidTestCase { public boolean isLayoutItem(int adapterPosition) { return false; } + + public static final class Item { + public String name; + public Rect rect; + + public Item(String n, Rect r) { + name = n; + rect = r; + } + + public String toString() { + return name + ": " + rect; + } + } } } diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java index 8e624a036331..56e54a61cfc0 100644 --- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java +++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java @@ -87,11 +87,6 @@ public class TestSelectionEnvironment implements SelectionEnvironment { } @Override - public int getRowCount() { - return 0; - } - - @Override public int getChildCount() { return 0; } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java index 55f55b0edbc3..83488cd5b490 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java @@ -14,12 +14,15 @@ * limitations under the License. */ -package com.android.mtp.exceptions; +package com.android.mtp; import java.io.IOException; /** * Exception thrown when the device is busy and the requested operation cannon be completed. */ -public class BusyDeviceException extends IOException { +class BusyDeviceException extends IOException { + BusyDeviceException() { + super("The MTP device is busy."); + } } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java index 72ad2f6a629e..8c73211cccf1 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java @@ -830,11 +830,21 @@ class MtpDatabase { if (info.getFormat() == MtpConstants.FORMAT_ASSOCIATION) { return DocumentsContract.Document.MIME_TYPE_DIR; } + final String formatCodeMimeType = MediaFile.getMimeTypeForFormatCode(info.getFormat()); + final String mediaFileMimeType = MediaFile.getMimeTypeForFile(info.getName()); + + // Format code can be mapped with multiple mime types, e.g. FORMAT_MPEG is mapped with + // audio/mp4 and video/mp4. + // As file extension contains more information than format code, returns mime type obtained + // from file extension if it is consistent with format code. + if (mediaFileMimeType != null && + MediaFile.getFormatCode("", mediaFileMimeType) == info.getFormat()) { + return mediaFileMimeType; + } if (formatCodeMimeType != null) { return formatCodeMimeType; } - final String mediaFileMimeType = MediaFile.getMimeTypeForFile(info.getName()); if (mediaFileMimeType != null) { return mediaFileMimeType; } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index d4d45912aecc..68c19923ccb5 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -22,6 +22,7 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.database.Cursor; import android.database.MatrixCursor; +import android.database.sqlite.SQLiteDiskIOException; import android.graphics.Point; import android.media.MediaFile; import android.mtp.MtpConstants; @@ -29,6 +30,8 @@ import android.mtp.MtpObjectInfo; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; +import android.os.FileUriExposedException; +import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.os.storage.StorageManager; import android.provider.DocumentsContract.Document; @@ -36,18 +39,17 @@ import android.provider.DocumentsContract.Root; import android.provider.DocumentsContract; import android.provider.DocumentsProvider; import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.mtp.exceptions.BusyDeviceException; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeoutException; /** * DocumentsProvider for MTP devices. @@ -103,25 +105,33 @@ public class MtpDocumentsProvider extends DocumentsProvider { // Check boot count and cleans database if it's first time to launch MtpDocumentsProvider // after booting. - final int bootCount = Settings.Global.getInt(mResolver, Settings.Global.BOOT_COUNT, -1); - final int lastBootCount = mDatabase.getLastBootCount(); - if (bootCount != -1 && bootCount != lastBootCount) { - mDatabase.setLastBootCount(bootCount); - final List<UriPermission> permissions = mResolver.getOutgoingPersistedUriPermissions(); - final Uri[] uris = new Uri[permissions.size()]; - for (int i = 0; i < permissions.size(); i++) { - uris[i] = permissions.get(i).getUri(); + try { + final int bootCount = Settings.Global.getInt(mResolver, Settings.Global.BOOT_COUNT, -1); + final int lastBootCount = mDatabase.getLastBootCount(); + if (bootCount != -1 && bootCount != lastBootCount) { + mDatabase.setLastBootCount(bootCount); + final List<UriPermission> permissions = + mResolver.getOutgoingPersistedUriPermissions(); + final Uri[] uris = new Uri[permissions.size()]; + for (int i = 0; i < permissions.size(); i++) { + uris[i] = permissions.get(i).getUri(); + } + mDatabase.cleanDatabase(uris); } - mDatabase.cleanDatabase(uris); + } catch (SQLiteDiskIOException error) { + // It can happen due to disk shortage. + Log.e(TAG, "Failed to clean database.", error); + return false; } // TODO: Mount AppFuse on demands. try { mAppFuse.mount(getContext().getSystemService(StorageManager.class)); - } catch (IOException e) { - Log.e(TAG, "Failed to start app fuse.", e); + } catch (IOException error) { + Log.e(TAG, "Failed to start app fuse.", error); return false; } + resume(); return true; } @@ -315,25 +325,61 @@ public class MtpDocumentsProvider extends DocumentsProvider { if (DEBUG) { Log.d(TAG, "createDocument: " + displayName); } + final Identifier parentId; + final MtpDeviceRecord record; + final ParcelFileDescriptor[] pipe; try { - final Identifier parentId = mDatabase.createIdentifier(parentDocumentId); + parentId = mDatabase.createIdentifier(parentDocumentId); openDevice(parentId.mDeviceId); - final MtpDeviceRecord record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord; + record = getDeviceToolkit(parentId.mDeviceId).mDeviceRecord; if (!MtpDeviceRecord.isWritingSupported(record.operationsSupported)) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException( + "Writing operation is not supported by the device."); + } + pipe = ParcelFileDescriptor.createReliablePipe(); + int objectHandle = -1; + MtpObjectInfo info = null; + try { + pipe[0].close(); // 0 bytes for a new document. + + final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ? + MtpConstants.FORMAT_ASSOCIATION : + MediaFile.getFormatCode(displayName, mimeType); + info = new MtpObjectInfo.Builder() + .setStorageId(parentId.mStorageId) + .setParent(parentId.mObjectHandle) + .setFormat(formatCode) + .setName(displayName) + .build(); + + final String[] parts = FileUtils.splitFileName(mimeType, displayName); + final String baseName = parts[0]; + final String extension = parts[1]; + for (int i = 0; i <= 32; i++) { + final MtpObjectInfo infoUniqueName; + if (i == 0) { + infoUniqueName = info; + } else { + infoUniqueName = new MtpObjectInfo.Builder(info).setName( + baseName + " (" + i + ")." + extension).build(); + } + try { + objectHandle = mMtpManager.createDocument( + parentId.mDeviceId, infoUniqueName, pipe[1]); + break; + } catch (SendObjectInfoFailure exp) { + // This can be caused when we have an existing file with the same name. + continue; + } + } + } finally { + pipe[1].close(); + } + if (objectHandle == -1) { + throw new IllegalArgumentException( + "The file name \"" + displayName + "\" is conflicted with existing files " + + "and the provider failed to find unique name."); } - final ParcelFileDescriptor pipe[] = ParcelFileDescriptor.createReliablePipe(); - pipe[0].close(); // 0 bytes for a new document. - final int formatCode = Document.MIME_TYPE_DIR.equals(mimeType) ? - MtpConstants.FORMAT_ASSOCIATION : - MediaFile.getFormatCode(displayName, mimeType); - final MtpObjectInfo info = new MtpObjectInfo.Builder() - .setStorageId(parentId.mStorageId) - .setParent(parentId.mObjectHandle) - .setFormat(formatCode) - .setName(displayName) - .build(); - final int objectHandle = mMtpManager.createDocument(parentId.mDeviceId, info, pipe[1]); final MtpObjectInfo infoWithHandle = new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build(); final String documentId = mDatabase.putNewDocument( @@ -342,9 +388,12 @@ public class MtpDocumentsProvider extends DocumentsProvider { getDocumentLoader(parentId).clearTask(parentId); notifyChildDocumentsChange(parentDocumentId); return documentId; + } catch (FileNotFoundException | RuntimeException error) { + Log.e(TAG, "createDocument", error); + throw error; } catch (IOException error) { Log.e(TAG, "createDocument", error); - throw new FileNotFoundException(error.getMessage()); + throw new IllegalStateException(error); } } @@ -426,7 +475,7 @@ public class MtpDocumentsProvider extends DocumentsProvider { closeDeviceInternal(id); } mRootScanner.pause(); - } catch (InterruptedException|IOException e) { + } catch (InterruptedException | IOException | TimeoutException e) { // It should fail unit tests by throwing runtime exception. throw new RuntimeException(e); } finally { @@ -464,9 +513,6 @@ public class MtpDocumentsProvider extends DocumentsProvider { getDeviceToolkit(deviceId).close(); mDeviceToolkits.remove(deviceId); mMtpManager.closeDevice(deviceId); - if (mDeviceToolkits.size() == 0) { - mRootScanner.pause(); - } } private DeviceToolkit getDeviceToolkit(int deviceId) throws FileNotFoundException { diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java index 020234394f87..6fb2a786be80 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java @@ -33,7 +33,6 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.mtp.exceptions.BusyDeviceException; import java.io.FileNotFoundException; import java.io.IOException; @@ -190,7 +189,7 @@ class MtpManager { synchronized (device) { final MtpObjectInfo sendObjectInfoResult = device.sendObjectInfo(objectInfo); if (sendObjectInfoResult == null) { - throw new IOException("Failed to create a document"); + throw new SendObjectInfoFailure(); } if (objectInfo.getFormat() != MtpConstants.FORMAT_ASSOCIATION) { if (!device.sendObject(sendObjectInfoResult.getObjectHandle(), diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java index 2f66c5cf17d7..2e9133bcb92f 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/RootScanner.java @@ -27,6 +27,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; final class RootScanner { /** @@ -95,15 +96,19 @@ final class RootScanner { * Stops background thread and wait for its termination. * @throws InterruptedException */ - synchronized void pause() throws InterruptedException { + synchronized void pause() throws InterruptedException, TimeoutException { if (mExecutor == null) { return; } mExecutor.shutdownNow(); - if (!mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) { - Log.e(MtpDocumentsProvider.TAG, "Failed to terminate RootScanner's background thread."); + try { + if (!mExecutor.awaitTermination(AWAIT_TERMINATION_TIMEOUT, TimeUnit.MILLISECONDS)) { + throw new TimeoutException( + "Timeout for terminating RootScanner's background thread."); + } + } finally { + mExecutor = null; } - mExecutor = null; } /** @@ -173,6 +178,9 @@ final class RootScanner { } mFirstScanCompleted.countDown(); pollingCount++; + if (devices.length == 0) { + break; + } try { // Use SHORT_POLLING_PERIOD for the first SHORT_POLLING_TIMES because it is // more likely to add new root just after the device is added. diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java new file mode 100644 index 000000000000..db7d777e280e --- /dev/null +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 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.mtp; + +import java.io.IOException; + +/** + * Exception thrown when sendObjectInfo failed. + */ +class SendObjectInfoFailure extends IOException { + SendObjectInfoFailure() { + super("Failed to MtpDevice#sendObjectInfo."); + } +} diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java index e49a93594edb..b74069ae36bb 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java @@ -17,6 +17,8 @@ package com.android.mtp; import android.database.Cursor; +import android.media.MediaFile; +import android.media.MediaFile.MediaFileType; import android.mtp.MtpConstants; import android.mtp.MtpObjectInfo; import android.net.Uri; @@ -1081,6 +1083,43 @@ public class MtpDatabaseTest extends AndroidTestCase { } } + public void testFormatCodeForMpeg() throws FileNotFoundException { + addTestDevice(); + addTestStorage("1"); + mDatabase.getMapper().startAddingDocuments("2"); + mDatabase.getMapper().putChildDocuments(0, "2", OPERATIONS_SUPPORTED, new MtpObjectInfo[] { + createDocument(100, "audio.m4a", MtpConstants.FORMAT_MPEG, 1000), + createDocument(101, "video.m4v", MtpConstants.FORMAT_MPEG, 1000), + createDocument(102, "unknown.mp4", MtpConstants.FORMAT_MPEG, 1000), + createDocument(103, "inconsistent.txt", MtpConstants.FORMAT_MPEG, 1000), + createDocument(104, "noext", MtpConstants.FORMAT_UNDEFINED, 1000), + }); + mDatabase.getMapper().stopAddingDocuments("2"); + try (final Cursor cursor = mDatabase.queryChildDocuments( + strings(COLUMN_DISPLAY_NAME, COLUMN_MIME_TYPE), + "2")) { + assertEquals(5, cursor.getCount()); + cursor.moveToNext(); + assertEquals("audio.m4a", cursor.getString(0)); + assertEquals("audio/mp4", cursor.getString(1)); + cursor.moveToNext(); + assertEquals("video.m4v", cursor.getString(0)); + assertEquals("video/mp4", cursor.getString(1)); + cursor.moveToNext(); + // Assume that the file is video as we don't have any hints to find out if the file is + // video or audio. + assertEquals("unknown.mp4", cursor.getString(0)); + assertEquals("video/mp4", cursor.getString(1)); + // Don't return mime type that is inconsistent with format code. + cursor.moveToNext(); + assertEquals("inconsistent.txt", cursor.getString(0)); + assertEquals("video/mp4", cursor.getString(1)); + cursor.moveToNext(); + assertEquals("noext", cursor.getString(0)); + assertEquals("application/octet-stream", cursor.getString(1)); + } + } + private void addTestDevice() throws FileNotFoundException { TestUtil.addTestDevice(mDatabase); } diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java index d6ad0f3c630c..9c1880a246a4 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java @@ -30,8 +30,6 @@ import android.provider.DocumentsContract; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.MediumTest; -import com.android.mtp.exceptions.BusyDeviceException; - import java.io.FileNotFoundException; import java.io.IOException; import java.util.Arrays; @@ -262,11 +260,9 @@ public class MtpDocumentsProviderTest extends AndroidTestCase { null)); { mProvider.openDevice(0); - mProvider.resumeRootScanner(); mResolver.waitForNotification(ROOTS_URI, 1); mProvider.openDevice(1); - mProvider.resumeRootScanner(); mResolver.waitForNotification(ROOTS_URI, 2); final Cursor cursor = mProvider.queryRoots(null); diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java index cdddd8178dc9..a08d9ee39a44 100644 --- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java +++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java @@ -48,6 +48,7 @@ public class PipeManagerTest extends AndroidTestCase { @Override protected void tearDown() throws Exception { assertTrue(mPipeManager.close()); + mDatabase.close(); } public void testReadDocument_basic() throws Exception { diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml index a0ce57afe569..dba0491fe70a 100644 --- a/packages/PrintSpooler/res/values-es/strings.xml +++ b/packages/PrintSpooler/res/values-es/strings.xml @@ -66,8 +66,8 @@ <string name="print_no_print_services" msgid="8561247706423327966">"No hay servicios de impresión habilitados"</string> <string name="print_no_printers" msgid="4869403323900054866">"No se encontraron impresoras"</string> <string name="cannot_add_printer" msgid="7840348733668023106">"No se pueden añadir impresoras"</string> - <string name="select_to_add_printers" msgid="3800709038689830974">"Seleccionar para añadir una impresora"</string> - <string name="enable_print_service" msgid="3482815747043533842">"Seleccionar para habilitar"</string> + <string name="select_to_add_printers" msgid="3800709038689830974">"Selecciona para añadir una impresora"</string> + <string name="enable_print_service" msgid="3482815747043533842">"Selecciona para habilitar"</string> <string name="enabled_services_title" msgid="7036986099096582296">"Servicios habilitados"</string> <string name="recommended_services_title" msgid="3799434882937956924">"Servicios recomendados"</string> <string name="disabled_services_title" msgid="7313253167968363211">"Servicios inhabilitados"</string> diff --git a/packages/PrintSpooler/res/values-ne-rNP/strings.xml b/packages/PrintSpooler/res/values-ne-rNP/strings.xml index e12c8dfc4ef7..5af3a04ed698 100644 --- a/packages/PrintSpooler/res/values-ne-rNP/strings.xml +++ b/packages/PrintSpooler/res/values-ne-rNP/strings.xml @@ -68,7 +68,7 @@ <string name="cannot_add_printer" msgid="7840348733668023106">"प्रिन्टरहरू थप्न सक्दैन"</string> <string name="select_to_add_printers" msgid="3800709038689830974">"प्रिन्टर थप्नका लागि चयन गर्नुहोस्"</string> <string name="enable_print_service" msgid="3482815747043533842">"सक्षम गर्नका लागि चयन गर्नुहोस्"</string> - <string name="enabled_services_title" msgid="7036986099096582296">"सेवाहरूलाई सक्षम गर्नुहोस्"</string> + <string name="enabled_services_title" msgid="7036986099096582296">"सक्षम गरिएका सेवाहरू"</string> <string name="recommended_services_title" msgid="3799434882937956924">"सिफारिस गरिएका सेवाहरू"</string> <string name="disabled_services_title" msgid="7313253167968363211">"असक्षम गरिएका सेवाहरू"</string> <string name="all_services_title" msgid="5578662754874906455">"सबै सेवाहरू"</string> diff --git a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml index ee6266fc6a33..a6af5bd4ab31 100644 --- a/packages/PrintSpooler/res/values-uz-rUZ/strings.xml +++ b/packages/PrintSpooler/res/values-uz-rUZ/strings.xml @@ -61,7 +61,7 @@ </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">"Printer haqida batafsil ma’lumot"</string> - <string name="print_services_disabled_toast" msgid="9089060734685174685">"Bir qancha chop etish xizmatlari o‘chirilgan"</string> + <string name="print_services_disabled_toast" msgid="9089060734685174685">"Ayrim chop etish xizmatlari o‘chirib qo‘yilgan"</string> <string name="print_searching_for_printers" msgid="6550424555079932867">"Printerlar qidirilmoqda"</string> <string name="print_no_print_services" msgid="8561247706423327966">"Hech qaysi chop etish xizmati yoqilmagan"</string> <string name="print_no_printers" msgid="4869403323900054866">"Printerlar topilmadi"</string> @@ -70,7 +70,7 @@ <string name="enable_print_service" msgid="3482815747043533842">"Yoqish uchun tanlang"</string> <string name="enabled_services_title" msgid="7036986099096582296">"Yoqilgan xizmatlar"</string> <string name="recommended_services_title" msgid="3799434882937956924">"Tavsiya etilgan xizmatlar"</string> - <string name="disabled_services_title" msgid="7313253167968363211">"O‘chirilgan xizmatlar"</string> + <string name="disabled_services_title" msgid="7313253167968363211">"O‘chirib qo‘yilgan xizmatlar"</string> <string name="all_services_title" msgid="5578662754874906455">"Barcha xizmatlar"</string> <string name="printing_notification_title_template" msgid="295903957762447362">"Chop etilmoqda: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> <string name="cancelling_notification_title_template" msgid="1821759594704703197">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> bekor qilinmoqda"</string> diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java index 606f4eb79c2e..645e182f0a1d 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java @@ -20,6 +20,8 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; +import android.os.Handler; +import android.os.Looper; import android.os.ParcelFileDescriptor; import android.print.PageRange; import android.print.PrintAttributes.MediaSize; @@ -570,7 +572,14 @@ public final class PageAdapter extends Adapter<ViewHolder> { if (DEBUG) { Log.i(LOG_TAG, "Requesting pages: " + Arrays.toString(mRequestedPages)); } - mCallbacks.onRequestContentUpdate(); + + // This call might come from a recylerview that is currently updating. Hence delay to + // after the update + (new Handler(Looper.getMainLooper())).post(new Runnable() { + @Override public void run() { + mCallbacks.onRequestContentUpdate(); + } + }); } } diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index a408c0820700..92374cbedec2 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Wys alle ANRe"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Wys Program reageer nie-dialoog vir agtergrond programme"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Programme verplig ekstern toegelaat"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Laat enige program na ekstern geskryf word, ongeag manifeswaardes"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Maak dat enige program in eksterne berging geskryf kan word, ongeag manifeswaardes"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Verplig verstelbare groottes vir aktiwiteite"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Maak die groottes van alle aktiwiteite verstelbaar vir veelvuldige vensters, ongeag manifeswaardes."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktiveer vormvrye-Windows"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 7ae97e2df5b5..386d697e0dbf 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"ሁሉንም ANRs አሳይ"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"ለዳራ መተግበሪያዎች ምላሽ የማይሰጥ መገናኛ ትግበራ አሳይ"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"በውጫዊ ላይ ሃይል ይፈቀዳል"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"አንጸባራቂ እሴቶች ግምት ውስጥ ሳይገቡ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻ ለመጻፍ ብቁ ያደርጋል።"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"የዝርዝር ሰነዶች እሴቶች ግምት ውስጥ ሳያስገባ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻው ለመጻፍ ብቁ ያደርጋል"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"እንቅስቃሴዎች ዳግመኛ እንዲመጣጠኑ አስገድድ"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"የዝርዝር ሰነድ እሴቶች ምንም ይሁኑ ምን ለበርካታ መስኮቶች ሁሉንም እንቅስቃሴዎች መጠናቸው የሚቀየሩ እንዲሆኑ ያደርጋቸዋል።"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"የነጻ ቅርጽ መስኮቶችን ያንቁ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index eb76e1f7153d..2c8eda0e74e7 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"عرض جميع رسائل ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"عرض مربع الحوار \"التطبيق لا يستجيب\" مع تطبيقات الخلفية"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"فرض السماح للتطبيقات على الخارجي"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"تأهيل أي تطبيق بحيث تتم كتابته على سعة تخزين خارجية، بغض النظر عن قيم البيان"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"تأهيل أي تطبيق بحيث تتم كتابته على وحدة تخزين خارجية، بغض النظر عن قيم البيان"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"فرض إمكانية تغيير على الأنشطة"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"تمكين تغيير حجم جميع الأنشطة لتناسب تعدد النوافذ، بغض النظر عن قيم البيان."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"تمكين النوافذ الحرة"</string> diff --git a/packages/SettingsLib/res/values-az-rAZ/strings.xml b/packages/SettingsLib/res/values-az-rAZ/strings.xml index 9903397dc3ae..d62f472d7eef 100644 --- a/packages/SettingsLib/res/values-az-rAZ/strings.xml +++ b/packages/SettingsLib/res/values-az-rAZ/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Bütün ANRları göstər"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Arxa tətbiqlər dialoquna cavab verməyən tətbiqi göstər"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Tətbiqlərə xaricdən məcburi icazə"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Ölçü dəyişdirmək üçün məcburi fəaliyyətlər"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bəyannamə dəyərlərindən aslı olmayaraq, bütün fəaliyyətləri çoxsaylı pəncərə üçün dəyişkən ölçülü edin."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Freeform windows aktiv edin"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index f570d093e813..eb050de44dfa 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaži dijalog Aplikacija ne reaguje za aplikacije u pozadini"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Prinudno dozvoli aplikacije u spoljnoj"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Prinudno omogući promenu veličine aktivnosti"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući promenu veličine svih aktivnosti za režim sa više prozora, bez obzira na vrednosti manifesta."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore proizvoljnog formata"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 72652c9e570c..7640ffd0c0b5 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Всички нереагиращи прил."</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Диалог. прозорец „НП“ за приложения на заден план"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Външно хран.: Принуд. разрешаване на приложенията"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Позволява прилож. да се записват във външ. хранил. независимо от стойностите в манифеста"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Прави всички приложения да отговарят на условията да бъдат записвани във външното хранилище независимо от стойностите в манифеста"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Възможност за преоразмеряване на активностите"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Дава възможност за преоразмеряване на всички активности в режима за няколко прозореца независимо от стойностите в манифеста."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Активиране на прозорците в свободна форма"</string> diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml index b863773ef40d..a1063b96df07 100644 --- a/packages/SettingsLib/res/values-bn-rBD/strings.xml +++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"সব ANR দেখান"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"পশ্চাদপটের অ্যাপ্লিকেশানগুলির জন্য অ্যাপ্লিকেশান কোনো প্রতিক্রিয়া দিচ্ছে না এমন কথোপকথন দেখান"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"বহিরাগততে বলপূর্বক মঞ্জুরি"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ম্যানিফেস্ট মানগুলির নির্বিশেষে মাল্টি-উইন্ডোর জন্য সমস্ত ক্রিয়াকলাপগুলির আকার পরিবর্তনযোগ্য করুন৷"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ফ্রি-ফর্ম উইন্ডোগুলি সক্ষম করুন"</string> diff --git a/packages/SettingsLib/res/values-bs-rBA/strings.xml b/packages/SettingsLib/res/values-bs-rBA/strings.xml index 542c3ce6093c..7a87fda24395 100644 --- a/packages/SettingsLib/res/values-bs-rBA/strings.xml +++ b/packages/SettingsLib/res/values-bs-rBA/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Prik. dijalog Aplikacija ne reagira za apl. u poz."</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Nametni aplikacije na vanjskoj pohrani"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Dozvoljava da bilo koja aplikacija bude upisana na vanjsku pohranu, bez obzira na vrijednosti manifesta."</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava da svaka aplikacija bude pogodna za upisivanje na vanjsku pohranu, bez obzira na prikazane vrijednosti"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni aktivnostima mijenjanje veličina"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Neka sve aktivnosti budu takve da mogu mijenjati veličinu za prikaz sa više prozora, bez obzira na prikazane vrijednosti."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore nepravilnih oblika"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index e2c4495b7427..0249282a4223 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Tots els errors sense resposta"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Informa que una aplicació en segon pla no respon"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Força permís d\'aplicacions a l\'emmagatzem. extern"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet que les aplicacions es puguin escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permet que les aplicacions es puguin escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Força l\'ajust de la mida de les activitats"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet ajustar la mida de totes les activitats per al mode multifinestra, independentment dels valors definits."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activa les finestres de format lliure"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index f713ceb86bff..86f269d73a08 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Zobrazit všechny ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Zobrazovat dialog „Aplikace neodpovídá“ pro aplikace na pozadí"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Vynutit povolení aplikací na externím úložišti"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Vynutit možnost změny velikosti aktivit"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Umožnit změnu velikosti všech aktivit na několik oken (bez ohledu na hodnoty manifestu)"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivovat okna s volným tvarem"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index d1d7b23bf3ce..720aeba6d93a 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Vis alle \"Appen svarer ikke\""</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Vis \"Appen svarer ikke\" for baggrundsapps"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Gennemtving tilladelse til eksternt lager"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til at kunne tilpasses"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tillad, at alle aktiviteter kan tilpasses flere vinduer uafhængigt af manifestværdier."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivér vinduer i frit format"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index fbd1207979e8..ec8407bb3f30 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Alle ANRS anzeigen"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Dialogfeld \"App antwortet nicht\" für Hintergrund-Apps anzeigen"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Externe Speichernutzung von Apps erlauben"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Anpassen der Größe von Aktivitäten erzwingen"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Größe aller Aktivitäten an den Mehrfenstermodus anpassen, unabhängig von den Manifestwerten."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Freiform-Fenster zulassen"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index dce2cf76b3c2..7db585374fb5 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Εμφάνιση όλων των ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Εμφ.του παραθ. \"Η εφαρμ.δεν αποκρ.\" για εφ.παρασκ."</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Να επιτρέπονται υποχρεωτικά εφαρμογές σε εξωτ.συσ."</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό χώρο αποθήκευσης, ανεξάρτητα από τις τιμές του μανιφέστου"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό αποθηκευτικό χώρο, ανεξάρτητα από τις τιμές του μανιφέστου"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Αναγκαστική δυνατότητα αλλαγής μεγέθους δραστηριοτήτων"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Να έχουν όλες οι δραστηριότητες δυνατότητα αλλαγής μεγέθους για την προβολή πολλαπλών παραθύρων, ανεξάρτητα από τις τιμές του μανιφέστου."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ενεργοποίηση παραθύρων ελεύθερης μορφής"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index 4821a719d1f3..28340313da16 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index 4821a719d1f3..28340313da16 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index 4821a719d1f3..28340313da16 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Make all activities resizable for multi-window, regardless of manifest values."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Enable freeform windows"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 2d0ce027caf0..5f7a4478af72 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Errores sin respuesta"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostrar diálogo cuando las aplic. en 2do plano no responden"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permisos en almacenamiento externo"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Cualquier aplicación puede escribirse en una memoria externa, independientemente de los valores del manifiesto."</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Cualquier app puede escribirse en un almacenamiento externo, sin importar los valores del manifiesto"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar actividades para que cambien de tamaño"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permitir que todas las actividades puedan cambiar de tamaño para el modo multiventana, sin importar los valores del manifiesto."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 8dcf6ab8de87..0314f2ef88eb 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Errores sin respuesta"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Informar de que una aplicación en segundo plano no responde"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicaciones de forma externa"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Hace que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hace que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar el ajuste de tamaño de las actividades"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite que se pueda ajustar el tamaño de todas las actividades para el modo multiventana, independientemente de los valores establecidos."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Habilitar ventanas de forma libre"</string> diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml index 62dd7ab70236..6420ccc6fe60 100644 --- a/packages/SettingsLib/res/values-et-rEE/strings.xml +++ b/packages/SettingsLib/res/values-et-rEE/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Näita kõiki ANR-e"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Kuva taustarakendustele dial. Rakendus ei reageeri"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Luba rakendused välises salvestusruumis"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Lubab rakendusi kirjutada välisesse salvestusruumi olenemata manifesti väärtustest"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Lubab mis tahes rakendusi kirjutada välisesse salvestusruumi manifesti väärtustest olenemata"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Muuda tegevuste suurused muudetavaks"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Muudetakse kõigi tegevuste suurused mitme aknaga vaates muudetavaks (manifesti väärtustest olenemata)."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Luba vabas vormis aknad"</string> diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml index cb6f0b47ca36..30bab3c05fe4 100644 --- a/packages/SettingsLib/res/values-eu-rES/strings.xml +++ b/packages/SettingsLib/res/values-eu-rES/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Erakutsi ANR guztiak"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"\"Erantzunik ez\" mezua atz. planoko aplikazioetarako"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Behartu aplikazioak onartzea kanpoko biltegian"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Behartu jardueren tamaina doitu ahal izatea"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Eman aukera jarduera guztien tamaina doitzeko, hainbat leihotan erabili ahal izan daitezen, manifestuan jartzen duena jartzen duela ere."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Gaitu estilo libreko leihoak"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index e7cbd1e05a5f..f1437d75ff8f 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"نمایش تمام ANRها"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"نمایش گفتگوی \"برنامه پاسخ نمیدهد\" برای برنامههای پسزمینه"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"اجازه اجباری به برنامههای دستگاه ذخیره خارجی"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"بدون توجه به مقادیر مانیفست، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"بدون توجه به مقادیر مانیفست، هر برنامهای را برای نوشتن در حافظه خارجی واجد شرایط میکند"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"اجبار فعالیتها به قابل تغییر اندازه بودن"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"بدون توجه به مقادیر مانیفست، اندازه همه فعالیتها برای حالت چند پنجرهای میتواند تغییر کند."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"فعال کردن پنجرههای آزاد"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index bb3ad97e41f3..9717a7853dfb 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Näytä kaikki ANR:t"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Näytä Sovellus ei vastaa -ikkuna taustasovell."</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Salli aina ulkoinen tallennus"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mahdollistaa sovellusten tallentamisen ulkoiseen tall.tilaan luettelosta riippumatta"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Mahdollistaa sovelluksen tietojen tallentamisen ulkoiseen tallennustilaan luetteloarvoista riippumatta."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Pakota kaikki toiminnot hyväksymään koon muutos"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Pakota kaikki toiminnot hyväksymään koon muuttaminen usean ikkunan tilassa luettelon arvoista riippumatta."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ota käyttöön vapaamuotoiset ikkunat"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 1f12f1866a68..80181f0d6001 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"Afficher tous les messages «L\'application ne répond pas»"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Afficher « L\'application ne répond plus » pour applis en arrière-plan"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer l\'autor. d\'applis sur stockage externe"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Permet enreg. d\'applis sur espace stockage externe"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer les activités à être redimensionnables"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permet de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 3dc2a6a27eb0..b8ff857bb333 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Afficher tous les messages ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Afficher \"L\'application ne répond plus\" pour applis en arrière-plan"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer disponibilité stockage externe pour applis"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rend possible enregistrement de toute appli sur espace stockage externe, indépendamment valeurs fichier manifeste."</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Rend possible l\'enregistrement de toute application sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer possibilité de redimensionner les activités"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permettre de redimensionner toutes les activités pour le mode multifenêtre, indépendamment des valeurs du fichier manifeste."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activer les fenêtres de forme libre"</string> diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml index 3715919525ea..2cde75237c25 100644 --- a/packages/SettingsLib/res/values-gl-rES/strings.xml +++ b/packages/SettingsLib/res/values-gl-rES/strings.xml @@ -248,9 +248,9 @@ <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Informa que aplicación segundo plano non responde"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicacións de forma externa"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Fai que calquera aplicación se poida escribir nun almacenamento externo, independentemente dos valores expresados"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permite que calquera aplicación apta se poida escribir nun almacenamento externo, independentemente dos valores expresados"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar o axuste do tamaño das actividades"</string> - <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite axustar o tamaño de todas as actividades para o modo de varias ventás, independentemente dos valores definidos."</string> + <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permite axustar o tamaño de todas as actividades para o modo multiventá, independentemente dos valores definidos."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activar ventás de forma libre"</string> <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa a compatibilidade con ventás de forma libre experimentais."</string> <string name="local_backup_password_title" msgid="3860471654439418822">"Contrasinal para copias"</string> diff --git a/packages/SettingsLib/res/values-gu-rIN/strings.xml b/packages/SettingsLib/res/values-gu-rIN/strings.xml index c77aeb6776c0..9c25a0feab67 100644 --- a/packages/SettingsLib/res/values-gu-rIN/strings.xml +++ b/packages/SettingsLib/res/values-gu-rIN/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"બધા ANR બતાવો"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"પૃષ્ઠભૂમિ એપ્લિકેશનો માટે એપ્લિકેશન પ્રતિસાદ આપતી નથી સંવાદ બતાવો"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"બાહ્ય પર એપ્લિકેશનોને મંજૂરી આપવાની ફરજ પાડો"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ એપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ ઍપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"મૅનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, તમામ પ્રવૃત્તિઓને મલ્ટી-વિંડો માટે ફરીથી કદ બદલી શકે તેવી બનાવો."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ફ્રિફોર્મ વિંડોઝ સક્ષમ કરો"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index e8a47cb69692..2e1b337ed37c 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"सभी ANR दिखाएं"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि ऐप्स के लिए ऐप्स प्रतिसाद नहीं दे रहा डॉयलॉग दिखाएं"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"ऐप्स को बाहरी मेमोरी पर बाध्य करें"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"इससे कोई भी ऐप मेनिफेस्ट मान अनदेखा करके, बाहरी मेमोरी पर लिखने योग्य बन जाता है"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"इससे कोई भी ऐप्लिकेशन, मेनिफेस्ट मानों को अनदेखा करके बाहरी मेमोरी पर लिखने योग्य बन जाता है"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"आकार बदले जाने के लिए गतिविधियों को बाध्य करें"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"सभी गतिविधियों को एकाधिक विंडो के लिए आकार बदलने योग्य बनाएं, चाहे मेनिफेस्ट मान कुछ भी हों."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"फ़्रीफ़ॉर्म विंडो सक्षम करें"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 320ebc17a4f6..f9dd6b731a78 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaz dijaloga o pozad. aplik. koja ne odgovara"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Prisilno dopusti aplikacije u vanjskoj pohrani"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o manifestu"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o vrijednostima manifesta"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni mogućnost promjene veličine za aktivnosti"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Omogući mijenjanje veličine svih aktivnosti za više prozora, neovisno o vrijednostima manifesta."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Omogući prozore slobodnog oblika"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 4ea452834838..94fa1bdd2ccc 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Összes ANR mutatása"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Az Alkalmazás nem válaszol ablak megjelenítése"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Külső tárhely alkalmazásainak engedélyezése"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Lehetővé teszi, hogy külső tárhelyre lehessen írni"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Lehetővé teszi bármely alkalmazás külső tárhelyre való írását a jegyzékértékektől függetlenül"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Tevékenységek átméretezésének kényszerítése"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Legyen az összes tevékenység átméretezhető a többablakos megjelenítés érdekében a jegyzékértékektől függetlenül."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Szabad formájú ablakok engedélyezése"</string> diff --git a/packages/SettingsLib/res/values-hy-rAM/strings.xml b/packages/SettingsLib/res/values-hy-rAM/strings.xml index 046ea489b64a..e9232f52a9a3 100644 --- a/packages/SettingsLib/res/values-hy-rAM/strings.xml +++ b/packages/SettingsLib/res/values-hy-rAM/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Ցույց տալ բոլոր ANR-երը"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Ցուցադրել այն ծրագիրը, որը չի արձագանքում երկխոսությունը հետնաշերտի ծրագրերի համար"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Միշտ թույլատրել ծրագրեր արտաքին պահեստում"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Թույլ է տալիս պահել հավելվածը արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Թույլ է տալիս ցանկացած հավելված պահել արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Ստիպել, որ ակտիվությունների չափերը լինեն փոփոխելի"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Բոլոր ակտիվությունների չափերը բազմապատուհան ռեժիմի համար դարձնել փոփոխելի՝ մանիֆեստի արժեքներից անկախ:"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ակտիվացնել կամայական ձևի պատուհանները"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 02c747a1c1bb..397139845e33 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Tampilkan semua ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Tmplkn dialog Apl Tidak Merespons utk apl ltr blkg"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Paksa izinkan aplikasi di eksternal"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksterna"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktivitas agar ukurannya dapat diubah"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Buat semua aktivitas dapat diubah ukurannya untuk banyak jendela, terlepas dari nilai manifes."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktifkan jendela berformat bebas"</string> diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml index 17a2f0802b85..7f9e7681a005 100644 --- a/packages/SettingsLib/res/values-is-rIS/strings.xml +++ b/packages/SettingsLib/res/values-is-rIS/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Öll forrit sem svara ekki"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Sýna „Forrit svarar ekki“ fyrir bakgrunnsforrit"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Þvinga fram leyfi forrita í ytri geymslu"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gerir hvaða forriti sem er kleift að skrifa í ytri geymslu, burtséð frá gildum í upplýsingaskrá"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Gerir öll forrit skrifanleg í ytra geymslurými, óháð gildum í upplýsingaskrá"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Þvinga breytanlega stærð virkni"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gera stærð allrar virkni breytanlega svo að hún henti fyrir marga glugga, óháð gildum í upplýsingaskrá."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Virkja glugga með frjálsu sniði"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 9c75939c5dab..147ad4da75fa 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Mostra tutti errori ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostra finestra ANR per applicazioni in background"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forza autorizzazione app su memoria esterna"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Rende l\'app idonea all\'installaz. su mem. esterna, senza considerare i valori manifest"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Consente l\'installazione di qualsiasi app su memoria esterna, indipendentemente dai valori manifest"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Imponi formato modificabile alle attività"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Rendi il formato di tutte le attività modificabile per la modalità multi-finestra, indipendentemente dai valori manifest."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Attiva finestre a forma libera"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 429ce612e09d..4fce9b8e0a96 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"הצג את כל פריטי ה-ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"הצג תיבת דו-שיח של \'אפליקציה לא מגיבה\' עבור אפליקציות שפועלות ברקע"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאה של אפליקציות באחסון חיצוני"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"אלץ יכולת קביעת גודל של הפעילויות"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"אפשר יכולת קביעת גודל של כל הפעילויות לריבוי חלונות, ללא קשר לערך המניפסט."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"הפעל את האפשרות לשנות את הגודל והמיקום של החלונות"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 6c42110d1b47..b2b36124d1ff 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"すべてのANRを表示"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"バックグラウンドアプリが応答しない場合に通知する"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"外部ストレージへのアプリの書き込みを許可"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"アクティビティをサイズ変更可能にする"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"マニフェストの値に関係なく、マルチウィンドウですべてのアクティビティのサイズを変更できるようにします。"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"フリーフォーム ウィンドウの有効化"</string> diff --git a/packages/SettingsLib/res/values-ka-rGE/strings.xml b/packages/SettingsLib/res/values-ka-rGE/strings.xml index 6dba53b38224..8c34c6384910 100644 --- a/packages/SettingsLib/res/values-ka-rGE/strings.xml +++ b/packages/SettingsLib/res/values-ka-rGE/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"ყველა ANR-ის ჩვენება"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"შეტყობინების ჩვენება, როცა ფონური აპლიკაცია არ პასუხობს"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"აპების დაშვება გარე მეხსიერებაში"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"აპები ჩაიწერ. გარე მეხს.-ზე აღწ. ფაილის მნიშვნ. მიუხედ."</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"აპები ჩაიწერება გარე მეხსიერებაზე აღწერის ფაილების მნიშვნელობების მიუხედავად"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"ზომაცვლადი აქტივობების იძულება"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"მანიფესტის მნიშვნელობების მიუხედავად, მრავალი ფანჯრის რეჟიმისთვის ყველა აქტივობის ზომაცვლადად გადაქცევა."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"თავისუფალი ფორმის მქონე ფანჯრების ჩართვა"</string> diff --git a/packages/SettingsLib/res/values-kk-rKZ/strings.xml b/packages/SettingsLib/res/values-kk-rKZ/strings.xml index 36843fd5bbc6..47d3458b6450 100644 --- a/packages/SettingsLib/res/values-kk-rKZ/strings.xml +++ b/packages/SettingsLib/res/values-kk-rKZ/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Барлық ANR (қолданба жауап бермеді) хабарларын көрсетіңіз"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Фондық қолданбалардың жауап бермегенін көрсету"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Сыртқыда қолданбаларға мәжбүрлеп рұқсат ету"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Әрекеттерді өлшемін өзгертуге болатын етуге мәжбүрлеу"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест мәндеріне қарамастан бірнеше терезе режимінде барлық әрекеттердің өлшемін өзгертуге рұқсат беру."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Еркін пішіндегі терезелерді қосу"</string> diff --git a/packages/SettingsLib/res/values-km-rKH/strings.xml b/packages/SettingsLib/res/values-km-rKH/strings.xml index 9985a1e1773c..3f2c6c308581 100644 --- a/packages/SettingsLib/res/values-km-rKH/strings.xml +++ b/packages/SettingsLib/res/values-km-rKH/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"បង្ហាញ ANRs ទាំងអស់"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"បង្ហាញប្រអប់កម្មវិធីមិនឆ្លើយតបសម្រាប់កម្មវិធីផ្ទៃខាងក្រោយ"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"បង្ខំឲ្យអនុញ្ញាតកម្មវិធីលើឧបករណ៍ផ្ទុកខាងក្រៅ"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃជាក់លាក់"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"កំណត់ឲ្យសកម្មភាពទាំងអស់អាចប្តូរទំហំបានសម្រាប់ពហុផ្ទាំងវិនដូ ដោយមិនគិតពីតម្លៃមេនីហ្វេស។"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"បើកដំណើរការផ្ទាំងវិនដូទម្រង់សេរី"</string> diff --git a/packages/SettingsLib/res/values-kn-rIN/strings.xml b/packages/SettingsLib/res/values-kn-rIN/strings.xml index 8ca9807cb93d..009b9f770076 100644 --- a/packages/SettingsLib/res/values-kn-rIN/strings.xml +++ b/packages/SettingsLib/res/values-kn-rIN/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"ಎಲ್ಲ ANR ಗಳನ್ನು ತೋರಿಸು"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"ಹಿನ್ನೆಲೆ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ ಎಂಬ ಸಂಭಾಷಣೆ ತೋರಿಸು"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"ಬಾಹ್ಯವಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಒತ್ತಾಯವಾಗಿ ಅನುಮತಿಸಿ"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ಗೆ ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳು ಯಾವುದೇ ಆಗಿದ್ದರೂ, ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಒತ್ತಾಯ ಮಾಡಿ"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳನ್ನು ಪರಿಗಣಿಸದೇ, ಬಹು-ವಿಂಡೊಗೆ ಎಲ್ಲಾ ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಮಾಡಿ."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ಮುಕ್ತಸ್ವರೂಪದ ವಿಂಡೊಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 31e037814168..4bfdbfd14416 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"모든 ANR 보기"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"백그라운드 앱에 대해 앱 응답 없음 대화상자 표시"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"외부에서 앱 강제 허용"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"매니페스트 값에 관계없이 앱을 외부 저장소에 작성"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"활동의 크기가 조정 가능하도록 설정"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"모든 활동을 매니페스트 값에 관계없이 멀티 윈도우용으로 크기 조정 가능하도록 설정"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"자유 형식 창 사용"</string> diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml index fd2d905004f3..d06aec5c446b 100644 --- a/packages/SettingsLib/res/values-ky-rKG/strings.xml +++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Бардык ANR\'лерди көрсөтүү"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Фондогу колдонмолорго Колдонмо Жооп Бербейт деп көрсөтүү"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Тышкы сактагычка сактоого уруксат берүү"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Аракеттердин өлчөмүн өзгөртүүнү мажбурлоо"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Манифест маанилерине карабастан бардык аракеттерди мульти-терезеге өлчөмү өзгөртүлгүдөй кылуу."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Эркин формадагы терезелерди түзүүнү иштетүү"</string> diff --git a/packages/SettingsLib/res/values-lo-rLA/strings.xml b/packages/SettingsLib/res/values-lo-rLA/strings.xml index 605f4765ba4b..c5121a532a2e 100644 --- a/packages/SettingsLib/res/values-lo-rLA/strings.xml +++ b/packages/SettingsLib/res/values-lo-rLA/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"ສະແດງ ANRs ທັງຫມົດ"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"ສະແດງໜ້າຈໍແອັບຯທີ່ບໍ່ຕອບສະໜອງສຳລັບແອັບຯພື້ນຫຼັງ"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"ບັງຄັບອະນຸຍາດແອັບຢູ່ພາຍນອກ"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ບ່ອນຈັດເກັບພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າທີ່ຈະແຈ້ງ"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"ບັງຄັງໃຫ້ກິດຈະກຳປ່ຽນຂະໜາດໄດ້"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ເຮັດໃຫ້ທຸກກິດຈະກຳສາມາດປັບຂະໜາດໄດ້ສຳລັບຫຼາຍໜ້າຈໍ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ເປີດໃຊ້ໜ້າຕ່າງຮູບແບບອິດສະຫຼະ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 253eeb375af4..dd1ccc84d9c8 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Rodyti visus ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Fon. programose rodyti dialogo langą „Neatsako“"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Priverstinai leisti programas išorinėje atmintin."</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Vis. pr. gal. įr. į vid. saug. nepais. apr. vert."</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Nustatoma, kad visas programas būtų galima įrašyti į išorinę saugyklą, nepaisant aprašo verčių"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Nustatyti, kad visus veiksmus būtų galima atlikti kelių dydžių languose, nepaisant aprašo verčių."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Įgalinti laisvos formos langus"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 3323cd99d164..009ccf6b113d 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Rādīt visus ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Rādīt fona lietotņu dialoglodz. Lietotne nereaģē"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Lietotņu piespiedu atļaušana ārējā krātuvē"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Pielāgot darbības"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Pielāgot visas darbības vairāku logu režīmam neatkarīgi no vērtībām manifestā."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Iespējot brīvās formas logus"</string> diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml index 41c8600f892f..0c2ddf4cafdb 100644 --- a/packages/SettingsLib/res/values-mk-rMK/strings.xml +++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"Прикажи ги сите ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Прикажи „Апл. не реагира“ за. апл. во заднина"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Принуд. дозволете апликации на надворешна меморија"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Запишува апл. во надв.меморија, незав. од манифест"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"Принуди ги активностите да ја менуваат големината"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Направете сите активности да бидат со променлива големина за повеќе прозорци, без разлика на вредностите на манифестот."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Овозможи прозорци со слободна форма"</string> diff --git a/packages/SettingsLib/res/values-ml-rIN/strings.xml b/packages/SettingsLib/res/values-ml-rIN/strings.xml index 80cf43ecc49b..3b4acd2656b0 100644 --- a/packages/SettingsLib/res/values-ml-rIN/strings.xml +++ b/packages/SettingsLib/res/values-ml-rIN/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"എല്ലാ ANR-കളും ദൃശ്യമാക്കുക"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"പശ്ചാത്തല അപ്ലിക്കേഷനുകൾക്ക് അപ്ലിക്കേഷൻ പ്രതികരിക്കുന്നില്ല എന്ന ഡയലോഗ് കാണിക്കുക"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"ബാഹ്യമായതിൽ നിർബന്ധിച്ച് അനുവദിക്കുക"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"വലിപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, എല്ലാ ആക്ടിവിറ്റികളെയും മൾട്ടി-വിൻഡോയ്ക്കായി വലിപ്പം മാറ്റുക."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"ഫ്രീഫോം വിൻഡോകൾ പ്രവർത്തനക്ഷമമാക്കുക"</string> diff --git a/packages/SettingsLib/res/values-mn-rMN/strings.xml b/packages/SettingsLib/res/values-mn-rMN/strings.xml index 5e7ea1544911..4473f7f18158 100644 --- a/packages/SettingsLib/res/values-mn-rMN/strings.xml +++ b/packages/SettingsLib/res/values-mn-rMN/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"Бүх ANRs харуулах"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Далд апп-уудад Апп Хариу Өгөхгүй байна гэснийг харуулах"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Апп-ыг гадаад санах ойд хадгалахыг зөвшөөрөх"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Манифест утгыг нь үл хамааран дурын апп-ыг гадаад санах ойд бичих боломжтой болгодог"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Тодорхойлогч файлын утгыг үл хамааран, бүх үйл ажиллагааны хэмжээг олон цонхонд өөрчилж болохуйц болгоно уу."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Чөлөөт хэлбэрийн цонхыг идэвхжүүлэх"</string> diff --git a/packages/SettingsLib/res/values-mr-rIN/strings.xml b/packages/SettingsLib/res/values-mr-rIN/strings.xml index 7a3d76db967c..d8075aa22380 100644 --- a/packages/SettingsLib/res/values-mr-rIN/strings.xml +++ b/packages/SettingsLib/res/values-mr-rIN/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"सर्व ANR दर्शवा"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"पार्श्वभूमी अॅप्ससाठी अॅप प्रतिसाद देत नाही संवाद दर्शवा"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यवर अॅप्सना अनुमती देण्याची सक्ती करा"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, कोणत्याही अॅपला बाह्य संचयनावर लेखन केले जाण्यासाठी पात्र बनविते"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, कोणत्याही अॅपला बाह्य संचयनावर लेखन केले जाण्यासाठी पात्र बनविते"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"क्रियाकलापाचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, एकाधिक-विंडोसाठी सर्व क्रियाकलापांचा आकार बदलण्यायोग्य करा."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"freeform विंडो सक्षम करा"</string> diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml index 3f2968711d7b..44ed1f6a068f 100644 --- a/packages/SettingsLib/res/values-ms-rMY/strings.xml +++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"Tunjukkan semua ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Tunjukkan dialog Aplikasi Tidak Memberi Maklum Balas untuk aplikasi latar belakang"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Benarkan apl secara paksa pada storan luaran"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Menjadikan sebarang apl layak ditulis ke storan luaran, walau apa juga nilai manifesnya"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktiviti supaya boleh diubah saiz"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bolehkan semua saiz aktiviti diubah untuk berbilang tetingkap, tanpa mengambil kira nilai manifes."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Dayakan tetingkap bentuk bebas"</string> diff --git a/packages/SettingsLib/res/values-my-rMM/strings.xml b/packages/SettingsLib/res/values-my-rMM/strings.xml index 71862a308098..bf2ea80f4d01 100644 --- a/packages/SettingsLib/res/values-my-rMM/strings.xml +++ b/packages/SettingsLib/res/values-my-rMM/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"ANRsအားလုံးအား ပြသရန်"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"နောက်ခံအပ်ပလီကေးရှင်းအတွက်တုံ့ပြန်မှုမရှိပြရန်"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"အပြင်မှာ အတင်း ခွင့်ပြုရန်"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ပြနေတဲ့ တန်ဖိုး ဘယ်လိုပဲရှိနေနေ၊ ဘယ် appကို မဆို အပြင် သိုလှောင်ခန်းသို့ ရေးသားခွင့် ပေးတယ်"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"တိကျစွာ သတ်မှတ်ထားသည့်တန်ဖိုးများရှိသော်လည်း၊ ပြင်ပသိုလှောင်ခန်းများသို့ မည်သည့်အက်ပ်ကိုမဆို သိမ်းဆည်းခွင့်ပြုပါ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"လုပ်ဆောင်ချက်များ ဆိုက်ညှိရနိုင်ရန် လုပ်ခိုင်းပါ"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"မန်နီးဖက်စ်တန်ဖိုးများ မည်မျှပင်ရှိစေကာမူ၊ ဝင်းဒိုးများအတွက် လှုပ်ရှားမှုများအားလုံးကို အရွယ်အစားချိန်ခြင်း ပြုလုပ်ပါ။"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"အခမဲ့ပုံစံ ဝင်းဒိုးကို ဖွင့်ပါ"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 2ad14dcbb197..94993d4bb14a 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Vis alle ANR-er"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Vis Appen svarer ikke-dialog for bakgrunnsapper"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Tving frem tillatelse for ekstern lagring av apper"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Gjør at apper kan skrives til ekstern lagring, uavhengig av manifestverdier"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Dette gjør at alle apper kan lagres på ekstern lagring – uavhengig av manifestverdier"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til å kunne endre størrelse"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gjør at alle aktivitetene kan endre størrelse for flervindusmodus, uavhengig av manifestverdier."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Slå på vinduer i fritt format"</string> diff --git a/packages/SettingsLib/res/values-ne-rNP/strings.xml b/packages/SettingsLib/res/values-ne-rNP/strings.xml index 6c8dc59c8b9e..8d253154ec3b 100644 --- a/packages/SettingsLib/res/values-ne-rNP/strings.xml +++ b/packages/SettingsLib/res/values-ne-rNP/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"सबै ANRs देखाउनुहोस्"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि अनुप्रयोगका लागि जवाफ नदिइरहेका अनुप्रयोगहरू देखाउनुहोस्"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यमा बल प्रयोगको अनुमति प्राप्त अनुप्रयोगहरू"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"म्यानिफेेस्टको उपेक्षा गरी, कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न योग्य बनाउँछ"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"म्यानिफेेस्टका मानहरूको ख्याल नगरी कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न सकिने खाले बनाउँछ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"गतिविधिहरू रिसाइज गर्नको लागि बाध्य गर्नुहोस्"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"म्यानिफेेस्ट मानहरूको ख्याल नगरी, बहु-विन्डोको लागि सबै रिसाइज गर्न सकिने गतिविधिहरू बनाउनुहोस्।"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"फ्रिफर्म विन्डोहरू सक्रिय गर्नुहोस्"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index 7f9df25cdf40..c60e9df610b5 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Alle ANR\'s weergeven"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"\'App reageert niet\' weerg. voor apps op achtergr."</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Toestaan van apps op externe opslag afdwingen"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Hierdoor komt een app in aanmerking om te worden geschreven naar externe opslag, ongeacht de manifestwaarden"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hiermee komt elke app in aanmerking voor schrijven naar externe opslag, ongeacht de manifestwaarden"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Formaat activiteiten geforceerd aanpasbaar maken"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Het formaat van alle activiteiten aanpasbaar maken, ongeacht de manifestwaarden."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Vensters met vrije vorm inschakelen"</string> diff --git a/packages/SettingsLib/res/values-pa-rIN/strings.xml b/packages/SettingsLib/res/values-pa-rIN/strings.xml index 10d57f426837..3771536bc887 100644 --- a/packages/SettingsLib/res/values-pa-rIN/strings.xml +++ b/packages/SettingsLib/res/values-pa-rIN/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"ਸਾਰੇ ANR ਦਿਖਾਓ"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"ਪਿਛੋਕੜ ਐਪਸ ਲਈ ਐਪਸ ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਹੇ ਡਾਇਲੌਗ ਦਿਖਾਓ"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"ਐਪਸ ਨੂੰ ਬਾਹਰਲੇ ਤੇ ਜ਼ਬਰਦਸਤੀ ਆਗਿਆ ਦਿਓ"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ਇੱਕ ਐਪ ਨੂੰ ਬਾਹਰਲੀ ਸਟੋਰੇਜ ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਮੈਨੀਫੈਸਟ ਵੈਲਯੂਜ ਤੇ ਵਿਚਾਰ ਕੀਤੇ ਬਿਨਾਂ"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਕਿਸੇ ਵੀ ਐਪ ਨੂੰ ਬਾਹਰੀ ਸਟੋਰੇਜ \'ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"ਮੁੜ-ਆਕਾਰ ਬਦਲਣ ਲਈ ਸਰਗਰਮੀਆਂ \'ਤੇ ਜ਼ੋਰ ਦਿਓ"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਮਲਟੀ-ਵਿੰਡੋ ਲਈ ਸਾਰੀਆਂ ਸਰਗਰਮੀਆਂ ਨੂੰ ਆਕਾਰ ਬਦਲਣਯੋਗ ਬਣਾਓ।"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"freeform windows ਨੂੰ ਯੋਗ ਬਣਾਓ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 3e8909408e19..cd4cc83bec89 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Pokaż wszystkie ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Pokaż okno Aplikacja Nie Reaguje dla aplikacji w tle"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Wymuś zezwalanie na aplikacje w pamięci zewn."</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Pozwala na zapis aplikacji w pamięci zewn. niezależnie od wartości w pliku manifestu"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Pozwala na zapis aplikacji w pamięci zewnętrznej niezależnie od wartości w pliku manifestu"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Wymuś zmianę rozmiaru okien aktywności"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Zezwól na zmianę rozmiaru wszystkich okien aktywności w trybie wielu okien niezależnie od ustawień w pliku manifestu."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Włącz dowolny rozmiar okien"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index c772ded4482a..64a97b9f0072 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANRS"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Exibir \"App não responde\" para app em 2º plano"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualifica apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 2b3dcc75032f..b648589f8b4a 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostrar erro \"Aplic. não Resp.\" p/ aplic. 2º plano"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar perm. de aplicações no armazenamento ext."</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualquer aplic. pode ser gravada no arm. ext., independ. dos valores do manif."</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Torna qualquer aplicação elegível para ser gravada no armazenamento externo, independentemente dos valores do manifesto"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar as atividades a serem redimensionáveis"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index c772ded4482a..64a97b9f0072 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANRS"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Exibir \"App não responde\" para app em 2º plano"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Qualifica apps p/ gravação em armazenamento externo, independentemente de valores de manifestos"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualifica apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Tornar todas as atividades redimensionáveis para várias janelas, independentemente dos valores do manifesto."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Ativar janelas de forma livre"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 0322f55af58d..b0c50649573a 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Afișați toate elem. ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Aplicații din fundal: afișați Aplicația nu răspunde"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Forțați accesul aplicațiilor la stocarea externă"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Forțați redimensionarea activităților"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Permiteți redimensionarea tuturor activităților pentru modul cu ferestre multiple, indiferent de valorile manifestului."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Activați ferestrele cu formă liberă"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 7548ace52c35..4aa4c1006c64 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Все ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Уведомлять о том, что приложение не отвечает"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Разрешить сохранение на внешние накопители"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Разрешает сохранение приложений на внешние накопители независимо от значения манифеста"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Разрешает сохранение приложений на внешних накопителях независимо от значений манифеста"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Изменение размера в многооконном режиме"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Разрешить изменение размера в многооконном режиме (независимо от значений манифеста)"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Разрешить создание окон произвольной формы"</string> diff --git a/packages/SettingsLib/res/values-si-rLK/strings.xml b/packages/SettingsLib/res/values-si-rLK/strings.xml index f3d6dc3686cd..b5053ddce0cf 100644 --- a/packages/SettingsLib/res/values-si-rLK/strings.xml +++ b/packages/SettingsLib/res/values-si-rLK/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"සියලුම ANR පෙන්වන්න"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"පසුබිම් යෙදුම් වලට යෙදුම ප්රතිචාර නොදක්වයි කවුළුව පෙන්වන්න"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"බාහිර මත යෙදුම් ඉඩ දීම බල කරන්න"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් අභ්යන්තර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"ක්රියාකාරකම් ප්රතිප්රමාණ කළ හැකි බවට බල කරන්න"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"මැනිෆෙස්ට් අගයන් නොසලකා, සියලු ක්රියාකාරකම් බහු-කවුළුව සඳහා ප්රතිප්රමාණ කළ හැකි බවට පත් කරන්න."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"අනියම් හැඩැති කවුළු සබල කරන්න"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 712c34893081..852bd9e34dba 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Zobrazovať všetky ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Zobrazovať dialóg „Aplikácia neodpovedá“ aj pre aplikácie na pozadí"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Vynútiť povolenie aplikácií na externom úložisku"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Vynútiť možnosť zmeny veľkosti aktivít"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Veľkosti všetkých aktivít bude možné zmeniť na niekoľko okien (bez ohľadu na hodnoty manifestu)."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Povoliť okná s voľným tvarom"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 2f23144ba46a..830399f48fb6 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Pokaži okna neodzivanj"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaz pogovornega okna za neodzivanje aplikacije v ozadju"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Vsili omogočanje aplikacij v zunanji shrambi"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Vsili povečanje velikosti za aktivnosti"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsem aktivnostim povečati velikost za način z več okni."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Omogočanje oken svobodne oblike"</string> diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml index 853dd2fb4d66..10b91346968c 100644 --- a/packages/SettingsLib/res/values-sq-rAL/strings.xml +++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Shfaq raportet ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Shfaq raportet ANR (Aplikacioni nuk përgjigjet) për aplikacionet në sfond"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Detyro lejimin në hapësirën e jashtme"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Detyro madhësinë e ndryshueshme për aktivitetet"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Bëj që të gjitha aktivitetet të kenë madhësi të ndryshueshme për përdorimin me shumë dritare, pavarësisht vlerave të manifestit."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivizo dritaret me formë të lirë"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 094a405dce93..51b2b10ebf3c 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Прикажи све ANR-ове"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Прикажи дијалог Апликација не реагује за апликације у позадини"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Принудно дозволи апликације у спољној"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Принудно омогући промену величине активности"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Омогући промену величине свих активности за режим са више прозора, без обзира на вредности манифеста."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Омогући прозоре произвољног формата"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index e12d39445950..c19f7f46209f 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Visa alla som inte svarar"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Visa dialogrutan om att appen inte svarar för bakgrundsappar"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Tillåt appar i externt lagringsutrymme"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Appen kan skrivas till extern lagring, oavsett manifestvärden"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Allar appar kan skrivas till extern lagring, oavsett manifestvärden"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Framtvinga storleksanpassning för aktiviteter"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gör det möjligt att ändra storleken på alla aktiviteter i flerfönsterläge, oavsett manifestvärden."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Aktivera frihandsfönster"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index d5a9d1b2989a..091a447f05d0 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Onyesha ANR zote"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Onyesha kisanduku kidadisi cha Programu Haiitikii kwa programu za usuli"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Lazima uruhusu programu kwenye hifadhi ya nje"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Huweka programu kwenye hifadhi ya nje, bila kujali maelezo"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Huruhusu programu yoyote iwekwe kwenye hifadhi ya nje, bila kujali thamani za faili ya maelezo"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Fanya shughuli zote ziweze kubadilishwa ukubwa kwenye madirisha mengi, bila kuzingatia thamani za faili ya maelezo."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Washa madirisha yenye muundo huru"</string> diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml index 5c7732f81612..105b98003e38 100644 --- a/packages/SettingsLib/res/values-ta-rIN/strings.xml +++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"எல்லா ANRகளையும் காட்டு"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"பின்புலப் பயன்பாடுகளுக்குப் பயன்பாடு பதிலளிக்கவில்லை என்ற உரையாடலைக் காட்டு"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"பயன்பாடுகளை வெளிப்புறச் சேமிப்பிடத்தில் அனுமதி"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"மேனிஃபெஸ்ட் மதிப்புகளை பொருட்படுத்தாமல், எந்தப் பயன்பாட்டையும் வெளிப்புற சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், பல சாளரத்திற்கு எல்லா செயல்பாடுகளையும் அளவுமாறக்கூடியதாக அமை."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"குறிப்பிட்ட வடிவமில்லாத சாளரங்களை இயக்கு"</string> diff --git a/packages/SettingsLib/res/values-te-rIN/strings.xml b/packages/SettingsLib/res/values-te-rIN/strings.xml index a74fc8207f32..91ee5fa9d2ca 100644 --- a/packages/SettingsLib/res/values-te-rIN/strings.xml +++ b/packages/SettingsLib/res/values-te-rIN/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"అన్ని ANRలను చూపు"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"నేపథ్య అనువర్తనాల కోసం అనువర్తనం ప్రతిస్పందించడం లేదు డైలాగ్ను చూపు"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"అనువర్తనాలను బాహ్య నిల్వలో నిర్బంధంగా అనుమతించు"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయగలిగేలా అనుమతిస్తుంది"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయడానికి అనుమతిస్తుంది"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"కార్యాచరణలను పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా అన్ని కార్యాచరణలను పలు రకాల విండోల్లో సరిపోయేట్లు పరిమాణం మార్చగలిగేలా చేస్తుంది."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"స్వతంత్ర రూప విండోలను ప్రారంభించండి"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 53caea574786..b5ec3d9ea381 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"แสดง ANR ทั้งหมด"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"แสดงหน้าต่างแอปไม่ตอบสนอง สำหรับแอปพื้นหลัง"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"บังคับให้แอปสามารถใช้ที่เก็บภายนอก"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"ให้สามารถเขียนแอปต่างๆ ไปยังที่เก็บภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"บังคับให้กิจกรรมปรับขนาดได้"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"ทำให้กิจกรรมทั้งหมดปรับขนาดได้สำหรับหน้าต่างหลายบาน โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"เปิดใช้หน้าต่างรูปแบบอิสระ"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 0c1f1678e125..d3bcc5fde9b0 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"Ipakita ang lahat ng ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"App Not Responding dialog para sa background apps"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Pwersahang payagan ang mga app sa external"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Mara-write na sa external storage ang anumang app, anuman ang manifest value"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"Sapilitang gawing resizable ang mga aktibidad"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Gawing nare-resize ang lahat ng aktibidad para sa multi-window, anuman ang mga value ng manifest."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"I-enable ang mga freeform window"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 230da226301a..a8f26202d7d3 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"Tüm ANR\'leri göster"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Arka plan uygulamalar için Uygulama Yanıt Vermiyor mesajını göster"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Harici birimdeki uygulamalara izin vermeye zorla"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Bildirilen değerlerden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Manifest değerlerinden bağımsız olarak, tüm etkinlikleri birden fazla pencerede yeniden boyutlandırılabilir yap."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Serbest biçimli pencereleri etkinleştir"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 01cedc6c03ad..d094ef7f5617 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Показувати всі ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Сповіщати, коли додаток не відповідає"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Примусово записувати додатки в зовнішню пам’ять"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Додатки можна записувати на зовнішню пам’ять незалежно від значень маніфесту"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Можна записувати додатки в зовнішню пам’ять, незалежно від значень у маніфесті"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Примусово масштабувати активність"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Масштабувати активність на кілька вікон, незалежно від значень у файлі маніфесту."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Увімкнути вікна довільного формату"</string> diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml index 878ff0cf29fc..27046dc6c60e 100644 --- a/packages/SettingsLib/res/values-ur-rPK/strings.xml +++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"سبھی ANRs کو دکھائیں"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"پس منظر کی ایپس کیلئے ایپ جواب نہیں دے رہی ہے ڈائلاگ دکھائیں"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"بیرونی پر ایپس کو زبردستی اجازت دیں"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"سرگرمیوں کو ری سائز ایبل بنائیں"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"manifest اقدار سے قطع نظر، ملٹی ونڈو کیلئے تمام سرگرمیوں کو ری سائز ایبل بنائیں۔"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"freeform ونڈوز فعال کریں"</string> diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml index d81a0414cb5b..031f8f7ce864 100644 --- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml +++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Hamma ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Ilova javob bermayotgani haqida xabar qilish"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Tashqi xotira qurilmasidagi ilova dasturlariga majburiy ruxsat berish"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Manifest qiymatidan qat’i nazar barcha harakatlarni ko‘p oynali rejimga moslashtirish."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Erkin shakldagi oynalarni yoqish"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 2b4bddd118c0..f3fb96a353a8 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"Hiển thị tất cả ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Hiện hộp thoại Ứng dụng ko đáp ứng cho ứng dụng nền"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Buộc cho phép các ứng dụng trên bộ nhớ ngoài"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Giúp ứng dụng bất kỳ đủ điều kiện được ghi vào bộ nhớ ngoài bất kể giá trị tệp kê khai là gì"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"Buộc các hoạt động có thể thay đổi kích thước"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Giúp tất cả hoạt động có thể thay đổi kích thước cho nhiều cửa sổ bất kể giá trị tệp kê khai là gì."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Bật cửa sổ dạng tự do"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 48f03b7616bb..348a319ebec6 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"显示所有“应用无响应”(ANR)"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"为后台应用显示“应用无响应”对话框"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"强制允许将应用写入外部存储设备"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"强制将活动设为可调整大小"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"将所有 Activity 设为可配合多窗口环境调整大小(忽略清单值)。"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"启用可自由调整的窗口"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 38656e570e2f..6adabc986f37 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"顯示所有 ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"顯示背景應用程式的「應用程式無回應」對話框"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許應用程式寫入到外部儲存空間"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將所有應用程式寫入到外部儲存完間 (所有資訊清單值)"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"強制可變更活動尺寸"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"在任何資訊清單值下,允許系統配合多重視窗環境調整所有活動的尺寸。"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形態視窗"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index af83365e969e..f4aade029aa7 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -248,7 +248,8 @@ <string name="show_all_anrs" msgid="28462979638729082">"顯示所有無回應程式"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"為背景應用程式顯示「應用程式無回應」對話方塊"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string> + <!-- no translation found for force_allow_on_external_summary (3640752408258034689) --> + <skip /> <string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"將所有活動設為可配合多重視窗環境調整大小 (無論資訊清單值為何)。"</string> <string name="enable_freeform_support" msgid="1461893351278940416">"啟用自由形式視窗"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 16841d3297df..268cdb2b809e 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -248,7 +248,7 @@ <string name="show_all_anrs" msgid="28462979638729082">"Bonisa wonke ama-ANR"</string> <string name="show_all_anrs_summary" msgid="641908614413544127">"Boniso idayalogi Yohlelo Lokusebenza Olungasabeli kwizinhlelo zokusebenza zasemuva"</string> <string name="force_allow_on_external" msgid="3215759785081916381">"Phoqelela ukuvumela izinhlelo zokusebenza ngaphandle"</string> - <string name="force_allow_on_external_summary" msgid="3191952505860343233">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string> + <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string> <string name="force_resizable_activities" msgid="8615764378147824985">"Imisebenzi yamandla izonikezwa usayizi omusha"</string> <string name="force_resizable_activities_summary" msgid="6667493494706124459">"Yenza yonke imisebenzi ibe nosayizi abasha kumawindi amaningi, ngokunganaki amavelu e-manifest."</string> <string name="enable_freeform_support" msgid="1461893351278940416">"Nika amandla amawindi e-freeform"</string> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index e4c2cbc92702..1aee490593e6 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -687,7 +687,7 @@ <!-- Developer settings: select WebView provider dialog title [CHAR LIMIT=30] --> <string name="select_webview_provider_dialog_title">Set WebView implementation</string> <!-- Developer settings: text for the WebView provider selection toast shown if an invalid provider was chosen (i.e. the setting list was stale). [CHAR LIMIT=NONE] --> - <string name="select_webview_provider_toast_text">The chosen WebView implementation is invalid because the list of implementation choices grew stale. The list should now be updated.</string> + <string name="select_webview_provider_toast_text">This choice is no longer valid. Try again.</string> <!-- Developer settings screen, convert userdata to file encryption option name --> <string name="convert_to_file_encryption">Convert to file encryption</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java index 47023c108eab..d0aba227baa5 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java @@ -146,12 +146,13 @@ public class RestrictedPreferenceHelper { public boolean setDisabledByAdmin(EnforcedAdmin admin) { final boolean disabled = (admin != null ? true : false); mEnforcedAdmin = admin; - mPreference.setEnabled(!disabled); + boolean changed = false; if (mDisabledByAdmin != disabled) { mDisabledByAdmin = disabled; - return true; + changed = true; } - return false; + mPreference.setEnabled(!disabled); + return changed; } public boolean isDisabledByAdmin() { diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java index fa2226d229be..74c1ebdd2a79 100644 --- a/packages/SettingsLib/src/com/android/settingslib/Utils.java +++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java @@ -151,10 +151,17 @@ public class Utils { if (sSystemSignature == null) { sSystemSignature = new Signature[]{ getSystemSignature(pm) }; } - return sSystemSignature[0] != null && sSystemSignature[0].equals(getFirstSignature(pkg)); + if (sPermissionControllerPackageName == null) { + sPermissionControllerPackageName = pm.getPermissionControllerPackageName(); + } + return (sSystemSignature[0] != null + && sSystemSignature[0].equals(getFirstSignature(pkg))) + || (sPermissionControllerPackageName != null + && sPermissionControllerPackageName.equals(pkg.packageName)); } private static Signature[] sSystemSignature; + private static String sPermissionControllerPackageName; private static Signature getFirstSignature(PackageInfo pkg) { if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) { diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java index 7a1c741eb490..ce69c5a86b72 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java @@ -103,16 +103,6 @@ public class SettingsDrawerActivity extends Activity { } @Override - public void onBackPressed() { - if (mShowingMenu) { - // If we are showing the menu, then we are a top level activity and the back should - // kick back to settings home. - openTile(null); - } - super.onBackPressed(); - } - - @Override public boolean onOptionsItemSelected(MenuItem item) { if (mShowingMenu && mDrawerLayout != null && item.getItemId() == android.R.id.home && mDrawerAdapter.getCount() != 0) { diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 987b5ea2db09..743912a12935 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -207,6 +207,10 @@ public class SettingsProvider extends ContentProvider { @Override public Bundle call(String method, String name, Bundle args) { + // If the remote side sent us bad parcelables, they won't get the + // results they want, which is their loss. + if (args != null) args.setDefusable(true); + final int requestingUserId = getRequestingUserId(args); switch (method) { case Settings.CALL_METHOD_GET_GLOBAL: { diff --git a/packages/Shell/res/layout/dialog_bugreport_info.xml b/packages/Shell/res/layout/dialog_bugreport_info.xml index b6b8d6bcf2b2..bb3084f5c10a 100644 --- a/packages/Shell/res/layout/dialog_bugreport_info.xml +++ b/packages/Shell/res/layout/dialog_bugreport_info.xml @@ -19,6 +19,7 @@ android:paddingTop="15dp" android:paddingStart="24dp" android:paddingEnd="24dp" + android:focusableInTouchMode="true" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView @@ -30,7 +31,6 @@ android:id="@+id/name" android:maxLength="30" android:singleLine="true" - android:selectAllOnFocus="true" android:inputType="textNoSuggestions" android:layout_width="match_parent" android:layout_height="wrap_content"/> diff --git a/packages/Shell/res/values-am/strings.xml b/packages/Shell/res/values-am/strings.xml index fae820ce84e0..b0d3de08fe42 100644 --- a/packages/Shell/res/values-am/strings.xml +++ b/packages/Shell/res/values-am/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"ቀፎ"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> እየተመነጨ ነው"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> ተወስዷል"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> ፎቶ ተነስቷል፣ ነገር ግን ቅጽበታዊ ገጽ ማያ በመጠባበቅ ላይ ነው"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"ዝርዝሮችን ወደ የሳንካ ሪፖርቱ በማከል ላይ"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"እባክዎ ይጠብቁ…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"የሳንካ ሪፖርትዎን ለማጋራት ወደ ግራ ያንሸራትቱ"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"የሳንካ ሪፖርትዎን ለማጋራት መታ ያድርጉ"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"የእርስዎን የሳንካ ሪፖርት ያለ ቅጽበታዊ ማያ ገጽ ለማጋራት መታ ያድርጉ ወይም ቅጽበታዊ ማያ ገጹ እስኪጨርስ ይጠብቁ"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"የእርስዎን የሳንካ ሪፖርት ያለ ቅጽበታዊ ማያ ገጽ ለማጋራት መታ ያድርጉ ወይም ቅጽበታዊ ማያ ገጹ እስኪጨርስ ይጠብቁ"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"የሳንካ ሪፖርቶች የግል መረጃን ጨምሮ ከበርካታ የስርዓቱ ምዝግብ ማስታወሻዎች የመጣ ውሂብን ይዟል። የሳንካ ሪፖርቶች ለሚያምኗቸው መተግበሪያዎችን እና ሰዎችን ብቻ ያጋሩ።"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ይህን መልዕክት በሚቀጥለው ጊዜ አሳይ"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"የሳንካ ሪፖርቶች"</string> diff --git a/packages/Shell/res/values-az-rAZ/strings.xml b/packages/Shell/res/values-az-rAZ/strings.xml index 6172e7d559d1..22791a6ef639 100644 --- a/packages/Shell/res/values-az-rAZ/strings.xml +++ b/packages/Shell/res/values-az-rAZ/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> yaradıldı"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> alındı"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> baq hesabatı çəkildi, amma skrinşot hələ gözlənilir"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Detallar baq hesabatına əlavə olunur"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lütfən, gözləyin..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Baq raportunu paylaşmaq üçün sola sürüşdürün"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Baq hesabatınızı paylaşmaq üçün tıklayın"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"baq hesabatınızı skrinşot olmadan paylaşmaq üçün tıklayın, skrinşotun tamamlanması üçün isə gözləyin"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Baq raportları sistemin müxtəlif jurnal fayllarından data içərir ki, buna şəxsi və konfidensial məlumatlar da aiddir. Yalnız inandığınız adamlarla baq raportlarını paylaşın."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bu mesajı növbəti dəfə göstər"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Baq hesabatları"</string> diff --git a/packages/Shell/res/values-bg/strings.xml b/packages/Shell/res/values-bg/strings.xml index 6a69f7de5b29..0f8676f1787c 100644 --- a/packages/Shell/res/values-bg/strings.xml +++ b/packages/Shell/res/values-bg/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Команден ред"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Сигналът за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“ се генерира"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Сигналът за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“ е заснет"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Сигналът (<xliff:g id="ID">#%d</xliff:g>) е заснет, но екр. снимка не е готова"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Подробностите се добавят към сигнала за пр. грешка"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Моля, изчакайте…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Прекарайте пръст наляво, за да споделите сигнала си за програмна грешка"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Докоснете, за да споделите сигнала си за програмна грешка"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Докоснете, за да споделите сигнала за прогр. грешка без екранна снимка, или изчакайте завършването й"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Докоснете, за да споделите сигнала за прогр. грешка без екранна снимка, или изчакайте завършването й"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Отчетите за програмни грешки съдържат данни от различни регистрационни файлове на системата, включително лична и поверителна информация. Споделяйте ги само с приложения и хора, на които имате доверие."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Това съобщение да се показва следващия път"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Отчети за прогр. грешки"</string> diff --git a/packages/Shell/res/values-bs-rBA/strings.xml b/packages/Shell/res/values-bs-rBA/strings.xml index a38be0e29a80..f4d71e910676 100644 --- a/packages/Shell/res/values-bs-rBA/strings.xml +++ b/packages/Shell/res/values-bs-rBA/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Ljuska"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Izvještaj o grešci <xliff:g id="ID">#%d</xliff:g> se generira"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Izvještaj o grešci <xliff:g id="ID">#%d</xliff:g> je snimljen"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Izvještaj o greškama <xliff:g id="ID">#%d</xliff:g> snimljen, čeka se snim. ekr."</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodavanje detalja u izvještaj o greškama"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Pričekajte..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Prevucite lijevo da podijelite izvještaj o greškama"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dodirnite da biste podijelili izvještaj o grešci"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dodirnite da podijelite izveštaj o greškama bez snimka ekrana ili sačekajte da snimak bude gotov"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dodirnite da podijelite izveštaj o greškama bez snimka ekrana ili sačekajte da snimak bude gotov"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Izvještaji o greškama sadrže podatke iz raznih zapisnika sistema, uključujući lične i privatne informacije. Podijelite izvještaje o greškama samo sa aplikacijama i osobama kojima vjerujete."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaži ovu poruku sljedeći put"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Izvještaji o greškama"</string> diff --git a/packages/Shell/res/values-ca/strings.xml b/packages/Shell/res/values-ca/strings.xml index c246ec400dcf..3efb53b99cc3 100644 --- a/packages/Shell/res/values-ca/strings.xml +++ b/packages/Shell/res/values-ca/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Protecció"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"S\'està generant l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"S\'ha capturat l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"L\'informe d\'errors <xliff:g id="ID">#%d</xliff:g> s\'ha capturat (captura pendent)"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"S\'estan afegint detalls a l\'informe d\'errors"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Llisca cap a l\'esquerra per compartir l\'informe d\'errors."</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca per compartir l\'informe d\'errors"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca per compartir l\'informe d\'errors sense captura de pantalla o espera que es creï la captura"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca per compartir l\'informe d\'errors sense captura de pantalla o espera que es creï la captura"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Els informes d\'error contenen dades dels diferents fitxers de registre del sistema, inclosa informació privada i personal. Comparteix els informes d\'error només amb les aplicacions i amb les persones en qui confies."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra aquest missatge la propera vegada"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes d\'error"</string> diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml index ebd9b5303175..afb6f9e8b5cb 100644 --- a/packages/Shell/res/values-cs/strings.xml +++ b/packages/Shell/res/values-cs/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Zpráva o chybě <xliff:g id="ID">#%d</xliff:g> se vytváří"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Zpráva o chybě <xliff:g id="ID">#%d</xliff:g> byla vytvořena"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Zpráva o chybě <xliff:g id="ID">#%d</xliff:g> byla vytvořena, čeká se na snímek"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Přidávání podrobností do zprávy o chybě"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Čekejte prosím…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Chcete-li hlášení chyby sdílet, přejeďte doleva."</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Zprávu o chybě můžete sdílet klepnutím"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Klepnutím můžete zprávu o chybě sdílet bez snímku obrazovky, nebo vyčkejte, než se snímek připraví"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Klepnutím můžete zprávu o chybě sdílet bez snímku obrazovky, nebo vyčkejte, než se snímek připraví"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Chybová hlášení obsahují data z různých souborů protokolů systému včetně osobních a soukromých informací. Chybová hlášení sdílejte pouze s aplikacemi a uživateli, kterým důvěřujete."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobrazit tuto zprávu příště"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Zprávy o chybách"</string> diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml index 3f7f4d60fba7..307548a75140 100644 --- a/packages/Shell/res/values-es-rUS/strings.xml +++ b/packages/Shell/res/values-es-rUS/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Se está generando el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Se capturó el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Informe de errores <xliff:g id="ID">#%d</xliff:g> capturado (captura pendiente)"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Agregando detalles al informe de errores"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Desliza el dedo hacia la izquierda para compartir el informe de errores."</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir el informe de errores"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir tu informe de errores sin una captura de pantalla o espera a que finalice"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir tu informe de errores sin una captura de pantalla o espera a que finalice"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida la información personal y privada. Comparte los informes de errores únicamente con aplicaciones y personas en las que confíes."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de errores"</string> diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml index 68abf83b4ed8..730ae73cb1a5 100644 --- a/packages/Shell/res/values-es/strings.xml +++ b/packages/Shell/res/values-es/strings.xml @@ -19,13 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Se está generando el informe de errores <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Informe de errores <xliff:g id="ID">#%d</xliff:g> capturado"</string> - <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Informe de errores <xliff:g id="ID">#%d</xliff:g> capturado (captura pendiente)"</string> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Informe <xliff:g id="ID">#%d</xliff:g> registrado (captura pantalla pendiente)"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Añadiendo detalles al informe de errores"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Espera…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Desliza el dedo hacia la izquierda para compartir el informe de error"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir el informe de errores"</string> - <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir informe de errores sin captura de pantalla o espera a que se haga la captura."</string> - <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir informe de errores sin captura de pantalla o espera a que se haga la captura."</string> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir el informe de errores sin captura de pantalla o espera a que se haga la captura."</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir el informe de errores sin captura de pantalla o espera a que se haga la captura."</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida información personal y privada. Comparte los informes de errores únicamente con aplicaciones y usuarios en los que confíes."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de error"</string> diff --git a/packages/Shell/res/values-eu-rES/strings.xml b/packages/Shell/res/values-eu-rES/strings.xml index 8f4d219796a1..7946f67aee92 100644 --- a/packages/Shell/res/values-eu-rES/strings.xml +++ b/packages/Shell/res/values-eu-rES/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell-interfazea"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostena egiten ari gara"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostena egin da"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Egin da <xliff:g id="ID">#%d</xliff:g> txostena. Pantaila-argazkia falta da."</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Akatsen txostenean xehetasunak gehitzen"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Itxaron, mesedez…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Programa-akatsen txostena partekatzeko, pasatu hatza ezkerrera"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Sakatu akatsen txostena partekatzeko"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Akatsen txostenek sistemaren erregistro-fitxategietako datuak dauzkate, informazio pertsonala eta pribatua barne. Akatsen txostenak partekatzen badituzu, partekatu soilik aplikazio eta pertsona fidagarriekin."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Erakutsi mezu hau hurrengoan"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Akatsen txostenak"</string> diff --git a/packages/Shell/res/values-fa/strings.xml b/packages/Shell/res/values-fa/strings.xml index c0f4d2adcae2..ecadf1a8fac6 100644 --- a/packages/Shell/res/values-fa/strings.xml +++ b/packages/Shell/res/values-fa/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"گزارش اشکال <xliff:g id="ID">#%d</xliff:g> در حال ایجاد شدن است"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"گزارش اشکال <xliff:g id="ID">#%d</xliff:g> ثبت شد"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"گزارش اشکال <xliff:g id="ID">#%d</xliff:g> گرفته شد اما عکس از صفحهنمایش هنوز نه"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"اضافه کردن جزئیات به گزارش اشکال"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"لطفاً منتظر بمانید..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"برای اشتراکگذاری گزارش اشکال، به تندی آن را به چپ بکشید"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"برای به اشتراک گذاشتن گزارش اشکال، ضربه بزنید"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"برای اشتراکگذاری گزارش مشکل بدون عکس صفحهنمایش، ضربه بزنید یا صبر کنید تا عکس صفحهنمایش گرفته شود."</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"برای اشتراکگذاری گزارش مشکل بدون عکس صفحهنمایش، ضربه بزنید یا صبر کنید تا عکس صفحهنمایش گرفته شود."</string> <string name="bugreport_confirm" msgid="5130698467795669780">"گزارشهای اشکال حاوی دادههایی از فایلهای گزارش مختلف در سیستم هستند، شامل اطلاعات شخصی و خصوصی. گزارشهای اشکال را فقط با افراد و برنامههای مورد اعتماد خود به اشتراک بگذارید."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"دفعه بعد این پیام نشان داده شود"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"گزارش اشکال"</string> diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml index 64245aa5e005..b5ae006a8487 100644 --- a/packages/Shell/res/values-fi/strings.xml +++ b/packages/Shell/res/values-fi/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Komentotulkki"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Luodaan virheraporttia <xliff:g id="ID">#%d</xliff:g>."</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Virheraportti <xliff:g id="ID">#%d</xliff:g> tallennettu"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Virheraportti <xliff:g id="ID">#%d</xliff:g> tallennettu, kuvakaappaus odottaa."</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Lisätään tietoja virheraporttiin"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Odota…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Jaa virheraportti pyyhkäisemällä vasemmalle"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Jaa virheraportti napauttamalla."</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Jaa virheraportti ilman kuvakaappausta napauttamalla tai odota, että kuvakaappaus latautuu."</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Jaa virheraportti ilman kuvakaappausta napauttamalla tai odota, että kuvakaappaus latautuu."</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Virheraportit sisältävät järjestelmän lokitietoja, ja niihin voi sisältyä henkilökohtaisia ja yksityisiä tietoja. Jaa virheraportteja vain luotettaville sovelluksille ja käyttäjille."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Näytä tämä viesti seuraavalla kerralla"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Virheraportit"</string> diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml index 9575273b2033..6c40edd4cea3 100644 --- a/packages/Shell/res/values-fr-rCA/strings.xml +++ b/packages/Shell/res/values-fr-rCA/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Rapport de bogue <xliff:g id="ID">#%d</xliff:g> généré"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Rapport de bogue <xliff:g id="ID">#%d</xliff:g> enregistré"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Rap. bogue <xliff:g id="ID">#%d</xliff:g> enreg., mais attente de saisie d\'écran"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Ajout de détails au rapport de bogue"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Veuillez patienter…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Faites glisser le doigt vers la gauche pour partager votre rapport de bogue."</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Touchez ici pour partager votre rapport de bogue"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Touchez pour partager le rapport de bogue sans saisie d\'écran ou attendez que la saisie soit prête"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Touchez pour partager le rapport de bogue sans saisie d\'écran ou attendez que la saisie soit prête"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bogue contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bogue qu\'avec les applications et les personnes que vous estimez fiables."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports de bogues"</string> diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml index 83d30e6c861b..54f0b98c08f3 100644 --- a/packages/Shell/res/values-fr/strings.xml +++ b/packages/Shell/res/values-fr/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\" est en cours de création"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\" a bien été enregistré"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Rapport bug \"<xliff:g id="ID">#%d</xliff:g>\" enregistré, mais attente capt. écran"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Ajout d\'informations au rapport de bug"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Veuillez patienter…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Faites glisser le doigt vers la gauche pour partager votre rapport d\'erreur."</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Appuyer pour partager votre rapport de bug"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Appuyer pour partager rapport de bug sans capture d\'écran ou attendre finalisation capture d\'écran"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Appuyer pour partager rapport de bug sans capture d\'écran ou attendre finalisation capture d\'écran"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bug contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bug qu\'avec les applications et les personnes que vous estimez fiables."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapports d\'erreur"</string> diff --git a/packages/Shell/res/values-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml index e462ceefcfe2..d4610977ba4b 100644 --- a/packages/Shell/res/values-gl-rES/strings.xml +++ b/packages/Shell/res/values-gl-rES/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Estase xerando o informe de erros <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Rexistrouse o informe de erros <xliff:g id="ID">#%d</xliff:g>"</string> - <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Inf. erros rexistrado <xliff:g id="ID">#%d</xliff:g> e captura pantalla pendente"</string> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Inf. erros <xliff:g id="ID">#%d</xliff:g> rexistrado e captura pantalla pendente"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Engadindo detalles ao informe de erro"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Agarda..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Pasa o dedo á esquerda para compartir o teu informe de erros"</string> diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml index 3cfe2f7c9903..c9351c2de692 100644 --- a/packages/Shell/res/values-hy-rAM/strings.xml +++ b/packages/Shell/res/values-hy-rAM/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Խեցի"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցը ստեղծվում է"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցը գրանցվեց"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցը ստեղծվել է, սակայն էկրանի պատկերը դեռ չի ստացվել"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Տվյալների ավելացում վրիպակի զեկույցում"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Խնդրում ենք սպասել…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Սահեցրեք ձախ՝ սխալի հաշվետվությունը համօգտագործելու համար"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Հպեք՝ վրիպակի զեկույցը տրամադրելու համար"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Հպեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Հպեք՝ վրիպակի զեկույցն առանց էկրանի պատկերի ուղարկելու համար կամ սպասեք էկրանի պատկերի ստեղծմանը"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Վրիպակի զեկույցները պարունակում են տվյալներ համակարգի տարբեր մուտքի ֆայլերից, այդ թվում նաև անհատական և գաղտնի տեղեկություններ: Վրիպակի զեկույցները կիսեք միայն այն հավելվածների և մարդկանց հետ, որոնց վստահում եք:"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Այս հաղորդագրությունը ցույց տալ հաջորդ անգամ"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Վրիպակների հաշվետվություններ"</string> diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml index d7d62e298680..5c4b8d3f324c 100644 --- a/packages/Shell/res/values-it/strings.xml +++ b/packages/Shell/res/values-it/strings.xml @@ -19,13 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generazione segnalazione di bug <xliff:g id="ID">#%d</xliff:g> in corso"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Segnalazione di bug <xliff:g id="ID">#%d</xliff:g> acquisita"</string> - <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Segnalazione di bug <xliff:g id="ID">#%d</xliff:g> acquisita, screenshot in attesa"</string> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Segnalazione bug <xliff:g id="ID">#%d</xliff:g> acquisita, screenshot in attesa"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Aggiunta di dettagli alla segnalazione di bug"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Attendi..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Scorri verso sinistra per condividere il rapporto sui bug"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Tocca per condividere la segnalazione di bug"</string> - <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tocca per condividere la segnalazione di bug senza screenshot o attendi che lo screenshot sia completo"</string> - <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tocca per condividere la segnalazione di bug senza screenshot o attendi che lo screenshot sia completo"</string> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Tocca per inviare la segnalazione del bug senza screenshot o attendi che lo screenshot sia completo"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Tocca per inviare la segnalazione del bug senza screenshot o attendi che lo screenshot sia completo"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Le segnalazioni di bug contengono dati da vari file di log del sistema, incluse informazioni personali e private. Condividi le segnalazioni di bug solo con app e persone attendibili."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra questo messaggio la prossima volta"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapporti sui bug"</string> diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml index 33ddec97abf7..a6ff33eef24f 100644 --- a/packages/Shell/res/values-ja/strings.xml +++ b/packages/Shell/res/values-ja/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"シェル"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"バグレポート <xliff:g id="ID">#%d</xliff:g> の生成中"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"バグレポート <xliff:g id="ID">#%d</xliff:g> の記録完了"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"バグレポート <xliff:g id="ID">#%d</xliff:g> 記録完了: スクリーンショット待ち"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"バグレポートに詳細情報を追加しています"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"お待ちください…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"バグレポートを共有するには左にスワイプ"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"バグレポートを共有するにはタップします"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"タップしてバグレポートをスクリーンショットなしで共有するか、スクリーンショット完成までお待ちください"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"タップしてバグレポートをスクリーンショットなしで共有するか、スクリーンショット完成までお待ちください"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"バグレポートには、個人の非公開情報など、システムのさまざまなログファイルのデータが含まれます。共有する場合は信頼するアプリとユーザーのみを選択してください。"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"このメッセージを次回も表示する"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"バグレポート"</string> diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml index 61bdff7c8cb5..119c360e2c06 100644 --- a/packages/Shell/res/values-ka-rGE/strings.xml +++ b/packages/Shell/res/values-ka-rGE/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"გარეკანი"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g> გენერირდება"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g> აღბეჭდილია"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ხარვეზის ანგარიში <xliff:g id="ID">#%d</xliff:g> მზადაა. იქმნება ეკრანის ანაბეჭდი"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"ხარვეზის შესახებ ანგარიშს დეტალები ემატება"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"გთხოვთ, მოითმინოთ..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"გაასრიალეთ მარცხნივ თქვენი ხარვეზის შეტყობინების გასაზიარებლად"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"შეეხეთ ხარვეზების შესახებ ანგარიშის გასაზიარებლად"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"შეეხეთ ხარვეზის შესახებ ანგარიშის ეკრანის ანაბეჭდის გარეშე გასაზიარებლად, ან დაელოდეთ მის შექმნას"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"შეეხეთ ხარვეზის შესახებ ანგარიშის ეკრანის ანაბეჭდის გარეშე გასაზიარებლად, ან დაელოდეთ მის შექმნას"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"ხარვეზის ანგარიშები მოიცავს მონაცემებს სხვადასხვა სისტემური ჟურნალის ფაილებიდან, მათ შორის პირად და კონფიდენციალურ ინფორმაციას."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"შემდგომში აჩვენე ეს შეტყობინება"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"შეცდომების ანგარიშები"</string> diff --git a/packages/Shell/res/values-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml index 403615a4dc2c..90028ca462b3 100644 --- a/packages/Shell/res/values-kk-rKZ/strings.xml +++ b/packages/Shell/res/values-kk-rKZ/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Қабыршық"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі жасалуда"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі жазып алынды"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі жазып алынды, бірақ скриншот әлі сақталған жоқ"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Қате туралы есепке мәліметтер қосылуда"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күте тұрыңыз…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Қате туралы есепті бөлісу үшін солға жанаңыз"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Қате туралы есепті бөлісу үшін түртіңіз"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Қате туралы есепті скриншотсыз бөлісу үшін түртіңіз немесе скриншот сақталып болғанша күтіңіз"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Қате туралы есепті скриншотсыз бөлісу үшін түртіңіз немесе скриншот сақталып болғанша күтіңіз"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Вирус туралы баянатта жүйеде тіркелген әртүрлі файлдар туралы деректер болады, оған жеке және құпия ақпарат та кіреді. Вирус баянаттарын сенімді қолданбалар және сенімді адамдармен ғана бөлісіңіз."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Бұл хабарды келесі жолы көрсетіңіз"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Қате туралы баяндамалар"</string> diff --git a/packages/Shell/res/values-km-rKH/strings.xml b/packages/Shell/res/values-km-rKH/strings.xml index 05f5cc5c14b7..d5fc400c46bb 100644 --- a/packages/Shell/res/values-km-rKH/strings.xml +++ b/packages/Shell/res/values-km-rKH/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"សែល"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"<xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុសកំពុងត្រូវបានបង្កើត"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"<xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុសត្រូវបានថត"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុសត្រូវបានថត ប៉ុន្តែរូបថតអេក្រង់មិនទាន់បានថតនៅឡើយទេ"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"កំពុងបន្ថែមព័ត៌មានលម្អិតទៅរបាយការណ៍កំហុស"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"សូមរង់ចាំ…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"អូសទៅឆ្វេង ដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នក"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នក"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នកដោយមិនចាំបាច់មានរូបថតអេក្រង់ ឬរង់ចាំការបញ្ចប់ការថតអេក្រង់"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ប៉ះដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នកដោយមិនចាំបាច់មានរូបថតអេក្រង់ ឬរង់ចាំការបញ្ចប់ការថតអេក្រង់"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"របាយការណ៍កំហុសរួមមានឯកសារកំណត់ហេតុផ្សេងៗរបស់ប្រព័ន្ធ រួមមានព័ត៌មានផ្ទាល់ខ្លួន និងឯកជន។ ចែករំលែករបាយការណ៍កំហុសជាមួយកម្មវិធី និងមនុស្សដែលអ្នកទុកចិត្ត។"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"បង្ហាញសារនេះពេលក្រោយ"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"រាយការណ៍ពីកំហុស"</string> diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml index 808730485abe..4c0a16988eff 100644 --- a/packages/Shell/res/values-ko/strings.xml +++ b/packages/Shell/res/values-ko/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"셸"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 생성 중"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 캡처됨"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"버그 신고 <xliff:g id="ID">#%d</xliff:g>이(가) 캡처되었으나 스크린샷 대기 중"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"세부정보를 버그 보고서에 추가"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"잠시 기다려 주세요..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"왼쪽으로 스와이프하여 버그 신고서를 공유하세요."</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"버그 신고를 공유하려면 탭하세요."</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"스크린샷 없이 버그 신고서를 공유하려면 탭하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요."</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"스크린샷 없이 버그 신고서를 공유하려면 탭하고 그렇지 않으면 스크린샷이 완료될 때까지 기다려 주세요."</string> <string name="bugreport_confirm" msgid="5130698467795669780">"버그 신고서는 시스템의 다양한 로그 파일 데이터(예: 개인 및 비공개 정보)를 포함합니다. 신뢰할 수 있는 앱과 사용자에게만 버그 신고서를 공유하세요."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"다음에 이 메시지 표시"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"버그 신고"</string> diff --git a/packages/Shell/res/values-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml index cc5b2e502e11..16a954931a6c 100644 --- a/packages/Shell/res/values-ky-rKG/strings.xml +++ b/packages/Shell/res/values-ky-rKG/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Командалык кабык"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> түзүлүүдө"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> жаздырылды"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> даяр, скриншот күтүлүүдө"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Мүчүлүштүк жөнүндө кабардын чоо-жайы кошулууда"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күтө туруңуз…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Ката жөнүндө кабар менен бөлүшүү үчүн солго серпип коюңуз"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Мүчүлүштүк тууралуу билдирүүңүздү бөлүшүү үчүн таптап коюңуз"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Ката тууралуу билдирүүлөр системанын ар кандай лог файлдарынын берилиштерин камтыйт, аларга өздүк жана купуя маалыматтар дагы кирет. Ката тууралуу билдирүүлөрдү сиз ишенген колдонмолор жана адамдар менен гана бөлүшүңүз."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Бул билдирүү кийин көрсөтүлсүн"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Мүчүлүштүктөрдү кабарлоолор"</string> diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml index 7685d4431c5f..28045286ec89 100644 --- a/packages/Shell/res/values-lo-rLA/strings.xml +++ b/packages/Shell/res/values-lo-rLA/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ກຳລັງສ້າງລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"ບັນທຶກລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g> ແລ້ວ"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ບັນທຶກລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g> ແລ້ວແຕ່ກຳລັງລໍຖ້າຮູບໜ້າຈໍຢູ່"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"ກຳລັງເພີ່ມລາຍລະອຽດໃສ່ລາຍງານຂໍ້ຜິດພາດ"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"ກະລຸນາລໍຖ້າ..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ປັດໄປຊ້າຍເພື່ອສົ່ງລາຍງານຂໍ້ຜິດພາດຂອງທ່ານ"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານ"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານໂດຍບໍ່ໃຊ້ຮູບໜ້າຈໍ ຫຼື ລໍຖ້າໃຫ້ຮູບໜ້າຈໍແລ້ວໆ"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ແຕະເພື່ອແບ່ງປັນລາຍງານຂໍ້ຜິດພາດຂອງທ່ານໂດຍບໍ່ໃຊ້ຮູບໜ້າຈໍ ຫຼື ລໍຖ້າໃຫ້ຮູບໜ້າຈໍແລ້ວໆ"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"ການລາຍງານຂໍ້ຜິດພາດປະກອບມີ ຂໍ້ມູນຈາກໄຟລ໌ບັນທຶກຂອງລະບົບຫຼາຍໄຟລ໌, ຮວມທັງຂໍ້ມູນສ່ວນໂຕນຳ. ທ່ານຕ້ອງແບ່ງປັນລາຍງານຂໍ້ຜິດພາດໃຫ້ແອັບຯ ແລະຄົນທີ່ທ່ານເຊື່ອຖືໄດ້ເທົ່ານັ້ນ."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ສະແດງຂໍ້ຄວາມນີ້ອີກໃນເທື່ອຕໍ່ໄປ"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"ລາຍງານບັນຫາ"</string> diff --git a/packages/Shell/res/values-lt/strings.xml b/packages/Shell/res/values-lt/strings.xml index 202401ad873d..a8468cfadcee 100644 --- a/packages/Shell/res/values-lt/strings.xml +++ b/packages/Shell/res/values-lt/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Apvalkalas"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Pranešimas apie riktą (<xliff:g id="ID">#%d</xliff:g>) generuojamas"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Pranešimas apie riktą (<xliff:g id="ID">#%d</xliff:g>) užfiksuotas"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Pranešimas apie riktą (<xliff:g id="ID">#%d</xliff:g>) užfiksuotas, bet laukiama ekrano kopijos"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Pridedama informacijos prie pranešimo apie riktą"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Palaukite…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Perbraukite kairėn, kad bendrintumėte rikto ataskaitą"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Palieskite, kad bendrintumėte pranešimą apie riktą"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Palieskite ir bendrinkite pranešimą apie riktą be ekrano kopijos arba palaukite, kol ji bus sukurta"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Palieskite ir bendrinkite pranešimą apie riktą be ekrano kopijos arba palaukite, kol ji bus sukurta"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Riktų ataskaitose pateikiami duomenys iš įvairių sistemos žurnalo failų, įskaitant asmeninę ir privačią informaciją. Riktų ataskaitas bendrinkite tik su patikimomis programomis ir žmonėmis."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rodyti šį pranešimą kitą kartą"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Riktų ataskaitos"</string> diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml index 93de35d94fa4..08e25be530da 100644 --- a/packages/Shell/res/values-lv/strings.xml +++ b/packages/Shell/res/values-lv/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Aizsargs"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g> tiek ģenerēts"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g> reģistrēts"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g> izveidots; gaida ekrānuzņēmumu"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Informācijas pievienošana kļūdas pārskatam"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lūdzu, uzgaidiet..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Velciet pa kreisi, lai kopīgotu savu kļūdu ziņojumu."</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Pieskarieties, lai kopīgotu kļūdas pārskatu."</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Pieskarieties, lai kopīgotu kļūdas pārskatu bez ekrānuzņēmuma vai gaidiet ekrānuzņēmumu."</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Pieskarieties, lai kopīgotu kļūdas pārskatu bez ekrānuzņēmuma vai gaidiet ekrānuzņēmumu."</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Kļūdu pārskatā ir iekļauti dati no dažādiem sistēmas žurnālfailiem, tostarp personas dati un privāta informācija. Kļūdu pārskatus ieteicams kopīgot tikai ar uzticamām lietotnēm un lietotājiem."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rādīt šo ziņojumu nākamajā reizē"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Kļūdu ziņojumi"</string> diff --git a/packages/Shell/res/values-mk-rMK/strings.xml b/packages/Shell/res/values-mk-rMK/strings.xml index f274f6d954f1..3f879b7e7c43 100644 --- a/packages/Shell/res/values-mk-rMK/strings.xml +++ b/packages/Shell/res/values-mk-rMK/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Обвивка"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Се генерира извештајот за грешки <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Извештајот за грешки <xliff:g id="ID">#%d</xliff:g> е снимен"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Извештајот за грешка <xliff:g id="ID">#%d</xliff:g> е снимен. Се чека на сликата"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Се додаваат детали на извештајот за грешка"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Почекајте..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Повлечете налево за да споделите пријава за грешка"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Допрете за да го споделите извештајот за грешки"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Допрете за споделување извештај за грешки без слика од екранот или почекајте да се подготви сликата"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Допрете за споделување извештај за грешки без слика од екранот или почекајте да се подготви сликата"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Извештаите за грешка содржат податоци од разни датотеки за евиденција на системот, вклучувајќи лични и приватни информации. Извештаите за грешка споделувајте ги само со апликации и луѓе на коишто им верувате."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Прикажи ја поракава следниот пат"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Извештаи за грешки"</string> diff --git a/packages/Shell/res/values-ml-rIN/strings.xml b/packages/Shell/res/values-ml-rIN/strings.xml index d5d2e4e5e372..3bb715d822d1 100644 --- a/packages/Shell/res/values-ml-rIN/strings.xml +++ b/packages/Shell/res/values-ml-rIN/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"ഷെൽ"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> സൃഷ്ടിക്കുന്നു"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> ക്യാപ്ചർ ചെയ്തു"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> ക്യാപ്ചർ ചെയ്തു, എന്നാൽ സ്ക്രീൻഷോട്ട് ശേഷിക്കുന്നു"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"ബഗ് റിപ്പോർട്ടിലേക്ക് വിശദാംശങ്ങൾ ചേർക്കുന്നു"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"കാത്തിരിക്കുക..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടുന്നതിന് ഇടത്തേയ്ക്ക് സ്വൈപ്പുചെയ്യുക"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"വ്യക്തിഗതവും സ്വകാര്യവുമായ വിവരങ്ങൾ ഉൾപ്പെടെ, സിസ്റ്റത്തിന്റെ നിരവധി ലോഗ് ഫയലുകളിൽ നിന്നുള്ള ഡാറ്റ, ബഗ് റിപ്പോർട്ടുകളിൽ അടങ്ങിയിരിക്കുന്നു. നിങ്ങൾ വിശ്വസിക്കുന്ന അപ്ലിക്കേഷനുകൾക്കും ആളുകൾക്കും മാത്രം ബഗ് റിപ്പോർട്ടുകൾ പങ്കിടുക."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ഈ സന്ദേശം അടുത്ത തവണ ദൃശ്യമാക്കുക"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"ബഗ് റിപ്പോർട്ടുകൾ"</string> diff --git a/packages/Shell/res/values-mn-rMN/strings.xml b/packages/Shell/res/values-mn-rMN/strings.xml index cce21078b147..296afabf8ff5 100644 --- a/packages/Shell/res/values-mn-rMN/strings.xml +++ b/packages/Shell/res/values-mn-rMN/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Шел"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g> үүсгэгдэж байна"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g>-г бүртгэгдлээ"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Алдааны тайлан <xliff:g id="ID">#%d</xliff:g>-г илрүүлсэн хэдий ч дэлгэцээс авсан зураг хүлээгдэж байна"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Алдааны тайланд дэлгэрэнгүй мэдээлэл нэмж байна"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Түр хүлээнэ үү..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Өөрийн согог репортыг хуваалцахын тулд зүүн шудрана уу"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Програмд гарсан алдааны мэдээллээ хуваалцах бол дарна уу"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Алдааны тайлангаа дэлгэцээс авсан зураггүйгээр хуваалцах бол дарж, эсвэл дэлгэцээс авсан зургийг бэлэн болтол нь хүлээнэ үү"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Алдааны тайлангаа дэлгэцээс авсан зураггүйгээр хуваалцах бол дарж, эсвэл дэлгэцээс авсан зургийг бэлэн болтол нь хүлээнэ үү"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Алдааны репорт нь хувийн болон нууц мэдээлэл зэргийг агуулсан системийн төрөл бүрийн лог файлын датаг агуулна. Алдааны репортыг зөвхөн итгэлтэй апп болон хүмүүст хуваалцана уу."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Энэ мессежийг дараагийн удаа харуулах"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Гэмтлийн тухай тайлан"</string> diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml index b23a382a4519..46bc1a977038 100644 --- a/packages/Shell/res/values-ms-rMY/strings.xml +++ b/packages/Shell/res/values-ms-rMY/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Laporan pepijat <xliff:g id="ID">#%d</xliff:g> sedang dijana"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Laporan pepijat <xliff:g id="ID">#%d</xliff:g> telah ditangkap"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Laporan pepijat <xliff:g id="ID">#%d</xliff:g> ditangkap, menunggu tngkpn skrin"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Menambahkan butiran pada laporan pepijat"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Sila tunggu…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Leret ke kiri untuk berkongsi laporan pepijat anda"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Ketik untuk berkongsi laporan pepijat anda"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ketik untuk berkongsi laporan pepijat anda tanpa tangkapan skrin atau tunggu tangkapan skrin selesai"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Ketik untuk berkongsi laporan pepijat anda tanpa tangkapan skrin atau tunggu tangkapan skrin selesai"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Laporan pepijat mengandungi data dari pelbagai fail log sistem, termasuk maklumat peribadi dan sulit. Kongsikan laporan pepijat hanya dengan apl dan orang yang anda percayai."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tunjukkan mesej ini pada masa akan datang"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Laporan pepijat"</string> diff --git a/packages/Shell/res/values-my-rMM/strings.xml b/packages/Shell/res/values-my-rMM/strings.xml index cecd20fcf27a..6f02e70a3cdc 100644 --- a/packages/Shell/res/values-my-rMM/strings.xml +++ b/packages/Shell/res/values-my-rMM/strings.xml @@ -19,13 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"အခွံ"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> ကိုထုတ်နေပါသည်"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> ကိုရယူထားပြီးပါပြီ"</string> - <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ချွတ်ယွင်းချက် အစီရင်ခံစာ <xliff:g id="ID">#%d</xliff:g> ဖမ်းယူထားသည် သို့သော် မျက်နှာပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း စောင့်ဆိုင်းနေသည်"</string> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"ချွတ်ယွင်းချက် အစီရင်ခံစာ <xliff:g id="ID">#%d</xliff:g> ဖမ်းယူထားသည် သို့သော် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း စောင့်ဆိုင်းနေသည်"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"ချွတ်ယွင်းချက်အစီရင်ခံချက်သို့ အသေးစိတ်များပေါင်းထည့်ရန်"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"ခေတ္တစောင့်ပါ..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"သင်၏ ဘာဂ် အစီရင်ခံစာကို မျှပေးရန် ဘယ်ဘက်သို့ ပွတ်ဆွဲရန်"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"သင့်ချွတ်ယွင်းမှုအစီရင်ခံချက်ကို မျှဝေရန် တို့ပါ"</string> - <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံချက်ကို မျက်နှာပြင်ဓတ်ပုံမှတ်တမ်း မပါဘဲမျှဝေရန် တို့ပါ သို့မဟုတ် မျက်နှာပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string> - <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံချက်ကို မျက်နှာပြင်ဓတ်ပုံမှတ်တမ်း မပါဘဲမျှဝေရန် တို့ပါ သို့မဟုတ် မျက်နှာပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံစာကို ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းမပါဘဲ မျှဝေရန် တို့ပါ သို့မဟုတ် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံစာကို ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းမပါဘဲ မျှဝေရန် တို့ပါ သို့မဟုတ် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"အမှားအယွင်း မှတ်တမ်းမှာ ပါရှိသော အချက်အလက်များမှာ ကိုယ်ရေးကိုယ်တာ နဲ့ လုံခြုံရေး အချက်အလက်များပါဝင်သော စနစ်မှ ပြုလုပ်မှု မှတ်တမ်းများ ဖြစ်ပါသည်၊ အမှားအယွင်း မှတ်တမ်းများကို ယုံကြည်ရသော အပလီကေးရှင်းများနဲ့ လူများကိုသာ ပေးဝေပြသမှု လုပ်ပါရန်။"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ဤစာတန်းကို နောက်တစ်ခါတွင် ပြရန်"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"ချို့ယွင်းမှု အစီရင်ခံစာများ"</string> diff --git a/packages/Shell/res/values-ne-rNP/strings.xml b/packages/Shell/res/values-ne-rNP/strings.xml index 9fb1bcbb2bdd..906d82457abf 100644 --- a/packages/Shell/res/values-ne-rNP/strings.xml +++ b/packages/Shell/res/values-ne-rNP/strings.xml @@ -24,8 +24,8 @@ <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा गर्नुहोला..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"तपाईँको बग रिपोर्ट साझेदारी गर्न बायाँ स्वाइप गर्नुहोस्"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"तपाईंको बग रिपोर्टलाई साझेदारी गर्न ट्याप गर्नुहोस्"</string> - <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string> - <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुने प्रतीक्षा गर्नुहोस्"</string> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"तपाईँको बग रिपोर्टलाई स्क्रिनसट बिना साझेदारी गर्नका लागि ट्याप गर्नुहोस् वा स्क्रिनसट लिने प्रक्रिया पूरा हुन प्रतीक्षा गर्नुहोस्"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"बग रिपोर्टहरूमा प्रणालीका विभिन्न लग फाइलहरूबाट व्यक्तिगत तथा नीजि सूचनासहितको डेटा रहन्छ। बग रिपोर्टहरू अनुप्रयोगहरू र तपाईँले विश्वास गरेका व्यक्तिहरूसँग मात्र साझेदारी गर्नुहोस्।"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"यो सन्देश अर्को पटक देखाउनुहोस्"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रिपोर्टहरू"</string> diff --git a/packages/Shell/res/values-pt-rBR/strings.xml b/packages/Shell/res/values-pt-rBR/strings.xml index 438c031a0d8f..2306c39ac414 100644 --- a/packages/Shell/res/values-pt-rBR/strings.xml +++ b/packages/Shell/res/values-pt-rBR/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório do bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado, captura pendente"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslize para a esquerda para compartilhar seu relatório de bugs"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório do bug"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string> diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml index 438c031a0d8f..2306c39ac414 100644 --- a/packages/Shell/res/values-pt/strings.xml +++ b/packages/Shell/res/values-pt/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"O relatório do bug <xliff:g id="ID">#%d</xliff:g> está sendo gerado"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Relatório do bug <xliff:g id="ID">#%d</xliff:g> capturado, captura pendente"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Adicionando detalhes ao relatório do bug"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Aguarde…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Deslize para a esquerda para compartilhar seu relatório de bugs"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toque para compartilhar seu relatório do bug"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toque para compartilhar seu relatório de bug sem captura de tela ou aguarde a conclusão"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com apps e pessoas nos quais você confia."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Relatórios de bugs"</string> diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml index 43366f812080..9529ade5295a 100644 --- a/packages/Shell/res/values-ro/strings.xml +++ b/packages/Shell/res/values-ro/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Raportul de eroare <xliff:g id="ID">#%d</xliff:g> se generează"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Raportul de eroare <xliff:g id="ID">#%d</xliff:g> a fost creat"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Raport eroare <xliff:g id="ID">#%d</xliff:g> creat, captură ecran în așteptare"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Se adaugă detaliile la raportul de eroare"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Așteptați…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Glisați la stânga pentru a trimite raportul de erori"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Atingeți pentru a trimite raportul de eroare"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Atingeți ca să trimiteți raportul de eroare fără captură de ecran sau așteptați finalizarea acesteia"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Atingeți ca să trimiteți raportul de eroare fără captură de ecran sau așteptați finalizarea acesteia"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Rapoartele despre erori conțin date din diferite fișiere de jurnal ale sistemului, inclusiv informații private și personale. Permiteți accesul la rapoartele despre erori numai aplicațiilor și persoanelor în care aveți încredere."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afișați acest mesaj data viitoare"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Rapoarte de erori"</string> diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml index e22ad2e8e0d5..4aafbba425b9 100644 --- a/packages/Shell/res/values-ru/strings.xml +++ b/packages/Shell/res/values-ru/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Оболочка"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Создание отчета об ошибке <xliff:g id="ID">#%d</xliff:g>…"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Отчет об ошибке <xliff:g id="ID">#%d</xliff:g> сохранен"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Отчет об ошибке (<xliff:g id="ID">#%d</xliff:g>) готов, ожидается скриншот"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Добавление данных в отчет об ошибке"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Подождите…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Проведите влево, чтобы отправить отчет"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Нажмите, чтобы отправить отчет об ошибке."</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Нажмите, чтобы отправить отчет об ошибке сразу, или подождите, пока будет сохранен скриншот."</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Нажмите, чтобы отправить отчет об ошибке сразу, или подождите, пока будет сохранен скриншот."</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Отчеты об ошибках содержат данные различных системных журналов и могут включать личную информацию. Рекомендуем открывать к ним доступ только лицам и приложениям, заслуживающим доверие."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показать это сообщение в следующий раз"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Отчеты об ошибках"</string> diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml index fa1732628867..7a78c433c2d3 100644 --- a/packages/Shell/res/values-sk/strings.xml +++ b/packages/Shell/res/values-sk/strings.xml @@ -19,7 +19,7 @@ <string name="app_label" msgid="3701846017049540910">"Prostredie"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Generuje sa hlásenie chyby <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Hlásenie chyby <xliff:g id="ID">#%d</xliff:g> bolo zaznamenané"</string> - <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Hlásenie chyby <xliff:g id="ID">#%d</xliff:g> bolo zaznamenané, ale čaká sa na snímku obrazovky"</string> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Chyba <xliff:g id="ID">#%d</xliff:g> bola zaznamenaná, čaká sa na snímku obrazovky"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Pridanie podrobností o hlásení chyby"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Čakajte prosím…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Ak chcete hlásenie o chybe zdieľať, prejdite prstom doľava."</string> diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml index 9419760f06f1..fdf34468c060 100644 --- a/packages/Shell/res/values-sl/strings.xml +++ b/packages/Shell/res/values-sl/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Lupina"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Poročilo o napaki <xliff:g id="ID">#%d</xliff:g> je v izdelavi"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Poročilo o napaki <xliff:g id="ID">#%d</xliff:g> zajeto"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Poroč. o napakah <xliff:g id="ID">#%d</xliff:g> zajeto, posnetek zaslona nastaja"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Dodajanje podrobnosti v poročilo o napakah"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Počakajte ..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Povlecite v levo, če želite poslati sporočilo o napaki"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Dotaknite se, če želite poročilo o napaki dati v skupno rabo"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Dotaknite se za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Dotaknite se za pošiljanje poročila o napakah brez posnetka zaslona ali počakajte, da se ta dokonča"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Poročila o napakah vsebujejo podatke iz različnih dnevniških datotek sistema, vključno z osebnimi in zasebnimi podatki. Poročila o napakah delite samo z aplikacijami in ljudmi, ki jim zaupate."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaži to sporočilo naslednjič"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Poročila o napakah"</string> diff --git a/packages/Shell/res/values-sq-rAL/strings.xml b/packages/Shell/res/values-sq-rAL/strings.xml index 206ffda6f773..f43ce9fdab0f 100644 --- a/packages/Shell/res/values-sq-rAL/strings.xml +++ b/packages/Shell/res/values-sq-rAL/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Guaska"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Raporti i defekteve në kod <xliff:g id="ID">#%d</xliff:g> po krijohet"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Raporti i defekteve në kod <xliff:g id="ID">#%d</xliff:g> u regjistrua"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Raporti i defekteve në kod <xliff:g id="ID">#%d</xliff:g> u regjistrua, por pamja e çastit është në pritje"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Po shtohen detajet te raporti i defekteve në kod"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Qëndro në pritje..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Rrëshqit majtas për të ndarë raportin e defektit në kod"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Trokit për të ndarë raportin e defekteve në kod"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Trokit për të ndarë raportin e defekteve në kod pa një pamje çasti ose prit që pamja e çastit të përfundojë"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Trokit për të ndarë raportin e defekteve në kod pa një pamje çasti ose prit që pamja e çastit të përfundojë"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Raportet e gabimeve përmbajnë të dhëna nga skedarë të ndryshëm ditarësh sistemi, përfshi informacione personale dhe private. Shpërndaji publikisht raportet e gabimeve vetëm me aplikacionet dhe personat që iu beson."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tregoje këtë mesazh herën tjetër"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Raportet e gabimeve"</string> diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml index ff9a647e61dd..db7f823230c7 100644 --- a/packages/Shell/res/values-th/strings.xml +++ b/packages/Shell/res/values-th/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"กำลังสร้างรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"บันทึกรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g> แล้ว"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"จับภาพรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g> แล้วแต่ภาพหน้าจอยังไม่เสร็จ"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"กำลังเพิ่มรายละเอียดในรายงานข้อบกพร่อง"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"โปรดรอสักครู่…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"กวาดไปทางซ้ายเพื่อแชร์รายงานข้อบกพร่อง"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณ"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณโดยไม่มีภาพหน้าจอ หรือรอให้ภาพหน้าจอเสร็จสมบูรณ์"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณโดยไม่มีภาพหน้าจอ หรือรอให้ภาพหน้าจอเสร็จสมบูรณ์"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"รายงานข้อบกพร่องมีข้อมูลจากไฟล์บันทึกต่างๆ ของระบบ รวมถึงข้อมูลส่วนตัว แชร์รายงานข้อบกพร่องกับแอปและบุคคลที่คุณไว้ใจเท่านั้น"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"แสดงข้อความนี้ในครั้งต่อไป"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"รายงานข้อบกพร่อง"</string> diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml index 9e152d3d1f70..f99a1b8fcb67 100644 --- a/packages/Shell/res/values-tl/strings.xml +++ b/packages/Shell/res/values-tl/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Binubuo na ang ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Na-capture ang ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Nakunan ang ulat ng bug <xliff:g id="ID">#%d</xliff:g>, nakabinbin ang screenshot"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Pagdaragdag ng mga detalye sa ulat ng bug"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Mangyaring maghintay..."</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Mag-swipe pakaliwa upang ibahagi ang iyong ulat ng bug"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Mag-tap upang ibahagi ang iyong ulat ng bug"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Mag-tap para ibahagi ang iyong ulat ng bug nang walang screenshot o hintaying matapos ang screenshot"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Mag-tap para ibahagi ang iyong ulat ng bug nang walang screenshot o hintaying matapos ang screenshot"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Naglalaman ang mga ulat ng bug ng data mula sa iba\'t ibang file ng log ng system, kabilang ang personal at pribadong impormasyon. Magbahagi lang ng mga ulat ng bug sa apps at mga tao na pinagkakatiwalaan mo."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ipakita ang mensaheng ito sa susunod"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Mga ulat sa bug"</string> diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml index 4c765da922ce..be448afa0fc9 100644 --- a/packages/Shell/res/values-tr/strings.xml +++ b/packages/Shell/res/values-tr/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Kabuk"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) oluşturuluyor"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) yakalandı"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"<xliff:g id="ID">#%d</xliff:g> hata raporu yakalandı, ekran görüntüsü bekleniyor"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Hata raporuna ayrıntılar ekleniyor"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Lütfen bekleyin…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Hata raporunuzu paylaşmak için hızlıca sola kaydırın"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Hata raporunuzu paylaşmak için hafifçe dokunun"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Hata raporunu ekran görüntüsüz paylaşmak için dokunun veya bitirmek için ekran görüntüsünü bekleyin"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Hata raporunu ekran görüntüsüz paylaşmak için dokunun veya bitirmek için ekran görüntüsünü bekleyin"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Hata raporları, kişisel ve özel bilgiler dahil olmak üzere sistemin çeşitli günlük dosyalarından veriler içerir. Hata raporlarını sadece güvendiğiniz uygulamalar ve kişilerle paylaşın."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bir dahaki sefere bu iletiyi göster"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Hata raporları"</string> diff --git a/packages/Shell/res/values-ur-rPK/strings.xml b/packages/Shell/res/values-ur-rPK/strings.xml index edc7433cf350..ef6801fefcb1 100644 --- a/packages/Shell/res/values-ur-rPK/strings.xml +++ b/packages/Shell/res/values-ur-rPK/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"شیل"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> تخلیق ہو رہی ہے"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> کیپچر ہو گئی"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> کیپچر ہو گیا مگر اسکرین شاٹ زیر التواء"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"بگ رپورٹ میں تفصیلات شامل کی جا رہی ہیں"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"براہ کرم انتظار کریں…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"اپنی بگ رپورٹ کا اشتراک کرنے کیلئے بائیں سوائپ کریں"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"اپنی بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"بغیر اسکرین شاٹ کے بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں یا اسکرین شاٹ کے ختم ہونے کا انتظار کریں"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"بغیر اسکرین شاٹ کے بگ رپورٹ کا اشتراک کرنے کیلئے تھپتھپائیں یا اسکرین شاٹ کے ختم ہونے کا انتظار کریں"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"بَگ رپورٹس میں سسٹم کی مختلف لاگ فائلوں سے ڈیٹا شامل ہوتا ہے، بشمول ذاتی اور نجی معلومات۔ بَگ رپورٹس کا اشتراک صرف اپنے بھروسے مند ایپس اور لوگوں کے ساتھ کریں۔"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"یہ پیغام اگلی بار دکھائیں"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"بگ رپورٹس"</string> diff --git a/packages/Shell/res/values-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml index 90d771818483..dd7f41b2dbb6 100644 --- a/packages/Shell/res/values-uz-rUZ/strings.xml +++ b/packages/Shell/res/values-uz-rUZ/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Terminal"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) tayyorlanmoqda"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) yozib olindi"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) tayyor, skrinshot kutilmoqda"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Xatoliklar hisobotiga tafsilotlar qo‘shilmoqda"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Iltimos, kuting…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Xatolik hisobotini yuborish uchun barmog‘ingiz bilan chapga suring"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Xatoliklar hisobotini ulashish uchun bosing"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Xatoliklar hisobotini darhol yuborish uchun shu yerga bosing yoki skrinshot saqlanguncha kuting"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Xatoliklar hisobotini darhol yuborish uchun shu yerga bosing yoki skrinshot saqlanguncha kuting"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Xatolik hisobotlari tizimdagi har xil jurnal fayllardagi ma’lumotlarni, shuningdek, shaxsiy hamda maxfiy ma’lumotlarni o‘z ichiga oladi. Xatolik hisobotlarini faqat ishonchli dasturlar va odamlar bilan bo‘lishing."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ushbu xabar keyingi safar ko‘rsatilsin"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Xatoliklar hisoboti"</string> diff --git a/packages/Shell/res/values-vi/strings.xml b/packages/Shell/res/values-vi/strings.xml index cb8c5b98c7cb..22299916c149 100644 --- a/packages/Shell/res/values-vi/strings.xml +++ b/packages/Shell/res/values-vi/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Báo cáo lỗi <xliff:g id="ID">#%d</xliff:g> đang được tạo"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"Đã chụp báo cáo lỗi <xliff:g id="ID">#%d</xliff:g>"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"Đã chụp báo cáo lỗi <xliff:g id="ID">#%d</xliff:g>, đang chờ ảnh chụp màn hình"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"Đang thêm thông tin chi tiết vào báo cáo lỗi"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"Vui lòng đợi…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Vuốt sang trái để chia sẻ báo cáo lỗi của bạn"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Nhấn để chia sẻ báo cáo lỗi của bạn"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Bấm để chia sẻ báo cáo lỗi mà không cần ảnh chụp màn hình hoặc đợi hoàn tất ảnh chụp màn hình"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Bấm để chia sẻ báo cáo lỗi mà không cần ảnh chụp màn hình hoặc đợi hoàn tất ảnh chụp màn hình"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"Các báo cáo lỗi chứa dữ liệu từ nhiều tệp nhật ký khác nhau của hệ thống, bao gồm cả thông tin cá nhân và riêng tư. Chỉ chia sẻ báo cáo lỗi với các ứng dụng và những người mà bạn tin tưởng."</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Hiển thị thông báo này vào lần tới"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"Báo cáo lỗi"</string> diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml index 6e13d75ab5cb..b09a7d0b783b 100644 --- a/packages/Shell/res/values-zh-rCN/strings.xml +++ b/packages/Shell/res/values-zh-rCN/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"Shell"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在生成错误报告 <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"已捕获错误报告 <xliff:g id="ID">#%d</xliff:g>"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"已捕获错误报告 <xliff:g id="ID">#%d</xliff:g>,但仍在等待屏幕截图完成"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"正在向错误报告添加详细信息"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"请稍候…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑动即可分享错误报告"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"点按即可分享您的错误报告"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"点按即可分享不含屏幕截图的错误报告;您也可以等待屏幕截图完成"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"点按即可分享不含屏幕截图的错误报告;您也可以等待屏幕截图完成"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"错误报告包含的数据来自于系统的各个日志文件,其中包含个人信息和隐私信息。请务必只与您信任的应用和用户分享错误报告。"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再显示这条讯息"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"错误报告"</string> diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml index 7ade56bdd949..384eee70caea 100644 --- a/packages/Shell/res/values-zh-rHK/strings.xml +++ b/packages/Shell/res/values-zh-rHK/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"命令介面"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在產生錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"已擷取錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"已擷取錯誤報告 <xliff:g id="ID">#%d</xliff:g>,但螢幕畫面仍未擷取完成"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"正在新增錯誤報告詳細資訊"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"請稍候…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑動即可分享錯誤報告"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕按即可分享錯誤報告"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕按以分享錯誤報告 (不包含螢幕擷圖),或等待螢幕畫面擷取完成"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕按以分享錯誤報告 (不包含螢幕擷圖),或等待螢幕畫面擷取完成"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告中有來自系統各個記錄檔案的資料,包括個人和私人資料。請只與您信任的應用程式和使用者分享錯誤報告。"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再顯示這則訊息"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string> diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml index 8695d5f3f57b..2702bad05e87 100644 --- a/packages/Shell/res/values-zh-rTW/strings.xml +++ b/packages/Shell/res/values-zh-rTW/strings.xml @@ -19,16 +19,13 @@ <string name="app_label" msgid="3701846017049540910">"殼層"</string> <string name="bugreport_in_progress_title" msgid="4311705936714972757">"正在產生錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string> <string name="bugreport_finished_title" msgid="4429132808670114081">"已擷取錯誤報告 <xliff:g id="ID">#%d</xliff:g>"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_title (5460883450679439591) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_title" msgid="5460883450679439591">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 擷取成功,但螢幕畫面尚未擷取完畢"</string> <string name="bugreport_updating_title" msgid="4423539949559634214">"正在新增錯誤報告詳細資訊"</string> <string name="bugreport_updating_wait" msgid="3322151947853929470">"請稍候…"</string> <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"向左滑動即可分享錯誤報告"</string> <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕按即可分享錯誤報告"</string> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> - <!-- no translation found for bugreport_finished_pending_screenshot_text (1474435374470177193) --> - <skip /> + <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;您也可以等候螢幕畫面擷取完畢"</string> + <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;您也可以等候螢幕畫面擷取完畢"</string> <string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告的資料來自系統各個紀錄檔,包括個人和私密資訊。請務必只與您信任的應用程式和使用者分享錯誤報告。"</string> <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次仍顯示這則訊息"</string> <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string> diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 10c541600d87..7fae0ee6b660 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -454,21 +454,15 @@ public class BugreportProgressService extends Service { final String name = info.name != null ? info.name : mContext.getString(R.string.bugreport_unnamed); - final Notification notification = new Notification.Builder(mContext) - .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) + final Notification notification = newBaseNotification(mContext) .setContentTitle(title) .setTicker(title) .setContentText(name) .setContentInfo(percentText) .setProgress(info.max, info.progress, false) .setOngoing(true) - .setLocalOnly(true) - .setColor(mContext.getColor( - com.android.internal.R.color.system_notification_accent_color)) .setContentIntent(infoPendingIntent) - .addAction(infoAction) - .addAction(screenshotAction) - .addAction(cancelAction) + .setActions(infoAction, screenshotAction, cancelAction) .build(); if (info.finished) { @@ -928,17 +922,13 @@ public class BugreportProgressService extends Service { title = context.getString(R.string.bugreport_finished_title, info.id); content = context.getString(R.string.bugreport_finished_text); } - final Notification.Builder builder = new Notification.Builder(context) - .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) + final Notification.Builder builder = newBaseNotification(context) .setContentTitle(title) .setTicker(title) .setContentText(content) .setContentIntent(PendingIntent.getService(context, info.id, shareIntent, PendingIntent.FLAG_UPDATE_CURRENT)) - .setDeleteIntent(newCancelIntent(context, info)) - .setLocalOnly(true) - .setColor(context.getColor( - com.android.internal.R.color.system_notification_accent_color)); + .setDeleteIntent(newCancelIntent(context, info)); if (!TextUtils.isEmpty(info.name)) { builder.setContentInfo(info.name); @@ -955,16 +945,21 @@ public class BugreportProgressService extends Service { */ private static void sendBugreportBeingUpdatedNotification(Context context, int id) { final String title = context.getString(R.string.bugreport_updating_title); - final Notification.Builder builder = new Notification.Builder(context) - .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) + final Notification.Builder builder = newBaseNotification(context) .setContentTitle(title) .setTicker(title) - .setContentText(context.getString(R.string.bugreport_updating_wait)) + .setContentText(context.getString(R.string.bugreport_updating_wait)); + Log.v(TAG, "Sending 'Updating zip' notification for ID " + id + ": " + title); + NotificationManager.from(context).notify(TAG, id, builder.build()); + } + + private static Notification.Builder newBaseNotification(Context context) { + return new Notification.Builder(context) + .setCategory(Notification.CATEGORY_SYSTEM) + .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb) .setLocalOnly(true) .setColor(context.getColor( com.android.internal.R.color.system_notification_accent_color)); - Log.v(TAG, "Sending 'Updating zip' notification for ID " + id + ": " + title); - NotificationManager.from(context).notify(TAG, id, builder.build()); } /** @@ -1102,7 +1097,14 @@ public class BugreportProgressService extends Service { preferredDomain = "@" + preferredDomain; } - final Account[] accounts = am.getAccounts(); + final Account[] accounts; + try { + accounts = am.getAccounts(); + } catch (RuntimeException e) { + Log.e(TAG, "Could not get accounts for preferred domain " + preferredDomain, e); + return null; + } + if (DEBUG) Log.d(TAG, "Number of accounts: " + accounts.length); Account foundAccount = null; for (Account account : accounts) { if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) { @@ -1281,9 +1283,6 @@ public class BugreportProgressService extends Service { if (hasFocus) { return; } - // Select-all is useful just initially, since the date-based filename is - // full of hyphens. - mInfoName.setSelectAllOnFocus(false); sanitizeName(); } }); diff --git a/packages/Shell/src/com/android/shell/BugreportReceiver.java b/packages/Shell/src/com/android/shell/BugreportReceiver.java index 9afa9005c43b..cbd17bfa3971 100644 --- a/packages/Shell/src/com/android/shell/BugreportReceiver.java +++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java @@ -51,6 +51,7 @@ public class BugreportReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + Log.d(TAG, "onReceive: " + intent); // Clean up older bugreports in background cleanupOldFiles(this, intent, INTENT_BUGREPORT_FINISHED, MIN_KEEP_COUNT, MIN_KEEP_AGE); diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java index 47e3b3b8f8f3..17f6f6b5ac89 100644 --- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java +++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java @@ -291,6 +291,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { detailsUi.assertName(NAME); // Change name - it should have changed system property once focus is changed. + detailsUi.focusOnName(); detailsUi.nameField.setText(NEW_NAME); detailsUi.focusAwayFromName(); assertPropertyValue(NAME_PROPERTY, NEW_NAME); @@ -966,40 +967,44 @@ public class BugreportReceiverTest extends InstrumentationTestCase { cancelButton = mUiBot.getObjectById("android:id/button2"); } - private void assertField(String name, UiObject field, String expected) { - try { - String actual = field.getText().toString(); - assertEquals("Wrong value on field '" + name + "'", expected, actual); - } catch (UiObjectNotFoundException e) { - // Should not happen... - throw new IllegalStateException("field not found: " + name, e); - } + private void assertField(String name, UiObject field, String expected) + throws UiObjectNotFoundException { + String actual = field.getText().toString(); + assertEquals("Wrong value on field '" + name + "'", expected, actual); } - void assertName(String expected) { + void assertName(String expected) throws UiObjectNotFoundException { assertField("name", nameField, expected); } - void assertTitle(String expected) { + void assertTitle(String expected) throws UiObjectNotFoundException { assertField("title", titleField, expected); } - void assertDescription(String expected) { + void assertDescription(String expected) throws UiObjectNotFoundException { assertField("description", descField, expected); } /** + * Set focus on the name field so it can be validated once focus is lost. + */ + void focusOnName() throws UiObjectNotFoundException { + mUiBot.click(nameField, "name_field"); + assertTrue("name_field not focused", nameField.isFocused()); + } + + /** * Takes focus away from the name field so it can be validated. */ - void focusAwayFromName() { + void focusAwayFromName() throws UiObjectNotFoundException { mUiBot.click(titleField, "title_field"); // Change focus. mUiBot.pressBack(); // Dismiss keyboard. + assertFalse("name_field is focused", nameField.isFocused()); } void reOpen() { openProgressNotification(ID); mUiBot.click(detailsButton, "details_button"); - } void clickOk() { diff --git a/packages/SystemUI/res/drawable/recents_empty.xml b/packages/SystemUI/res/drawable/recents_empty.xml new file mode 100644 index 000000000000..5506de1d583f --- /dev/null +++ b/packages/SystemUI/res/drawable/recents_empty.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2014 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="100dp" + android:height="132dp" + android:viewportWidth="100" + android:viewportHeight="132"> + + <path + android:fillColor="#5AFFFFFF" + android:pathData="M86.91,68.67H13.09c-4.96,0-9,4.04-9,9V119c0,4.96,4.04,9,9,9h73.82c4.96,0,9-4.04,9-9V77.67 +C95.91,72.7,91.87,68.67,86.91,68.67z M27.59,77.27h26.72v3.94H27.59V77.27z +M18.73,74.74c2.49,0,4.5,2.01,4.5,4.5 +c0,2.49-2.01,4.5-4.5,4.5s-4.5-2.01-4.5-4.5C14.23,76.75,16.24,74.74,18.73,74.74z +M89.91,119c0,1.65-1.35,3-3,3H13.09 c-1.65,0-3-1.35-3-3V88.67h79.82V119z" /> + <path + android:fillColor="#5AFFFFFF" + android:pathData="M86.91,36.3H13.09c-4.96,0-9,4.04-9,9v23c1.65-1.58,3.71-2.73,6-3.28v-9.08h79.82v9.08 +c2.29,0.55,4.35,1.69,6,3.28v-23C95.91,40.34,91.87,36.3,86.91,36.3z +M18.73,51.38c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5 +s4.5,2.01,4.5,4.5S21.22,51.38,18.73,51.38z M54.31,48.84H27.59v-3.94h26.72V48.84z" /> + <path + android:fillColor="#5AFFFFFF" + android:pathData="M86.91,4H13.09c-4.96,0-9,4.04-9,9v22.94c1.65-1.58,3.71-2.73,6-3.28V24h79.82v8.67 +c2.29,0.55,4.35,1.69,6,3.28V13C95.91,8.04,91.87,4,86.91,4z +M18.73,18.5c-2.49,0-4.5-2.01-4.5-4.5s2.01-4.5,4.5-4.5 +s4.5,2.01,4.5,4.5S21.22,18.5,18.73,18.5z M54.31,15.97H27.59v-3.94h26.72V15.97z" /> + <path + android:pathData="M 0 0 H 100 V 132 H 0 V 0 Z" /> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml index df46271b5d64..c062b6d671a5 100644 --- a/packages/SystemUI/res/layout/qs_detail_header.xml +++ b/packages/SystemUI/res/layout/qs_detail_header.xml @@ -30,6 +30,7 @@ android:padding="16dp" android:clickable="true" android:background="?android:attr/selectableItemBackground" + android:contentDescription="@*android:string/action_bar_up_description" android:src="?android:attr/homeAsUpIndicator" /> <TextView diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml index b2c03312c9d1..53d9cc53161d 100644 --- a/packages/SystemUI/res/layout/recents_empty.xml +++ b/packages/SystemUI/res/layout/recents_empty.xml @@ -16,10 +16,12 @@ <TextView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" + android:layout_width="wrap_content" + android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" + android:drawableTop="@drawable/recents_empty" + android:drawablePadding="25dp" android:textSize="16sp" android:textColor="#ffffffff" android:text="@string/recents_empty_message" diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml index 3a7c1d10e642..567e009d07ee 100644 --- a/packages/SystemUI/res/layout/recents_on_tv.xml +++ b/packages/SystemUI/res/layout/recents_on_tv.xml @@ -18,7 +18,6 @@ android:id="@+id/recents_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@drawable/recents_tv_background_gradient" android:clipChildren="false" android:clipToPadding="false" android:layoutDirection="rtl"> diff --git a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml index c5b1a7a51782..54e97da1471e 100644 --- a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml +++ b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml @@ -59,7 +59,7 @@ <ImageView android:id="@+id/card_view_thumbnail" android:layout_width="match_parent" - android:layout_height="@dimen/recents_tv_card_height" + android:layout_height="@dimen/recents_tv_screenshot_height" android:scaleType="centerCrop" android:gravity="center" android:layout_alignParentTop="true" diff --git a/packages/SystemUI/res/layout/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml index f031bb466bd7..b0814cfd1d69 100644 --- a/packages/SystemUI/res/layout/tv_pip_onboarding.xml +++ b/packages/SystemUI/res/layout/tv_pip_onboarding.xml @@ -37,10 +37,13 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" + android:paddingStart="24dp" + android:paddingEnd="24dp" android:fontFamily="sans-serif" android:textSize="16sp" android:textColor="#EEEEEE" android:lineSpacingMultiplier="1.28" + android:gravity="top|center_horizontal" android:text="@string/pip_onboarding_description" /> <Button android:id="@+id/close" diff --git a/packages/SystemUI/res/layout/tv_pip_overlay.xml b/packages/SystemUI/res/layout/tv_pip_overlay.xml index 40c6fa18816b..1ba423bb22cf 100644 --- a/packages/SystemUI/res/layout/tv_pip_overlay.xml +++ b/packages/SystemUI/res/layout/tv_pip_overlay.xml @@ -24,13 +24,19 @@ <TextView android:id="@+id/guide_overlay" android:layout_width="match_parent" - android:layout_height="32dp" + android:layout_height="wrap_content" android:layout_alignParentBottom="true" + android:paddingTop="6dp" + android:paddingBottom="6dp" + android:paddingStart="10dp" + android:paddingEnd="10dp" android:textSize="14sp" android:textColor="#EEEEEE" android:fontFamily="sans-serif" android:background="@drawable/tv_pip_overlay_background" + android:lineSpacingMultiplier="1.465" android:gravity="center" + android:maxLines="2" android:text="@string/pip_hold_home" /> <LinearLayout android:id="@+id/guide_buttons" diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 70247eec090e..090b8e6fcb3f 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Skermkiekie geneem."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Raak om jou skermkiekie te sien."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Kon nie skermkiekie neem nie."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Kon nie skermkiekie stoor nie."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB-lêeroordrag-opsies"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Werkmodus is aan."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Werkmodus is afgeskakel."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Werkmodus is aangeskakel."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Databespaarder is afgeskakel."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Databespaarder is aangeskakel."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Skermhelderheid"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G-data is laat wag"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data is laat wag"</string> diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml index adc1306b0af6..f595479c6059 100644 --- a/packages/SystemUI/res/values-af/strings_tv.xml +++ b/packages/SystemUI/res/values-af/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Speel"</string> <string name="pip_pause" msgid="8412075640017218862">"Laat wag"</string> <string name="pip_hold_home" msgid="340086535668778109">"Hou "<b>"TUIS"</b>" om PIP te beheer"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Druk en hou die TUIS-\nknoppie om PIP te beheer"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Druk en hou die TUIS-knoppie om PIP te beheer"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Het dit"</string> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 226d7f505424..e870ea7315c0 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"ቅጽበታዊ ገጽ እይታ ተቀርጿል"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት ይንኩ"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"ቅጽበታዊ ገጽ እይታ መቅረጽ አልተቻለም::"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ቅጽበታዊ ገጽ ዕይታን በማስቀመጥ ጊዜ ችግር አጋጥሟል።"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ባለው የተገደበ የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም።"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም።"</string> <string name="usb_preference_title" msgid="6551050377388882787">"የUSB ፋይል ሰደዳ አማራጮች"</string> diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml index a6b9660bab9e..95e480c3301a 100644 --- a/packages/SystemUI/res/values-am/strings_tv.xml +++ b/packages/SystemUI/res/values-am/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIPን ዝጋ"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"ሙሉ ማያ ገጽ"</string> <string name="pip_play" msgid="674145557658227044">"አጫውት"</string> <string name="pip_pause" msgid="8412075640017218862">"ለአፍታ አቁም"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"PIPን ለመቆጣጠር "<b>"መነሻ"</b>"ን ይያዙ"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIPን ለመቆጣጠር የመነሻ አዝራሩን ተጭነው ይያዙ"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"ገባኝ"</string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 5dc3b01fe7d6..4a4e004fa3cc 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -77,6 +77,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"تم التقاط لقطة الشاشة."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"المس لعرض لقطة الشاشة."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"تعذر التقاط لقطة الشاشة."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"حدثت مشكلة أثناء حفظ لقطة الشاشة."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"يتعذر حفظ لقطة الشاشة نظرًا لأن مساحة التخزين المتاحة محدودة."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"غير مسموح بالتقاط لقطات شاشة نظرًا لإذن يتعلق بالتطبيق أو بالمؤسسة."</string> <string name="usb_preference_title" msgid="6551050377388882787">"خيارات نقل الملفات عبر USB"</string> @@ -224,10 +225,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"وضع العمل قيد التشغيل."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"تم تعطيل وضع العمل."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"تم تشغيل وضع العمل."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"تم تعطيل توفير البيانات."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"تم تشغيل توفير البيانات."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"سطوع الشاشة"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"بيانات شبكات الجيل الثاني والثالث متوقفة مؤقتًا"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"تم إيقاف بيانات شبكة الجيل الرابع مؤقتًا"</string> diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml index 99c413cf6bf8..a54e0ab86aa3 100644 --- a/packages/SystemUI/res/values-ar/strings_tv.xml +++ b/packages/SystemUI/res/values-ar/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"تشغيل"</string> <string name="pip_pause" msgid="8412075640017218862">"إيقاف مؤقت"</string> <string name="pip_hold_home" msgid="340086535668778109">"اضغط "<b>"الرئيسية"</b>" للتحكم في PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"اضغط مع الاستمرار على زر الرئيسية\nللتحكم في PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"اضغط مع الاستمرار على زر الشاشة الرئيسية للتحكم في PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"حسنًا"</string> </resources> diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml index 21bdc4590bf1..7763cb3588c6 100644 --- a/packages/SystemUI/res/values-az-rAZ/strings.xml +++ b/packages/SystemUI/res/values-az-rAZ/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinşot çəkildi."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Skrinşotunuza baxmaq üçün toxunun"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinşot götürülə bilinmədi."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Skrinşot yadda saxlanarkən problem baş verdi."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Tətbiq və ya təşkilatınız tərəfindən skrinşot çəkməyə icazə verilmir."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl transferi seçimləri"</string> diff --git a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml index e4e35ab21f71..b3ac6d403ea0 100644 --- a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml +++ b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP bağlayın"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string> <string name="pip_play" msgid="674145557658227044">"Göstərin"</string> <string name="pip_pause" msgid="8412075640017218862">"Fasilə verin"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"PIP idarı etmək üçün "<b>"Əsas səhifəni"</b>" tutub saxlayın"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PİP nəzarət etmək üçün ƏSAS EKRAN düyməni basıb saxlayın"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Anladım"</string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 969b3783e02f..fff464df8a03 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -74,6 +74,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Snimak ekrana je napravljen."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite da biste videli snimak ekrana."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Nije moguće napraviti snimak ekrana."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Došlo je do problema pri čuvanju snimka ekrana."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prenosa datoteka"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml index 39a858cfc50a..d78f8d33ea30 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Pusti"</string> <string name="pip_pause" msgid="8412075640017218862">"Pauziraj"</string> <string name="pip_hold_home" msgid="340086535668778109"><b>"POČETNI EKRAN"</b>" kont. PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Pritisnite i zadržite dugme POČETNI EKRAN\n da biste kontrolisali PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Pritisnite i zadržite dugme POČETNI EKRAN da biste kontrolisali PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Važi"</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 9ff5f951d596..876af0af7d23 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Екранната снимка е заснета."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Докоснете, за да видите екранната си снимка."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Екранната снимка не можа да бъде заснета."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"При запазването на екранната снимка възникна проблем."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Екранната снимка не може да се запази поради ограничено място в хранилището."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Правенето на екранни снимки не е разрешено от приложението или организацията ви."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Опции за пренос на файлове чрез USB"</string> diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml index c5fc5b1c95bc..c5230a48749a 100644 --- a/packages/SystemUI/res/values-bg/strings_tv.xml +++ b/packages/SystemUI/res/values-bg/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Затваряне на PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Цял екран"</string> <string name="pip_play" msgid="674145557658227044">"Пускане"</string> <string name="pip_pause" msgid="8412075640017218862">"Пауза"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Контр. на PIP: Задр. "<b>"HOME"</b></string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"За контролиране на PIP натиснете и задръжте бутона „HOME“"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Разбрах"</string> </resources> diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml index 66537da17104..eaf450fa3d8d 100644 --- a/packages/SystemUI/res/values-bn-rBD/strings.xml +++ b/packages/SystemUI/res/values-bn-rBD/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"স্ক্রীনশট নেওয়া হযেছে৷"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"আপনার স্ক্রীনশট দেখতে স্পর্শ করুন৷"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"স্ক্রীনশট নেওয়া যায়নি৷"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"স্ক্রীনশট সংরক্ষণের সময়ে সমস্যা হয়েছে৷"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"সঞ্চয়স্থান সীমিত থাকায় স্ক্রীনশটটি সংরক্ষণ করা যাবে না৷"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"অ্যাপ্লিকেশান বা আপনার প্রতিষ্ঠান স্ক্রীনশটগুলি নেওয়া অনুমতি দেয়নি৷"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string> diff --git a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml index 7a958155d505..6bb19f5a87b1 100644 --- a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml +++ b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"চালান"</string> <string name="pip_pause" msgid="8412075640017218862">"বিরাম দিন"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP নিয়ন্ত্রণ করতে "<b>"হোম"</b>" কী ধরে রাখুন"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP নিয়ন্ত্রণ করতে হোম\nবোতামটি টিপে ধরে রাখুন"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP নিয়ন্ত্রণ করতে HOME বোতামটিকে টিপুন ও ধরে থাকুন"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"বুঝেছি"</string> </resources> diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml index 91d9dead2c5f..0b72a066812f 100644 --- a/packages/SystemUI/res/values-bs-rBA/strings.xml +++ b/packages/SystemUI/res/values-bs-rBA/strings.xml @@ -74,6 +74,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran snimljen."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite za prikaz snimka ekrana."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Došlo je do greške prilikom snimanja ekrana."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Došlo je do problema prilikom spašavanja snimka ekrana."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ili vaša organizacija ne dopuštaju pravljenje snimaka ekrana."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa fajlova"</string> diff --git a/packages/SystemUI/res/values-bs-rBA/strings_tv.xml b/packages/SystemUI/res/values-bs-rBA/strings_tv.xml new file mode 100644 index 000000000000..dd4a518f6db3 --- /dev/null +++ b/packages/SystemUI/res/values-bs-rBA/strings_tv.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright (c) 2016, 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 xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <string name="pip_close" msgid="3480680679023423574">"Zatvori PIP"</string> + <!-- no translation found for pip_fullscreen (8604643018538487816) --> + <skip /> + <!-- no translation found for pip_play (674145557658227044) --> + <skip /> + <!-- no translation found for pip_pause (8412075640017218862) --> + <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Za kontr. PIP držite "<b>"HOME"</b></string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Za kontrolu PIP, pritisnite i držite dugme POČETAK"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Jasno mi je"</string> +</resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index a75879834197..6ddec67e88d8 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"S\'ha fet una captura de pantalla."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca per veure la captura de pantalla."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"No s\'ha pogut fer una captura de pantalla."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"S\'ha trobat un problema en desar la captura de pantalla."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'aplicació o l\'organització no permeten fer captures de pantalla."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string> diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml index c5779ae6807e..3634b994c105 100644 --- a/packages/SystemUI/res/values-ca/strings_tv.xml +++ b/packages/SystemUI/res/values-ca/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Tanca PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string> <string name="pip_play" msgid="674145557658227044">"Reprodueix"</string> <string name="pip_pause" msgid="8412075640017218862">"Posa en pausa"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Prem "<b>"INICI"</b>" per controlar PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén premut el botó INICI per controlar PIP"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"D\'acord"</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 86353a6a679a..e23f53fa39d7 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -75,6 +75,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímek obrazovky Snímek obrazovky pořízen."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Snímek obrazovky zobrazíte dotykem."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Snímek obrazovky se nepodařilo zachytit."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Při ukládání snímku obrazovky došlo k problému."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímek obrazovky nelze pořídit kvůli nedostatku místa v úložišti."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti přenosu souborů pomocí rozhraní USB"</string> @@ -222,10 +223,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Pracovní režim zapnutý"</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Pracovní režim je vypnutý."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Pracovní režim je zapnutý."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Spořič dat byl vypnut."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Spořič dat byl zapnut."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Jas displeje"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G a 3G jsou pozastavena"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G jsou pozastavena"</string> diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml index 89640cdab1cf..b65b08e2254f 100644 --- a/packages/SystemUI/res/values-cs/strings_tv.xml +++ b/packages/SystemUI/res/values-cs/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Ukončit PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Celá obrazovka"</string> <string name="pip_play" msgid="674145557658227044">"Přehrát"</string> <string name="pip_pause" msgid="8412075640017218862">"Pozastavit"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Funkci PIP lze ovládat podržením tlačítka "<b>"PLOCHA"</b></string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Funkci PIP lze ovládat podržením tlačítka PLOCHA"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Rozumím"</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 55fefc236d46..ba8898e5c64b 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Skærmbilledet er gemt."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Tryk for at se dit skærmbillede."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Skærmbilledet kunne ikke tages."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Der opstod et problem ved lagringen af skærmbilledet."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Skærmbilledet kan ikke gemmes pga. begrænset lagerplads."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller din organisation tillader ikke, at du tager skærmbilleder."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Muligheder for USB-filoverførsel"</string> diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml index 10a1ecd8a4b3..b51c5df95375 100644 --- a/packages/SystemUI/res/values-da/strings_tv.xml +++ b/packages/SystemUI/res/values-da/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Afspil"</string> <string name="pip_pause" msgid="8412075640017218862">"Pause"</string> <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" nede for at styre PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Tryk på knappen HOME,\nog hold den nede for at styre PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Tryk på HOME-knappen, og hold den nede for at styre PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index cb8e0fd0feaa..345dbeddf95f 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot aufgenommen"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Zum Ansehen berühren"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot konnte nicht aufgenommen werden."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Beim Speichern des Screenshots ist ein Problem aufgetreten."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Die App oder Ihr Unternehmen lässt das Erstellen von Screenshots nicht zu."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string> diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml index aa1a9b20de42..b96669b1c7c0 100644 --- a/packages/SystemUI/res/values-de/strings_tv.xml +++ b/packages/SystemUI/res/values-de/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Wiedergeben"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausieren"</string> <string name="pip_hold_home" msgid="340086535668778109"><b>"STARTBILDSCHIRMTASTE"</b>" drücken, um PIP zu steuern"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"STARTBILDSCHIRMTASTE\n gedrückt halten, um PIP zu steuern"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Halte die Taste für die Startseite gedrückt, um das Bild-in-Bild zu steuern"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index b1df6154f434..78cbb20dc113 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Λήφθηκε το στιγμιότυπο οθόνης ."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Αγγίξτε για να δείτε το στιγμιότυπο οθόνης σας"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Παρουσιάστηκε πρόβλημα κατά την αποθήκευση του στιγμιότυπου οθόνης."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Δεν είναι δυνατή η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου χώρου αποθήκευσης."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Η λήψη στιγμιοτύπων οθόνης δεν επιτρέπεται από την εφαρμογή ή από τον οργανισμό σας."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Επιλογές μεταφοράς αρχείων μέσω USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Η λειτουργία εργασίας είναι ενεργή."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Η λειτουργία εργασίας απενεργοποιήθηκε."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Η λειτουργία εργασίας ενεργοποιήθηκε."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Η Εξοικονόμηση δεδομένων είναι ανενεργή."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Η Εξοικονόμηση δεδομένων είναι ενεργή."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Φωτεινότητα οθόνης"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Τα δεδομένα 2G-3G τέθηκαν σε παύση"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Τα δεδομένα 4G τέθηκαν σε παύση"</string> diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml index c96f852d1ab7..e72d579acdc8 100644 --- a/packages/SystemUI/res/values-el/strings_tv.xml +++ b/packages/SystemUI/res/values-el/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Αναπαραγωγή"</string> <string name="pip_pause" msgid="8412075640017218862">"Παύση"</string> <string name="pip_hold_home" msgid="340086535668778109">"Κρατήστε το πλήκτρο "<b>"HOME"</b>" πατημένο για έλεγχο του PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Πατήστε παρατεταμένα το κουμπί HOME\nγια έλεγχο του PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Πιέστε παρατεταμένα το κουμπί HOME, για να ελέγξετε τη λειτουργία PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Κατάλαβα"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 72c71a876cca..6367ed9900d7 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver turned off."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver turned on."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml index 6f3365569ab3..5711c352aa1a 100644 --- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Play"</string> <string name="pip_pause" msgid="8412075640017218862">"Pause"</string> <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Press and hold the HOME\nbutton to control PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 72c71a876cca..6367ed9900d7 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver turned off."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver turned on."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml index 6f3365569ab3..5711c352aa1a 100644 --- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Play"</string> <string name="pip_pause" msgid="8412075640017218862">"Pause"</string> <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Press and hold the HOME\nbutton to control PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 72c71a876cca..6367ed9900d7 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problem encountered while saving screenshot."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Can\'t save screenshot due to limited storage space."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Taking screenshots is not allowed by the app or your organisation."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work mode on."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work mode turned off."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work mode turned on."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver turned off."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver turned on."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Display brightness"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G data is paused"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data is paused"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml index 6f3365569ab3..5711c352aa1a 100644 --- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Play"</string> <string name="pip_pause" msgid="8412075640017218862">"Pause"</string> <string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Press and hold the HOME\nbutton to control PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 34e5a7eb2a0c..4769e20df73e 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Se guardó la captura de pantalla."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver tu captura de pantalla."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"No se pudo guardar la captura de pantalla."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Se produjo un error al guardar la captura de pantalla."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla debido al almacenamiento limitado."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"La app o tu organización no permiten las capturas de pantalla."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml index 16d9f364dc8d..99913e644cf8 100644 --- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml +++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Cerrar PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string> <string name="pip_play" msgid="674145557658227044">"Reproducir"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Mantén presionado "<b>"INICIO"</b>" para controlar PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén presionado el botón INICIO para controlar PIP"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 2698ffc45774..e89125e2a21a 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura guardada"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver la captura de pantalla"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"No se ha podido guardar la captura de pantalla."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Se ha detectado un problema al guardar la captura de pantalla."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"La aplicación o tu organización no permiten que se realicen capturas de pantalla."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string> diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml index fcc839e7421b..200410cee2c8 100644 --- a/packages/SystemUI/res/values-es/strings_tv.xml +++ b/packages/SystemUI/res/values-es/strings_tv.xml @@ -23,7 +23,7 @@ <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string> <string name="pip_play" msgid="674145557658227044">"Reproducir"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string> - <string name="pip_hold_home" msgid="340086535668778109"><b>"INICIO"</b>" pulsado: control PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"INICIO pulsado:\ncontrol PIP"</string> + <string name="pip_hold_home" msgid="340086535668778109">"Mantén el botón "<b>"INICIO"</b>" pulsado para control de PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén el botón de INICIO pulsado para controlar el modo PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string> </resources> diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml index 42d449aa03ac..cad44d9b6d90 100644 --- a/packages/SystemUI/res/values-et-rEE/strings.xml +++ b/packages/SystemUI/res/values-et-rEE/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekraanipilt on jäädvustatud."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Puudutage kuvatõmmise vaatamiseks."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Kuvatõmmist ei saanud jäädvustada."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Ekraanipildi salvestamisel ilmnes probleem."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB-failiedastuse valikud"</string> diff --git a/packages/SystemUI/res/values-et-rEE/strings_tv.xml b/packages/SystemUI/res/values-et-rEE/strings_tv.xml index ae6cb30bf8b3..972083b4a100 100644 --- a/packages/SystemUI/res/values-et-rEE/strings_tv.xml +++ b/packages/SystemUI/res/values-et-rEE/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Esita"</string> <string name="pip_pause" msgid="8412075640017218862">"Peata"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP juht. hoidke all nuppu "<b>"AVAEKRAAN"</b></string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP juhtim. vajutage\npikalt nuppu AVAEKRAAN"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP juhtimiseks vajutage pikalt nuppu AVAEKRAAN"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Selge"</string> </resources> diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml index 67f13cc1ea92..1dc6d687de4d 100644 --- a/packages/SystemUI/res/values-eu-rES/strings.xml +++ b/packages/SystemUI/res/values-eu-rES/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Pantaila-argazkia atera da."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Pantaila-argazkia ikusteko, ukitu ezazu."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Ezin izan da pantaila-argazkia atera."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Arazo bat izan da pantaila-argazkia gordetzean."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ezin da atera pantaila-argazkia ez delako tokirik geratzen."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB fitxategiak transferitzeko aukerak"</string> diff --git a/packages/SystemUI/res/values-eu-rES/strings_tv.xml b/packages/SystemUI/res/values-eu-rES/strings_tv.xml index e6bbd32ef8c5..a312ea48bd4a 100644 --- a/packages/SystemUI/res/values-eu-rES/strings_tv.xml +++ b/packages/SystemUI/res/values-eu-rES/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Itxi PIPa"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Pantaila osoa"</string> <string name="pip_play" msgid="674145557658227044">"Erreproduzitu"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausatu"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109"><b>"HASIERA"</b>" PIP kontrolatzeko"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Eduki sakatuta hasierako botoia pantaila txikia kontrolatzeko"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Ados"</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 13c9132e2506..dfe1d544f9b5 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"عکس صفحهنمایش گرفته شد."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"برای مشاهده عکس صفحهنمایشتان، لمس کنید."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"عکس صفحهنمایش گرفته نشد."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"هنگام ذخیره عکس صفحهنمایش مشکلی رخ داد."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"به دلیل محدود بودن فضای ذخیرهسازی نمیتوانید عکس صفحهنمایش را ذخیره کنید."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"این برنامه یا سازمان شما اجازه نمیدهند عکس صفحهنمایش بگیرید."</string> <string name="usb_preference_title" msgid="6551050377388882787">"گزینههای انتقال فایل USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"حالت کار روشن."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"حالت کار خاموش شد."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"حالت کار روشن شد."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"صرفهجویی داده خاموش شد."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"صرفهجویی داده روشن شد."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"روشنایی نمایشگر"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"داده 2G-3G موقتاً متوقف شده است"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"داده 4G موقتاً متوقف شده است"</string> @@ -510,9 +509,9 @@ <string name="headset" msgid="4534219457597457353">"هدست"</string> <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"هدفون وصل شد"</string> <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"هدست وصل شد"</string> - <string name="data_saver" msgid="5037565123367048522">"صرفهجویی در مصرف داده"</string> - <string name="accessibility_data_saver_on" msgid="8454111686783887148">"صرفهجویی در مصرف داده روشن است"</string> - <string name="accessibility_data_saver_off" msgid="8841582529453005337">"صرفهجویی در مصرف داده خاموش است"</string> + <string name="data_saver" msgid="5037565123367048522">"صرفهجویی داده"</string> + <string name="accessibility_data_saver_on" msgid="8454111686783887148">"صرفهجویی داده روشن است"</string> + <string name="accessibility_data_saver_off" msgid="8841582529453005337">"صرفهجویی داده خاموش است"</string> <string name="switch_bar_on" msgid="1142437840752794229">"روشن"</string> <string name="switch_bar_off" msgid="8803270596930432874">"خاموش"</string> <string name="nav_bar" msgid="1993221402773877607">"نوار پیمایش"</string> diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml index 6a62f1251fe8..cf37db108277 100644 --- a/packages/SystemUI/res/values-fa/strings_tv.xml +++ b/packages/SystemUI/res/values-fa/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"بستن PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"تمام صفحه"</string> <string name="pip_play" msgid="674145557658227044">"پخش"</string> <string name="pip_pause" msgid="8412075640017218862">"مکث"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"کنترل PIP با نگهداشتن "<b>"HOME"</b></string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"برای کنترل PIP دکمه صفحه اصلی را فشار داده و نگهدارید"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"متوجه شدم"</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index e5ddaad90763..e5d513fabae5 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Kuvakaappaus tallennettu"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Katso kuvakaappaus koskettamalla."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Kuvakaappausta ei voitu tallentaa"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Kuvakaappausta tallennettaessa tapahtui virhe."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kuvakaappauksen tallentaminen epäonnistui, sillä tallennustilaa ei ole riittävästi."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Sovellus tai organisaatiosi ei salli kuvakaappauksien tallentamista."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Työtila on käytössä."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Työtila poistettiin käytöstä."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Työtila otettiin käyttöön."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver poistettiin käytöstä."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver otettiin käyttöön."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Näytön kirkkaus"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G–3G-tiedonsiirto keskeytettiin"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-tiedonsiirto keskeytettiin"</string> diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml index c19894f74f26..94c780628ad9 100644 --- a/packages/SystemUI/res/values-fi/strings_tv.xml +++ b/packages/SystemUI/res/values-fi/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Sulje PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Koko näyttö"</string> <string name="pip_play" msgid="674145557658227044">"Toista"</string> <string name="pip_pause" msgid="8412075640017218862">"Keskeytä"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"PIP: paina pitkään "<b>"aloituspain"</b>"."</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Hallinnoi PIP-tilaa painamalla ALOITUSNÄYTTÖ-painiketta pitkään."</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Selvä"</string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 8ad463b674a1..223274f555c1 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Une erreur s\'est produite lors de l\'enregistrement de la saisie d\'écran."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la saisie d\'écran, car l\'espace de stockage est limité."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml index 9165632e69d0..48bbb269b3ba 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Fermer mode IDI"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string> <string name="pip_play" msgid="674145557658227044">"Lecture"</string> <string name="pip_pause" msgid="8412075640017218862">"Interrompre"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"Maint. enf. "<b>"ACC."</b>" pr gér. mode IDI"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index b520a883f76c..474a24055ace 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Erreur lors de l\'enregistrement de la capture d\'écran."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Les captures d\'écran ne sont pas autorisées par l\'application ou par votre organisation."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string> diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml index bc4bd22cc97b..27c62fb50c41 100644 --- a/packages/SystemUI/res/values-fr/strings_tv.xml +++ b/packages/SystemUI/res/values-fr/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Fermer mode PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string> <string name="pip_play" msgid="674145557658227044">"Lire"</string> <string name="pip_pause" msgid="8412075640017218862">"Suspendre"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Appui long "<b>"ACCUEIL"</b>" pour contrôler PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Appuyez de manière prolongée sur le bouton ACCUEIL pour contrôler le mode PIP."</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml index 1dc47d5aa4e4..a675c217166d 100644 --- a/packages/SystemUI/res/values-gl-rES/strings.xml +++ b/packages/SystemUI/res/values-gl-rES/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de pantalla gardada."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Toca para ver a captura de pantalla."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Non se puido facer a captura de pantalla."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Produciuse un problema ao gardar a captura de pantalla."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Non se pode gardar a captura de pantalla porque o espazo de almacenamento é limitado."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"A aplicación ou a túa organización non permite realizar capturas de pantalla."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opcións de transferencia USB"</string> diff --git a/packages/SystemUI/res/values-gl-rES/strings_tv.xml b/packages/SystemUI/res/values-gl-rES/strings_tv.xml index 6aab613923a5..b0343e16ebdb 100644 --- a/packages/SystemUI/res/values-gl-rES/strings_tv.xml +++ b/packages/SystemUI/res/values-gl-rES/strings_tv.xml @@ -23,7 +23,7 @@ <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string> <string name="pip_play" msgid="674145557658227044">"Reproducir"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string> - <string name="pip_hold_home" msgid="340086535668778109">"Premido "<b>"INICIO"</b>" para PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Premido INICIO\npara PIP"</string> + <string name="pip_hold_home" msgid="340086535668778109">"Manter premido "<b>"INICIO"</b>" para controlar PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén premido o botón de INICIO para controlar PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"De acordo"</string> </resources> diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml index 57a95cd30c5d..a8394a2e25ee 100644 --- a/packages/SystemUI/res/values-gu-rIN/strings.xml +++ b/packages/SystemUI/res/values-gu-rIN/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"સ્ક્રીનશોટ કેપ્ચર કર્યો."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"તમારો સ્ક્રીનશોટ જોવા માટે ટચ કરો."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"સ્ક્રીનશોટ કેપ્ચર કરી શકાયો નથી."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"સ્ક્રીનશૉટ સાચવવામાં સમયા આવી."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"મર્યાદિત સંગ્રહ સ્થાનને કારણે સ્ક્રીનશોટ સાચવી શકાતો નથી."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશોટ્સ લેવાની મંજૂરી નથી."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ફાઇલ ટ્રાન્સફર વિકલ્પો"</string> diff --git a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml index 56f0298d4ee3..3f2f68a93520 100644 --- a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"ચલાવો"</string> <string name="pip_pause" msgid="8412075640017218862">"થોભાવો"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP નિયંત્રિત કરવા માટે "<b>"હોમ"</b>" પકડી રાખો"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP નિયંત્રિત કરવા માટે હોમ\n બટન દબાવો અને પકડી રાખો"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP નિયંત્રિત કરવા માટે હોમ બટન દબાવો અને પકડી રાખો"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"સમજાઈ ગયું"</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 0c3cb482f15e..43331fd09160 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रीनशॉट कैप्चर किया गया."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"अपना स्क्रीनशॉट देखने के लिए स्पर्श करें."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट को कैप्चर नहीं किया जा सका."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रीनशॉट सहेजते समय समस्या आई"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित मेमोरी स्थान के कारण स्क्रीनशॉट सहेजा नहीं जा सकता."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"आपके ऐप्लिकेशन या आपके संगठन द्वारा स्क्रीनशॉट लेने की अनुमति नहीं है."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB फ़ाइल स्थानांतरण विकल्प"</string> diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml index c4bb26baa418..cf259ddc9012 100644 --- a/packages/SystemUI/res/values-hi/strings_tv.xml +++ b/packages/SystemUI/res/values-hi/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"चलाएं"</string> <string name="pip_pause" msgid="8412075640017218862">"रोकें"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP नियंत्रण हेतु "<b>"HOME"</b>" होल्ड करें"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP नियंत्रण हेतु HOME\nबटन दबाए रखें"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP नियंत्रण के लिए HOME बटन को दबाए रखें"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"समझ लिया"</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 81f10a2ed995..715f667ecd83 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -74,6 +74,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Zaslon je snimljen."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Dodirnite za prikaz snimke zaslona."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Nije bilo moguće snimiti zaslon."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Prilikom spremanja snimke zaslona pojavio se problem."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Zaslon nije snimljen zbog ograničenog prostora za pohranu."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Snimanje zaslona ne dopušta aplikacija ili vaša organizacija."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa datoteka"</string> diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml index 2a72055867b3..424c68b06ce5 100644 --- a/packages/SystemUI/res/values-hr/strings_tv.xml +++ b/packages/SystemUI/res/values-hr/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Reproduciraj"</string> <string name="pip_pause" msgid="8412075640017218862">"Pauziraj"</string> <string name="pip_hold_home" msgid="340086535668778109">"Držite "<b>"POČETNI"</b>" za PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Pritisnite i držite POČETNI\nza upravljanje PIP-om"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Pritisnite i zadržite tipku POČETNI ZASLON da biste upravljali slikom u slici"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Shvaćam"</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index ccf582b44d68..280cdb6248f6 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Képernyőkép rögzítve."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Megérintésével megtekintheti a képernyőképet."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Nem sikerült rögzíteni a képernyőképet."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Hiba történt a képernyőkép mentése során."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nem menthet képernyőképet, mert kevés a tárhely."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Az alkalmazás vagy szervezete nem engedélyezi képernyőképek készítését."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB-fájlátvitel beállításai"</string> diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml index ff4d37cea08a..5271a4a24102 100644 --- a/packages/SystemUI/res/values-hu/strings_tv.xml +++ b/packages/SystemUI/res/values-hu/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Lejátszás"</string> <string name="pip_pause" msgid="8412075640017218862">"Szüneteltetés"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP vezérlése a "<b>"HOME"</b>"-mal"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"A PIP vezérléséhez\ntartsa nyomva a HOME-ot"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"A PIP vezérléséhez tartsa nyomva a HOME gombot"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Rendben"</string> </resources> diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml index e60ce28d20f6..6338d8e5abf8 100644 --- a/packages/SystemUI/res/values-hy-rAM/strings.xml +++ b/packages/SystemUI/res/values-hy-rAM/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի հանույթը լուսանկարվել է:"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Հպեք ձեր էկրանի հանույթը տեսնելու համար:"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի հանույթը:"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Էկրանի պատկերը պահելիս խնդիր առաջացավ:"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Չհաջողվեց պահել էկրանի պատկերը սահմանափակ հիշողության պատճառով:"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Այս հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում Էկրանի պատկերի ստացումը:"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ֆայլերի փոխանցման ընտրանքներ"</string> diff --git a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml index 2eed586e62f7..280d733afd80 100644 --- a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml +++ b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Փակել PIP-ն"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Լիէկրան"</string> <string name="pip_play" msgid="674145557658227044">"Նվագարկել"</string> <string name="pip_pause" msgid="8412075640017218862">"Դադարեցնել"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"PIP-ն կառավարելու համար սեղմած պահեք "<b>"HOME"</b>" կոճակը"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP-ն կառավարելու համար սեղմեք և պահեք HOME կոճակը"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Պարզ է"</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 9eb133116b35..77236634c139 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan layar diambil."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan layar Anda."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat mengambil tangkapan layar."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Terjadi masalah saat menyimpan tangkapan layar."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan layar karena ruang penyimpanan terbatas."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Mengambil tangkapan layar tidak diizinkan oleh aplikasi atau organisasi."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer file USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mode kerja aktif."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Mode kerja dinonaktifkan."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Mode kerja diaktifkan."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Penghemat Data nonaktif."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Penghemat Data diaktifkan."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan tampilan"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data 2G-3G dijeda"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data 4G dijeda"</string> diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml index f6315139626c..c12fa9c92a76 100644 --- a/packages/SystemUI/res/values-in/strings_tv.xml +++ b/packages/SystemUI/res/values-in/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Putar"</string> <string name="pip_pause" msgid="8412075640017218862">"Jeda"</string> <string name="pip_hold_home" msgid="340086535668778109">"Tahan "<b>"LAYAR UTAMA"</b>" untuk mengontrol PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Tekan dan tahan tombol LAYAR UTAMA\nuntuk mengontrol PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Tekan dan tahan tombol LAYAR UTAMA untuk mengontrol PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Mengerti"</string> </resources> diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml index 19325958db02..57756e086329 100644 --- a/packages/SystemUI/res/values-is-rIS/strings.xml +++ b/packages/SystemUI/res/values-is-rIS/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Skjámynd var tekin."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Snertu til að skoða skjámyndina."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Ekki tókst að taka skjámynd."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Upp kom vandamál við að vista skjámynd."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Forritið eða fyrirtækið þitt leyfir ekki að teknar séu skjámyndir."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Valkostir USB-skráaflutnings"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Kveikt á vinnustillingu."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Slökkt á vinnustillingu."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Kveikt á vinnustillingu."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Slökkt var á gagnasparnaði."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Kveikt var á gagnasparnaði."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Birtustig skjás"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Slökkt er á 2G- og 3G-gögnum"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Slökkt er á 4G-gögnum"</string> diff --git a/packages/SystemUI/res/values-is-rIS/strings_tv.xml b/packages/SystemUI/res/values-is-rIS/strings_tv.xml index b44aaf0ca1df..9c3db2f9ea9c 100644 --- a/packages/SystemUI/res/values-is-rIS/strings_tv.xml +++ b/packages/SystemUI/res/values-is-rIS/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Spila"</string> <string name="pip_pause" msgid="8412075640017218862">"Hlé"</string> <string name="pip_hold_home" msgid="340086535668778109">"Haltu "<b>"HOME"</b>"-hnappinum inni til að stjórna innfelldri mynd"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Haltu HOME\n-hnappinum inni til að stjórna innfelldri mynd"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Haltu „Home“-hnappinum inni til að stjórna innfelldri mynd"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Ég skil"</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 34faece8a85e..b4f473a4bbde 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot acquisito."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Tocca per visualizzare il tuo screenshot."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Impossibile acquisire lo screenshot."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Si è verificato un problema durante il salvataggio dello screenshot."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opzioni trasferimento file USB"</string> diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml index 08f2b67a5f17..dc79802aeb45 100644 --- a/packages/SystemUI/res/values-it/strings_tv.xml +++ b/packages/SystemUI/res/values-it/strings_tv.xml @@ -19,11 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="pip_close" msgid="3480680679023423574">"Chiudi visualizzazione PIP"</string> + <string name="pip_close" msgid="3480680679023423574">"Chiudi PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Schermo intero"</string> <string name="pip_play" msgid="674145557658227044">"Riproduci"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausa"</string> - <string name="pip_hold_home" msgid="340086535668778109">"Tieni premuto "<b>"HOME"</b>" per controllare la visualizzazione PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Premi e tieni premuto HOME\nper controllare la visualizzazione PIP"</string> + <string name="pip_hold_home" msgid="340086535668778109">"Tieni premuto "<b>"HOME"</b>" per controllare PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Tieni premuto il pulsante HOME per controllare PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 9beed4fc7d6b..2ace8e887bef 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -75,6 +75,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"צילום המסך בוצע."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"גע כדי להציג את צילום המסך שלך"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"לא ניתן לבצע צילום מסך."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"התגלתה בעיה בשמירת צילום מסך."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"לא ניתן לשמור צילום מסך עקב שטח אחסון מוגבל."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"האפליקציה, או הארגון שלך, אינם מתירים לבצע צילומי מסך."</string> <string name="usb_preference_title" msgid="6551050377388882787">"אפשרויות העברת קבצים ב-USB"</string> diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml index 74297e42d695..77deaf613e6c 100644 --- a/packages/SystemUI/res/values-iw/strings_tv.xml +++ b/packages/SystemUI/res/values-iw/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"הפעל"</string> <string name="pip_pause" msgid="8412075640017218862">"השהה"</string> <string name="pip_hold_home" msgid="340086535668778109">"לחץ לחיצה ארוכה על "<b>"דף הבית"</b>" כדי לשלוט ב-PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"לחץ לחיצה ארוכה על לחצן דף הבית\nכדי לשלוט ב-PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"לחץ לחיצה ממושכת על לחצן דף הבית כדי לשלוט ב-PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"הבנתי"</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index b4b24ecc1c80..27bb23224011 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"スクリーンショットを取得しました。"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"タップしてスクリーンショットを表示します。"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"スクリーンショットをキャプチャできませんでした。"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"スクリーンショットの保存中に問題が発生しました。"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"空き容量が足りないため、スクリーンショットを保存できません。"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"アプリまたは組織によって許可されていないため、スクリーンショットは撮れません。"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USBファイル転送オプション"</string> diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml index 8c56866b9b5c..e045fd6d0917 100644 --- a/packages/SystemUI/res/values-ja/strings_tv.xml +++ b/packages/SystemUI/res/values-ja/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP を閉じる"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"全画面表示"</string> <string name="pip_play" msgid="674145557658227044">"再生"</string> <string name="pip_pause" msgid="8412075640017218862">"一時停止"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"PIP を管理するには ["<b>"ホーム"</b>"] を押し続けます"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"閉じる"</string> </resources> diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml index 4c461de820be..14f9406e1adb 100644 --- a/packages/SystemUI/res/values-ka-rGE/strings.xml +++ b/packages/SystemUI/res/values-ka-rGE/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"სკრინშოტი გადაღებულია."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"შეეხეთ ეკრანის სურათის სანახავად."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"ვერ მოხერხდა ეკრანის ანაბეჭდის გადაღება."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ეკრანის ანაბეჭდის შენახვისას წარმოიქმნა პრობლემა."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ფაილის ტრანსფერის პარამეტრები"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"სამსახურის რეჟიმი ჩართულია."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"სამსახურის რეჟიმი გამორთულია."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"სამსახურის რეჟიმი ჩართულია."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"მონაცემთა დამზოგველი გამორთულია."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"მონაცემთა დამზოგველი ჩართულია."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"ეკრანის სიკაშკაშე"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G მონაცემები შეჩერებულია"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G მონაცემები შეჩერებულია"</string> diff --git a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml index 9c5b0d6e7927..e525eba29588 100644 --- a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml +++ b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP-ის დახურვა"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"სრულ ეკრანზე"</string> <string name="pip_play" msgid="674145557658227044">"დაკვრა"</string> <string name="pip_pause" msgid="8412075640017218862">"პაუზა"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"PIP-ის სამართავად, გეჭიროთ "<b>"მთავარ ღილაკზე"</b></string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP-ის სამართავად, ხანგრძლივად დააჭირეთ მთავარ ღილაკს"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"გასაგებია"</string> </resources> diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml index f1c09d8d3c38..07c95c82ecc8 100644 --- a/packages/SystemUI/res/values-kk-rKZ/strings.xml +++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сақталды."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Скриншотты көру үшін түрту."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот жасалмады."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Скриншотты сақтау кезінде мәселе орын алды."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Жадтағы шектеулі бос орынға байланысты скриншотты сақтау мүмкін емес."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB файлын жіберу опциялары"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Жұмыс режимі қосулы."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Жұмыс режимі өшірілді."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Жұмыс режимі қосылды."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Дерек сақтағыш өшірілді."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Дерек сақтағыш қосылды."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Дисплей жарықтығы"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G деректері кідіртілді"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G деректері кідіртілді"</string> diff --git a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml index 3fc3403b14e5..e7e7bfd96bf8 100644 --- a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml +++ b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP жабу"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Толық экран"</string> <string name="pip_play" msgid="674145557658227044">"Ойнату"</string> <string name="pip_pause" msgid="8412075640017218862">"Кідірту"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"PIP басқару үшін "<b>"HOME"</b>" басып тұрыңыз"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP функциясын басқару үшін НЕГІЗГІ БЕТ түймесін басып тұрыңыз"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Түсіндім"</string> </resources> diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml index 845a48e0f01b..cafa32902e5d 100644 --- a/packages/SystemUI/res/values-km-rKH/strings.xml +++ b/packages/SystemUI/res/values-km-rKH/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"បានចាប់យករូបថតអេក្រង់។"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ដើម្បីមើលរូបថតអេក្រង់របស់អ្នក។"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"មិនអាចចាប់យករូបថតអេក្រង់។"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"បានជួបប្រទះបញ្ហាខណៈពេលរក្សាទុកការថតអេក្រង់"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេដោយសារទំហំផ្ទុកមានកម្រិត។"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ការថតរូបអេក្រង់មិនត្រូវបានអនុញ្ញាតដោយកម្មវិធីនេះ ឬស្ថាប័នរបស់អ្នក។"</string> <string name="usb_preference_title" msgid="6551050377388882787">"ជម្រើសផ្ទេរឯកសារតាមយូអេសប៊ី"</string> diff --git a/packages/SystemUI/res/values-km-rKH/strings_tv.xml b/packages/SystemUI/res/values-km-rKH/strings_tv.xml index 4b4213264157..2d40468d7100 100644 --- a/packages/SystemUI/res/values-km-rKH/strings_tv.xml +++ b/packages/SystemUI/res/values-km-rKH/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"បិទ PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"ពេញអេក្រង់"</string> <string name="pip_play" msgid="674145557658227044">"ចាក់"</string> <string name="pip_pause" msgid="8412075640017218862">"ផ្អាក"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"សង្កត់ប៊ូតុង "<b>"ដើម"</b>" ដើម្បីគ្រប់គ្រង PIP"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"យល់ហើយ"</string> </resources> diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml index bf604e783b34..11d239ca8d5a 100644 --- a/packages/SystemUI/res/values-kn-rIN/strings.xml +++ b/packages/SystemUI/res/values-kn-rIN/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲಾಗಿದೆ."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ಶಾಟ್ ವೀಕ್ಷಿಸಲು ಸ್ಪರ್ಶಿಸಿ."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಸೆರೆಹಿಡಿಯಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸುವಲ್ಲಿ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳುವುದನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆ ಅನುಮತಿಸುವುದಿಲ್ಲ."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ಫೈಲ್ ವರ್ಗಾವಣೆ ಆಯ್ಕೆಗಳು"</string> diff --git a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml index 09d7b07e3b05..5ed77050ae29 100644 --- a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"ಪ್ಲೇ"</string> <string name="pip_pause" msgid="8412075640017218862">"ವಿರಾಮ"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP ನಿಯಂತ್ರಿಸಲು "<b>"HOME"</b>" ಕೀಯನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP ನಿಯಂತ್ರಿಸಲು HOME\n ಬಟನ್ ಒತ್ತಿರಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ನಿಯಂತ್ರಿಸಲು HOME ಬಟನ್ ಒತ್ತಿರಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"ಅರ್ಥವಾಯಿತು"</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 1a1cabe10f07..30d421643381 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"캡쳐화면 저장됨"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"캡쳐화면을 보려면 터치하세요."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"캡쳐화면을 캡쳐하지 못했습니다."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"스크린샷을 저장하는 중 문제가 발생했습니다."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB 파일 전송 옵션"</string> diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml index e7cac9fc2a8b..2846e55c0375 100644 --- a/packages/SystemUI/res/values-ko/strings_tv.xml +++ b/packages/SystemUI/res/values-ko/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP 닫기"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"전체화면"</string> <string name="pip_play" msgid="674145557658227044">"재생"</string> <string name="pip_pause" msgid="8412075640017218862">"일시중지"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109"><b>"HOME"</b>"을 눌러 PIP 제어"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"확인"</string> </resources> diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml index 571b69157a02..653dded1a4e3 100644 --- a/packages/SystemUI/res/values-ky-rKG/strings.xml +++ b/packages/SystemUI/res/values-ky-rKG/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот тартылды."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Тийип, скриншотту көрүңүз."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот кылынбай жатат."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Скриншотту сактоо учурунда көйгөй чыкты."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сактагычта бош орун аз болгондуктан скриншот сакталбай жатат."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Скриншот тартууга колдонмо же ишканаңыз уруксат бербейт."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB менен файл өткөрүү мүмкүнчүлүктөрү"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Иштөө режими күйүк."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Иштөө режими өчүрүлдү."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Иштөө режими күйгүзүлдү."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Дайындарды үнөмдөгүч өчүрүлдү."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Дайындарды үнөмдөгүч күйгүзүлдү."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Жарыктыгын көрсөтүү"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G дайындары тындырылды."</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G дайындары тындырылды"</string> diff --git a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml index 2724230fc74a..2da47ea689c9 100644 --- a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml +++ b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP\'ти жабуу"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Толук экран"</string> <string name="pip_play" msgid="674145557658227044">"Ойнотуу"</string> <string name="pip_pause" msgid="8412075640017218862">"Тындыруу"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109"><b>"БАШКЫ БЕТ"</b>" басып туруп PIP\'ти башкарыңыз"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP көзөмөлдөө үчүн БАШКЫ БЕТ баскычын басып, кармап туруңуз"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Түшүндүм"</string> </resources> diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml index 823e02b82818..80c1e01d7137 100644 --- a/packages/SystemUI/res/values-lo-rLA/strings.xml +++ b/packages/SystemUI/res/values-lo-rLA/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"ຖ່າຍຮູບໜ້າຈໍແລ້ວ"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"ແຕະເພື່ອເບິ່ງພາບໜ້າຈໍຂອງທ່ານ."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ເກີດບັນຫາໃນການບັນທຶກພາບໜ້າຈໍຂອງທ່ານ."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ມີການຖ່າຍຮູບໜ້າຈໍ."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ໂຕເລືອກການຍ້າຍໄຟລ໌"</string> diff --git a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml index 47374e8affe2..e4116f855a50 100644 --- a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml +++ b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"ປິດ PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"ເຕັມໜ້າຈໍ"</string> <string name="pip_play" msgid="674145557658227044">"ຫຼິ້ນ"</string> <string name="pip_pause" msgid="8412075640017218862">"ຢຸດຊົ່ວຄາວ"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"ກົດ "<b>"HOME"</b>" ຄ້າງໄວ້ເພື່ອຄວບຄຸມ PIP"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"ເຂົ້າໃຈແລ້ວ"</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index db354eb26b40..3c7af5c63721 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -75,6 +75,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrano kopija užfiksuota."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Palieskite, kad peržiūrėtumėte ekrano kopiją."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Išsaugant ekrano kopiją iškilo problemų."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string> diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml index ac3a44e9a3d8..8c60970b8c78 100644 --- a/packages/SystemUI/res/values-lt/strings_tv.xml +++ b/packages/SystemUI/res/values-lt/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Uždaryti PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Visas ekranas"</string> <string name="pip_play" msgid="674145557658227044">"Leisti"</string> <string name="pip_pause" msgid="8412075640017218862">"Pristabdyti"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Kad vald. PIP, pal. pasp. m. "<b>"PAGRINDINIS"</b></string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Jei norite valdyti PIP, paspauskite ir palaikykite pagrindinio puslapio mygtuką"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Supratau"</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 29e1b95c7845..bafad80fb99d 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -74,6 +74,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrānuzņēmums ir uzņemts."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Nevarēja uzņemt ekrānuzņēmumu."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Saglabājot ekrānuzņēmumu, radās problēma."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB failu pārsūtīšanas opcijas"</string> diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml index 7fa804db1c90..397376a2700a 100644 --- a/packages/SystemUI/res/values-lv/strings_tv.xml +++ b/packages/SystemUI/res/values-lv/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Aizvērt PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Pilnekrāna režīms"</string> <string name="pip_play" msgid="674145557658227044">"Atskaņot"</string> <string name="pip_pause" msgid="8412075640017218862">"Apturēt"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Turiet taustiņu "<b>"SĀKUMS"</b>", lai kontrolētu PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Nospiediet un turiet pogu SĀKUMS, lai kontrolētu PIP"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Labi"</string> </resources> diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml index cf97df84fabc..490200618b63 100644 --- a/packages/SystemUI/res/values-mk-rMK/strings.xml +++ b/packages/SystemUI/res/values-mk-rMK/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Сликата на екранот е снимена."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Допрете за да ја видите сликата на екранот."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Сликата на екранот не можеше да се сними."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Се појави проблем при зачувување на сликата од екранот."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сликата од екранот не може да се зачува поради ограничена меморија."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Апликацијата или вашата организација не дозволува создавање слики од екранот."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Пренос на датотека со УСБ"</string> diff --git a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml index 30c6db9297d3..acb04be8fbb9 100644 --- a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml +++ b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Затвори PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Цел екран"</string> <string name="pip_play" msgid="674145557658227044">"Пушти"</string> <string name="pip_pause" msgid="8412075640017218862">"Пауза"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"Задржете "<b>"ДОМА"</b>" за кон. PIP"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Разбрав"</string> </resources> diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml index df69933ba178..9bbc3ad8e810 100644 --- a/packages/SystemUI/res/values-ml-rIN/strings.xml +++ b/packages/SystemUI/res/values-ml-rIN/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"സ്ക്രീൻഷോട്ട് എടുത്തു."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"നിങ്ങളുടെ സ്ക്രീൻഷോട്ട് കാണാനായി സ്പർശിക്കുക."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്ന സമയത്ത് പ്രശ്നം നേരിട്ടു."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"സ്റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാൻ കഴിയില്ല."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ഫയൽ കൈമാറൽ ഓപ്ഷനുകൾ"</string> diff --git a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml index 564a32ab1870..3d6250d3ec59 100644 --- a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP അടയ്ക്കുക"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"പൂര്ണ്ണ സ്ക്രീന്"</string> <string name="pip_play" msgid="674145557658227044">"പ്ലേ ചെയ്യുക"</string> <string name="pip_pause" msgid="8412075640017218862">"തൽക്കാലം നിർത്തൂ"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"PIP നിയന്ത്രിക്കാൻ "<b>"ഹോം"</b>" പിടിക്കുക"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"മനസ്സിലായി"</string> </resources> diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml index 793e16551f06..73df53559da6 100644 --- a/packages/SystemUI/res/values-mn-rMN/strings.xml +++ b/packages/SystemUI/res/values-mn-rMN/strings.xml @@ -71,6 +71,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Дэлгэцийн агшинг авсан."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Дэлгэцийн агшныг харах бол хүрнэ үү."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Дэлгэцийн агшинг авч чадсангүй."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Дэлгэцийн агшинг хадгалахад алдаа гарлаа."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Хадгалах сангийн багтаамж бага байгаа тул дэлгэцийн авсан зургийг хадгалах боломжгүй байна."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Дэлгэцийн зураг авахыг апп эсвэл танай байгууллагаас зөвшөөрөөгүй байна."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB файл шилжүүлэх сонголт"</string> diff --git a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml index ae4029fd4eb2..334a9f115c56 100644 --- a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml +++ b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP-г хаах"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Бүтэн дэлгэц"</string> <string name="pip_play" msgid="674145557658227044">"Тоглуулах"</string> <string name="pip_pause" msgid="8412075640017218862">"Түр зогсоох"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"PIP-г удирдахын тулд "<b>"HOME"</b>" товчлуурыг дарна уу"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Ойлголоо"</string> </resources> diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml index e39db5d0789c..a37365c94c7f 100644 --- a/packages/SystemUI/res/values-mr-rIN/strings.xml +++ b/packages/SystemUI/res/values-mr-rIN/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रीनशॉट कॅप्चर केला."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"आपला स्क्रीनशॉट पाहण्यासाठी स्पर्श करा."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रीनशॉट कॅप्चर करू शकलो नाही."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रीनशॉट जतन करताना समस्या आली."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"मर्यादित संचय जागेमुळे स्क्रीनशॉट जतन करू शकत नाही."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"अॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्यास अनुमती नाही."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB फाईल स्थानांतरण पर्याय"</string> diff --git a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml index fd76c531356b..2f56b0aa0178 100644 --- a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"प्ले करा"</string> <string name="pip_pause" msgid="8412075640017218862">"विराम द्या"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP नियंत्रित करण्यासाठी "<b>"मुख्यपृष्ठ"</b>" धरून ठेवा"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP नियंत्रित करण्यासाठी\nमुख्यपृष्ठ बटण धरून ठेवा"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP नियंत्रित करण्यासाठी मुख्यपृष्ठ बटण दाबा आणि धरून ठेवा"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"समजले"</string> </resources> diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml index 3ec3db17da1c..e2175e53399c 100644 --- a/packages/SystemUI/res/values-ms-rMY/strings.xml +++ b/packages/SystemUI/res/values-ms-rMY/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan skrin ditangkap."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan skrin anda."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat menangkap tangkapan skrin."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Berlaku masalah semasa menyimpan tangkapan skrin."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Apl atau organisasi anda tidak membenarkan pengambilan tangkapan skrin."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Pilihan pemindahan fail USB"</string> diff --git a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml index feae0424b603..83dee5ae9a37 100644 --- a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml +++ b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Tutup PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Skrin penuh"</string> <string name="pip_play" msgid="674145557658227044">"Main"</string> <string name="pip_pause" msgid="8412075640017218862">"Jeda"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"Thn "<b>"SKRN UTMA"</b>" utk kwl PIP"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml index ca3414488583..d6362f332ab5 100644 --- a/packages/SystemUI/res/values-my-rMM/strings.xml +++ b/packages/SystemUI/res/values-my-rMM/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ဖမ်းယူပြီး"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"သင့်ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား ကြည့်ရှုရန် ထိပါ"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား မဖမ်းစီးနိုင်ပါ"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ဖန်သားပြင်ဓာတ်ပုံဖမ်းယူမှုကို သိမ်းဆည်းရာတွင် ပြဿနာကြုံခဲ့သည်။"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ။"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို အက်ပ်မှ သို့မဟုတ် သင့်အဖွဲ့အစည်းမှ ခွင့်မပြုပါ။"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ဖိုင်ပြောင်း ရွေးမှုများ"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"အလုပ် မုဒ်ကို ဖွင့်ထားပါသည်။"</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"အလုပ် မုဒ်ကို ပိတ်ထားပါသည်။"</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"အလုပ် မုဒ်ကို ဖွင့်ထားပါသည်။"</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"ဒေတာချွေတာမှု ပိတ်ထားသည်။"</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"ဒေတာချွေတာမှု ဖွင့်ထားသည်။"</string> <string name="accessibility_brightness" msgid="8003681285547803095">"တောက်ပမှုကို ပြရန်"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ဒေတာ ခေတ္တရပ်တန့်သည်"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G data ခေတ္တရပ်တန့်သည်"</string> diff --git a/packages/SystemUI/res/values-my-rMM/strings_tv.xml b/packages/SystemUI/res/values-my-rMM/strings_tv.xml index ebadebe4516b..616acda0b567 100644 --- a/packages/SystemUI/res/values-my-rMM/strings_tv.xml +++ b/packages/SystemUI/res/values-my-rMM/strings_tv.xml @@ -23,7 +23,7 @@ <string name="pip_fullscreen" msgid="8604643018538487816">"မျက်နှာပြင် အပြည့်"</string> <string name="pip_play" msgid="674145557658227044">"ဖွင့်ပါ"</string> <string name="pip_pause" msgid="8412075640017218862">"ဆိုင်းငံ့ပါ"</string> - <string name="pip_hold_home" msgid="340086535668778109">"PIP ကိုထိန်းချုပ်ရန် "<b>"ပင်မခလုတ်"</b>" ကိုဖိထားပါ"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP ကိုထိန်းချုပ်ရန် ပင်မခလုတ်\nကိုနှိပ်ပြီးဖိထားပါ"</string> + <string name="pip_hold_home" msgid="340086535668778109">"PIP ကိုထိန်းချုပ်ရန် "<b>"ပင်မ"</b>" ခလုတ်ကို ဖိထားပါ"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ကိုထိန်းချုပ်ရန် ပင်မခလုတ်ကို နှိပ်ပြီးဖိထားပါ"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"ရပါပြီ"</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 269746e2a56a..a2b09c556d54 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Skjermdumpen er lagret."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Trykk for å se skjermdumpen."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Kan ikke lagre skjermdumpen."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Det oppsto et problem under lagring av skjermdumpen."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string> diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml index 8574d66a3129..921744e575cf 100644 --- a/packages/SystemUI/res/values-nb/strings_tv.xml +++ b/packages/SystemUI/res/values-nb/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Spill av"</string> <string name="pip_pause" msgid="8412075640017218862">"Sett på pause"</string> <string name="pip_hold_home" msgid="340086535668778109">"Hold inne "<b>"STARTSIDE"</b>" for å kontrollere PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Trykk og hold STARTSIDE-\nknappen for å kontrollere PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Trykk og hold inne STARTSIDE-knappen for å kontrollere PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Greit"</string> </resources> diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml index 882a19426cf9..42067abd9cf4 100644 --- a/packages/SystemUI/res/values-ne-rNP/strings.xml +++ b/packages/SystemUI/res/values-ne-rNP/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रिनसट क्याप्चर गरियो।"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"तपाईँको स्क्रिनसट हेर्न छुनुहोस्।"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रिनसट क्याप्चर गर्न सकिएन।"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"स्क्रिनसटलाई सुरक्षित गर्दा समस्या भयो।"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"सीमित भण्डारण स्थान उपलब्ध रहेको हुनाले स्क्रिनसटलाई सुरक्षित गर्न सकिँदैन।"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"अनुप्रयोग वा तपाईँको संगठनले स्क्रिनसट लिन अनुमति दॅिंदैन।"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB फाइल सार्ने विकल्पहरू"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"कार्य मोड अन।"</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"कार्य मोड बन्द भयो।"</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"कार्य मोड सक्रिय भयो।"</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"डेटा सेभरलाई निष्क्रिय पारियो।"</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"डेटा सेभरलाई सक्रिय गरियो।"</string> <string name="accessibility_brightness" msgid="8003681285547803095">"प्रदर्शन चमक"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G डेटा रोकिएको छ"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G डेटा रोकिएको छ"</string> diff --git a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml index 68c86ca79fe0..adfb4433d361 100644 --- a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml +++ b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"प्ले गर्नुहोस्"</string> <string name="pip_pause" msgid="8412075640017218862">"रोक्नुहोस्"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP लाई नियन्त्रण गर्न "<b>"गृह"</b>" कुञ्जीलाई थिचिरहनुहोस्"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP लाई नियन्त्रण गर्न गृह\nबटनलाई थिचेर होल्ड गर्नुहोस्"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"IP लाई नियन्त्रण गर्न गृह बटनलाई थिची होल्ड गर्नुहोस्"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"बुझेँ"</string> </resources> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 99acbaa2e3f9..6f15bafee917 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot gemaakt."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Raak aan om je screenshot te bekijken."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot is niet gemaakt."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Er is een probleem opgetreden bij het opslaan van het screenshot."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan screenshot niet opslaan vanwege beperkte opslagruimte."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opties voor USB-bestandsoverdracht"</string> diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml index c116f817da3d..8ccf464e5b04 100644 --- a/packages/SystemUI/res/values-nl/strings_tv.xml +++ b/packages/SystemUI/res/values-nl/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Afspelen"</string> <string name="pip_pause" msgid="8412075640017218862">"Onderbreken"</string> <string name="pip_hold_home" msgid="340086535668778109">"Bedien PIP met "<b>"HOME"</b></string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Houd HOME ingedrukt\nom PIP te bedienen"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Houd HOME ingedrukt om PIP te bedienen"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml index 2de6583096c1..d07c4d2a864f 100644 --- a/packages/SystemUI/res/values-pa-rIN/strings.xml +++ b/packages/SystemUI/res/values-pa-rIN/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਕੀਤਾ।"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ੌਟ ਦੇਖਣ ਲਈ ਛੋਹਵੋ।"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕਰਨ ਦੌਰਾਨ ਸਮੱਸਿਆ ਆਈ।"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਥਾਂ ਦੇ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ।"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਦੁਆਰਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਮਨਜ਼ੂਰੀ ਨਹੀਂ ਹੈ।"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਚੋਣਾਂ"</string> diff --git a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml index 1bf28af27ebe..fafcd622c545 100644 --- a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"ਚਲਾਓ"</string> <string name="pip_pause" msgid="8412075640017218862">"ਰੋਕੋ"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP ਕੰਟਰੋਲ ਕਰਨ ਲਈ "<b>"ਹੋਮ"</b>" ਦਬਾਈ ਰੱਖੋ"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਹੋਮ\nਬਟਨ ਦਬਾਈ ਰੱਖੋ"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਹੋਮ ਬਟਨ ਨੂੰ ਦੱਬੋ ਅਤੇ ਦਬਾਈ ਰੱਖੋ"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"ਸਮਝ ਲਿਆ"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 0fdb4dfd5195..5a4a320e0dc5 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -75,6 +75,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Wykonano zrzut ekranu."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Dotknij, aby wyświetlić zrzut ekranu."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Nie udało się wykonać zrzutu ekranu."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Podczas zapisywania zrzutu ekranu wystąpił błąd."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB – opcje przesyłania plików"</string> diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml index b804146643ab..d0371b05725a 100644 --- a/packages/SystemUI/res/values-pl/strings_tv.xml +++ b/packages/SystemUI/res/values-pl/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Odtwórz"</string> <string name="pip_pause" msgid="8412075640017218862">"Wstrzymaj"</string> <string name="pip_hold_home" msgid="340086535668778109">"Przytrzymaj "<b>"EKRAN GŁÓWNY"</b>", by sterować PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Przytrzymaj EKRAN GŁÓWNY,\nby sterować PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Przytrzymaj przycisk EKRAN GŁÓWNY, by sterować PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 86b94ab55819..089fa7527d44 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para visualizar a captura de tela."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao salvar captura de tela."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Capturas de tela não são permitidas pelo app ou por sua organização."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabalho desativado."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabalho ativado."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Economia de dados desativada."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Economia de dados ativada."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho da tela"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os dados 2G e 3G foram pausados"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml index 742ea28e6751..36ba02db88ba 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Fechar PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Tela cheia"</string> <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Mantenha "<b>"INÍCIO"</b>" pressionado para controlar o PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantenha a tecla \"HOME\" pressionada para controlar o PIP"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendi"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 35ef0dd7b65b..166067020253 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de ecrã efetuada"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para ver a captura de ecrã"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter captura de ecrã."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao guardar a captura de ecrã."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"A aplicação ou a sua entidade não tem autorização para tirar capturas de ecrã."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"O modo de trabalho foi desativado."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"O modo de trabalho foi ativado."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Poupança de dados desativada."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Poupança de dados ativada."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho do visor"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dados 2G-3G em pausa"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dados 4G em pausa"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml index 8b1b032eb3ff..b588c7bf7691 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string> <string name="pip_pause" msgid="8412075640017218862">"Interromper"</string> <string name="pip_hold_home" msgid="340086535668778109">"Prima sem soltar o botão "<b>"HOME"</b>" para controlar o PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Prima sem soltar o botão HOME\npara controlar o PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Prima sem soltar o botão HOME para controlar o PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Compreendi"</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 86b94ab55819..089fa7527d44 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de tela obtida."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Toque para visualizar a captura de tela."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Não foi possível obter a captura de tela."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problema encontrado ao salvar captura de tela."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Não é possível salvar a captura de tela, porque não há espaço suficiente."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Capturas de tela não são permitidas pelo app ou por sua organização."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opções transf. arq. por USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Modo de trabalho ativado."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Modo de trabalho desativado."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Modo de trabalho ativado."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Economia de dados desativada."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Economia de dados ativada."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Brilho da tela"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Os dados 2G e 3G foram pausados"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Os dados 4G foram pausados"</string> diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml index 742ea28e6751..36ba02db88ba 100644 --- a/packages/SystemUI/res/values-pt/strings_tv.xml +++ b/packages/SystemUI/res/values-pt/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Fechar PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Tela cheia"</string> <string name="pip_play" msgid="674145557658227044">"Reproduzir"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausar"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Mantenha "<b>"INÍCIO"</b>" pressionado para controlar o PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Mantenha a tecla \"HOME\" pressionada para controlar o PIP"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Entendi"</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index b854ffba4579..b7e0834c5dbc 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -74,6 +74,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Captură de ecran realizată."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Atingeți pentru a vedea captura de ecran."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Captura de ecran nu a putut fi realizată."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Problemă întâmpinată la salvarea capturii de ecran."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opțiuni pentru transferul de fișiere prin USB"</string> diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml index cbe5e386e78e..0af2b39599d5 100644 --- a/packages/SystemUI/res/values-ro/strings_tv.xml +++ b/packages/SystemUI/res/values-ro/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Închideți PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Ecran complet"</string> <string name="pip_play" msgid="674145557658227044">"Redați"</string> <string name="pip_pause" msgid="8412075640017218862">"Întrerupeți"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Apăsați lung "<b>"ACASĂ"</b>" pentru a controla PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Apăsați lung butonul ACASĂ pentru a controla PIP"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Am înțeles"</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 5a7e51c74cac..f73ebf4397d2 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -75,6 +75,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сохранен"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Нажмите, чтобы просмотреть"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Не удалось сохранить скриншот."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Не удалось сохранить скриншот."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не удалось сохранить скриншот: недостаточно места."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Параметры передачи через USB"</string> diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml index dd9cb5a8b20d..30f55cbca9c9 100644 --- a/packages/SystemUI/res/values-ru/strings_tv.xml +++ b/packages/SystemUI/res/values-ru/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"\"Кадр в кадре\" – выйти"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Во весь экран"</string> <string name="pip_play" msgid="674145557658227044">"Воспроизвести"</string> <string name="pip_pause" msgid="8412075640017218862">"Приостановить"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Управляйте кадром в кадре, удерживая кнопку "<b>"ГЛАВНАЯ"</b></string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Управляйте режимом \"Кадр в кадре\", удерживая кнопку ГЛАВНАЯ"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"ОК"</string> </resources> diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml index 1e178cfe3d08..5a09d3e4785f 100644 --- a/packages/SystemUI/res/values-si-rLK/strings.xml +++ b/packages/SystemUI/res/values-si-rLK/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"තිර රුව ග්රහණය කරන ලදි."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"ඔබගේ තිර රුව බැලීමට ස්පර්ශ කරන්න."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"තිර රුව ග්රහණය කිරීමට නොහැකි විය."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"තිර රුව සුරකින අතරතුර ගැටලුවක් ඇති විය."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ගොනු හුවමාරු විකල්ප"</string> diff --git a/packages/SystemUI/res/values-si-rLK/strings_tv.xml b/packages/SystemUI/res/values-si-rLK/strings_tv.xml index b2c6485ac3a6..70884b032c02 100644 --- a/packages/SystemUI/res/values-si-rLK/strings_tv.xml +++ b/packages/SystemUI/res/values-si-rLK/strings_tv.xml @@ -24,6 +24,7 @@ <string name="pip_play" msgid="674145557658227044">"ධාවනය කරන්න"</string> <string name="pip_pause" msgid="8412075640017218862">"විරාමය"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP පාලනයට "<b>"HOME"</b>" අල්ලාගන්න"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP පාලනයට HOME\nඔබා අල්ලාගන්න"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> + <skip /> <string name="pip_onboarding_button" msgid="3957426748484904611">"හරි, තේරුණා"</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index c07598055318..edae154a8474 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -75,6 +75,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímka obrazovky bola zaznamenaná."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Snímku obrazovky zobrazíte dotykom."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Snímku obrazovky sa nepodarilo zachytiť."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Pri ukladaní snímky obrazovky sa vyskytol problém."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímku obrazovky nie je možné vytvoriť z dôvodu nedostatku miesta v úložisku."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string> @@ -222,10 +223,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Pracovný režim – zap."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Pracovný režim je vypnutý."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Pracovný režim je zapnutý."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Šetrič dát bol vypnutý."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Šetrič dát bol zapnutý."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Jas displeja"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Dátové prenosy 2G a 3G sú pozastavené"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Dátové prenosy 4G sú pozastavené"</string> diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml index 46f88f90b9c0..98a67f877d5c 100644 --- a/packages/SystemUI/res/values-sk/strings_tv.xml +++ b/packages/SystemUI/res/values-sk/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Prehrať"</string> <string name="pip_pause" msgid="8412075640017218862">"Pozastaviť"</string> <string name="pip_hold_home" msgid="340086535668778109">"Režim PIP ovládajte pomocou tlačidla "<b>"PLOCHA"</b></string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Režim PIP ovládajte stlačením a podržaním tlačidla PLOCHA\n"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Režim PIP ovládajte stlačením a podržaním tlačidla PLOCHA"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Dobre"</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 8aa79bec6725..b268f183ff6a 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -75,6 +75,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Posnetek zaslona je shranjen."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Dotaknite se, če si želite ogledati posnetek zaslona."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Posnetka zaslona ni bilo mogoče shraniti."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Pri shranjevanju posnetka zaslona je prišlo do težave."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Aplikacija ali organizacija ne dovoljuje posnetkov zaslona."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosa datotek prek USB-ja"</string> diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml index 9fab6e1dfede..20de9c5fb30c 100644 --- a/packages/SystemUI/res/values-sl/strings_tv.xml +++ b/packages/SystemUI/res/values-sl/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Zapri način PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Celozaslonsko"</string> <string name="pip_play" msgid="674145557658227044">"Predvajanje"</string> <string name="pip_pause" msgid="8412075640017218862">"Zaustavitev"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Pridr. "<b>"HOME"</b>" za up. n. PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Pridržite gumb HOME za upravljanje načina PIP"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Razumem"</string> </resources> diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml index 8314044b072e..f657fb495976 100644 --- a/packages/SystemUI/res/values-sq-rAL/strings.xml +++ b/packages/SystemUI/res/values-sq-rAL/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Pamja e ekranit u kap."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Prek për të parë pamjen e ekranit tënd."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Nuk mundi të kapte pamjen e ekranit."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"U has problem gjatë ruajtjes së pamjes së ekranit."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opsionet e transferimit të dosjeve të USB-së"</string> diff --git a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml index 10cf2f9f7dd2..481662ffabd4 100644 --- a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml +++ b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Mbyll PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Ekrani i plotë"</string> <string name="pip_play" msgid="674145557658227044">"Luaj"</string> <string name="pip_pause" msgid="8412075640017218862">"Pauzë"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"Mbaj shtypur "<b>"HOME"</b>" për të kontrolluar PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Shtyp dhe mbaj shtypur butonin HOME për të kontrolluar PIP"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"E kuptova"</string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 318a92afe743..52d52e023211 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -74,6 +74,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Снимак екрана је направљен."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Додирните да бисте видели снимак екрана."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Није могуће направити снимак екрана."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Дошло је до проблема при чувању снимка екрана."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Чување снимка екрана није успело због ограниченог меморијског простора."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Апликација или организација не дозвољавају прављење снимака екрана."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Опције USB преноса датотека"</string> diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml index 4b03b6894a90..eed8f51c6d80 100644 --- a/packages/SystemUI/res/values-sr/strings_tv.xml +++ b/packages/SystemUI/res/values-sr/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Пусти"</string> <string name="pip_pause" msgid="8412075640017218862">"Паузирај"</string> <string name="pip_hold_home" msgid="340086535668778109"><b>"ПОЧЕТНИ ЕКРАН"</b>" конт. PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Притисните и задржите дугме ПОЧЕТНИ ЕКРАН\n да бисте контролисали PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Притисните и задржите дугме ПОЧЕТНИ ЕКРАН да бисте контролисали PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Важи"</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index a50e7442aeab..1c72fa96b220 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Skärmdumpen har tagits."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Tryck här om du vill visa skärmdumpen."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Det gick inte att ta någon skärmdump."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Det gick inte att spara skärmdumpen."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Appen eller organisationen tillåter inte att du tar skärmdumpar."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Överföringsalternativ"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Arbetsläget aktiverat."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Arbetsläget har inaktiverats."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Arbetsläget har aktiverats."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Databesparing har inaktiverats."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Databesparing har aktiverats."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Skärmens ljusstyrka"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G- och 3G-data har pausats"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G-data har pausats"</string> diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml index dc65877621d7..2b2c5c282a4e 100644 --- a/packages/SystemUI/res/values-sv/strings_tv.xml +++ b/packages/SystemUI/res/values-sv/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Spela upp"</string> <string name="pip_pause" msgid="8412075640017218862">"Pausa"</string> <string name="pip_hold_home" msgid="340086535668778109">"Styr PIP med "<b>"startknappen"</b></string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Håll ned startknappen\n för att styra PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Styr bild-i-bild genom att hålla ned startsideknappen"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 2a10259b6789..5fe6375771e4 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Picha ya skrini imenaswa."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Gusa ili kuona picha yako ya skrini."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Haikuweza kunasa picha ya skrini"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Hitilafu imetokea wakati wa kuhifadhi picha ya skrini."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Haina nafasi ya kutosha kuhifadhi picha ya skrini."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Shirika au programu yako haikuruhusu upige picha za skrini."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Machaguo ya uhamisho wa faili la USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Hali ya kazi imewashwa."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Hali ya kazi imezimwa."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Hali ya kazi imewashwa."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Kiokoa Data kimezimwa."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Kiokoa Data kimewashwa."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Ung\'aavu wa skrini"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Data ya 2G-3G imesitishwa"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Data ya 4G imesitishwa"</string> diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml index 9b3799adde1b..337c1360f3cf 100644 --- a/packages/SystemUI/res/values-sw/strings_tv.xml +++ b/packages/SystemUI/res/values-sw/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Cheza"</string> <string name="pip_pause" msgid="8412075640017218862">"Sitisha"</string> <string name="pip_hold_home" msgid="340086535668778109">"Shikilia kitufe cha "<b>"HOME"</b>" ili udhibiti PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Bonyeza na ushikilie kitufe cha\nHOME ili udhibiti PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Bonyeza na ushikilie kitufe cha HOME ili kudhibiti PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Nimeelewa"</string> </resources> diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml index eb7dbe4018d9..570aeae47e1a 100644 --- a/packages/SystemUI/res/values-ta-rIN/strings.xml +++ b/packages/SystemUI/res/values-ta-rIN/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"ஸ்கிரீன் ஷாட் எடுக்கப்பட்டது."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"உங்கள் ஸ்க்ரீன் ஷாட்டைப் பார்க்க தொடவும்."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"ஸ்க்ரீன் ஷாட்டை எடுக்க முடியவில்லை."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ஸ்க்ரீன்ஷாட்டைச் சேமிக்கும் போது, பிழை ஏற்பட்டது."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"பயன்பாடு அல்லது உங்கள் நிறுவனம் ஸ்கிரீன்ஷாட்டுகளை எடுக்க அனுமதிக்கவில்லை."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string> diff --git a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml index d4d661a31f25..b92af22109b6 100644 --- a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml @@ -24,6 +24,7 @@ <string name="pip_play" msgid="674145557658227044">"இயக்கு"</string> <string name="pip_pause" msgid="8412075640017218862">"இடைநிறுத்து"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIPஐக் கட்டுப்படுத்த, "<b>"முகப்பைப்"</b>" பிடித்திருக்கவும்"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIPஐக் கட்டுப்படுத்த, முகப்புப்\nபொத்தானை அழுத்தவும், பிடிக்கவும்"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> + <skip /> <string name="pip_onboarding_button" msgid="3957426748484904611">"சரி"</string> </resources> diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml index 29e25392a604..f0e5c60146c5 100644 --- a/packages/SystemUI/res/values-te-rIN/strings.xml +++ b/packages/SystemUI/res/values-te-rIN/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"స్క్రీన్షాట్ క్యాప్చర్ చేయబడింది."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"మీ స్క్రీన్షాట్ను వీక్షించడానికి తాకండి."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"స్క్రీన్షాట్ను క్యాప్చర్ చేయడం సాధ్యపడలేదు."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"స్క్రీన్షాట్ని సేవ్ చేస్తున్నప్పుడు సమస్య సంభవించింది."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"పరిమిత నిల్వ స్థలం కారణంగా స్క్రీన్షాట్ను సేవ్ చేయడం సాధ్యపడదు."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"స్క్రీన్షాట్లు తీయడానికి అనువర్తనం లేదా మీ సంస్థ అనుమతించలేదు."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB ఫైల్ బదిలీ ఎంపికలు"</string> diff --git a/packages/SystemUI/res/values-te-rIN/strings_tv.xml b/packages/SystemUI/res/values-te-rIN/strings_tv.xml index 4c18743006a0..7ce24cb4fdc1 100644 --- a/packages/SystemUI/res/values-te-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-te-rIN/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"ప్లే చేయి"</string> <string name="pip_pause" msgid="8412075640017218862">"పాజ్ చేయి"</string> <string name="pip_hold_home" msgid="340086535668778109">"PIP నియం. "<b>"HOME"</b>"నొక్కిఉంచండి"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"PIPని నియంత్రించడానికి HOME\nబటన్ను నొక్కి ఉంచండి"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIPని నియంత్రించడానికి హోమ్ బటన్ను నొక్కి పట్టుకోండి"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"అర్థమైంది"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 2fb82b75218e..98029ed9c785 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"จับภาพหน้าจอแล้ว"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"แตะเพื่อดูภาพหน้าจอของคุณ"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"ไม่สามารถจับภาพหน้าจอ"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"พบปัญหาขณะกำลังบันทึกภาพหน้าจอ"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ไม่สามารถบันทึกภาพหน้าจอเนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string> <string name="usb_preference_title" msgid="6551050377388882787">"ตัวเลือกการถ่ายโอนไฟล์ USB"</string> diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml index 78fd1b8837fc..abc1a87c57b1 100644 --- a/packages/SystemUI/res/values-th/strings_tv.xml +++ b/packages/SystemUI/res/values-th/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"ปิด PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"เต็มหน้าจอ"</string> <string name="pip_play" msgid="674145557658227044">"เล่น"</string> <string name="pip_pause" msgid="8412075640017218862">"หยุดชั่วคราว"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"กด "<b>"HOME"</b>" ค้างไว้เพื่อควบคุม PIP"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"รับทราบ"</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 943d21fc4654..d93fd96362f6 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Nakuha ang screenshot."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Pindutin upang tingnan ang iyong screenshot."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Hindi makuha ang screenshot."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Nagkaroon ng problema habang sine-save ang screenshot."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Hindi pinapayagan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Opsyon paglipat ng USB file"</string> diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml index db898c689b24..e6aad6045f7f 100644 --- a/packages/SystemUI/res/values-tl/strings_tv.xml +++ b/packages/SystemUI/res/values-tl/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Isara ang PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Full screen"</string> <string name="pip_play" msgid="674145557658227044">"I-play"</string> <string name="pip_pause" msgid="8412075640017218862">"I-pause"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"I-hold ang "<b>"HOME"</b>" para makontrol ang PIP"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index a294977f5181..039a63f5e84d 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran görüntüsü alındı."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Ekran görüntünüzü izlemek için dokunun."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Ekran görüntüsü alınamadı."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Ekran görüntüsü kaydedilirken sorun oluştu."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB dosya aktarım seçenekleri"</string> diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml index 255df49a66d3..c6da011442d3 100644 --- a/packages/SystemUI/res/values-tr/strings_tv.xml +++ b/packages/SystemUI/res/values-tr/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP\'yi kapat"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Tam ekran"</string> <string name="pip_play" msgid="674145557658227044">"Oynat"</string> <string name="pip_pause" msgid="8412075640017218862">"Duraklat"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"PIP\'yi kontrol etmek için "<b>"ANA EKRAN"</b>"\'ı basılı tutun"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"Anladım"</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 41b89f905e1f..e2ca5c57d956 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -75,6 +75,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Знімок екрана зроблено."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Торкніться, щоб переглянути знімок екрана."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Не вдалося зробити знімок екрана."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Не вдалося зберегти знімок екрана."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Додаток або ваша організація не дозволяють робити знімки екрана."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Парам.передав.файлів через USB"</string> diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml index 22bcf52ba4aa..dcb7a52ccbad 100644 --- a/packages/SystemUI/res/values-uk/strings_tv.xml +++ b/packages/SystemUI/res/values-uk/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Відтворити"</string> <string name="pip_pause" msgid="8412075640017218862">"Призупинити"</string> <string name="pip_hold_home" msgid="340086535668778109">"Щоб керувати PIP, утримуйте кнопку "<b>"ГОЛОВНИЙ ЕКРАН"</b></string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Щоб керувати PIP,\nутримуйте кнопку \"ГОЛОВНИЙ ЕКРАН\""</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Щоб керувати PIP, утримуйте кнопку \"ГОЛОВНИЙ ЕКРАН\""</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml index ba2d014852e3..866350c4a17f 100644 --- a/packages/SystemUI/res/values-ur-rPK/strings.xml +++ b/packages/SystemUI/res/values-ur-rPK/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"اسکرین شاٹ کیپچر کیا گیا۔"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"اپنے اسکرین شاٹ دیکھنے کیلئے چھوئیں۔"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"اسکرین شاٹ کیپچر نہیں کر سکے۔"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"اسکرین شاٹ محفوظ کرتے وقت مسئلہ پیش آ گیا۔"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"محدود اسٹوریج جگہ کی وجہ سے اسکرین شاٹس نہیں لئے جا سکتے۔"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے۔"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB فائل منتقل کرنیکے اختیارات"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"کام موڈ آن ہے۔"</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"کام موڈ آف ہو گیا۔"</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"کام موڈ آن ہو گیا۔"</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"ڈیٹا سیور آف ہو گیا۔"</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"ڈیٹا سرور آن ہو گیا۔"</string> <string name="accessibility_brightness" msgid="8003681285547803095">"ڈسپلے کی چمک"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G ڈیٹا موقوف کر دیا گیا"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G ڈیٹا موقوف کر دیا گیا"</string> diff --git a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml index 28987c37c693..4216e9e85d5e 100644 --- a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml +++ b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"PIP بند کریں"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"فُل اسکرین"</string> <string name="pip_play" msgid="674145557658227044">"چلائیں"</string> <string name="pip_pause" msgid="8412075640017218862">"موقوف کریں"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"PIP کنٹرول کرنے کیلئے "<b>"ہوم"</b>" پکڑے رکھیں"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"PIP کنٹرول کرنے کیلئے ہوم بٹن دبائیں اور پکڑے رکھیں"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"سمجھ آ گئی"</string> </resources> diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml index 0ad7df6b35e5..fb9a9e2856db 100644 --- a/packages/SystemUI/res/values-uz-rUZ/strings.xml +++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinshot saqlandi."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Ko‘rish uchun bu yerga bosing."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinshot saqlanmadi."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Skrinshotni saqlashda muammo yuz berdi."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Xotirada joy kamligi uchun skrinshotni saqlab bo‘lmadi."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan."</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl ko‘chirish moslamalari"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Ish rejimi yoniq."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Ish rejimi o‘chirib qo‘yildi."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Ishchi rejim yoqildi."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Trafik tejash rejimi o‘chirib qo‘yildi."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Trafik tejash rejimi yoqildi."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Ekran yorqinligi"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G internet to‘xtatib qo‘yildi"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G internet to‘xtatib qo‘yildi"</string> diff --git a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml index 00d259605370..d9db7d233b3d 100644 --- a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml +++ b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml @@ -19,15 +19,11 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Kadr ichida kadr – chiqish"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"To‘liq ekran"</string> <string name="pip_play" msgid="674145557658227044">"Ijro"</string> <string name="pip_pause" msgid="8412075640017218862">"Pauza"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> - <skip /> + <string name="pip_hold_home" msgid="340086535668778109">"“Kadr ichida kadr” rejimini boshqarish uchun "<b>"BOSHI"</b>" tugmasini bosib turing"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"“Kadr ichida kadr” rejimini boshqarish uchun BOSHIGA tugmasini bosib turing"</string> + <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 9a80cb2e1e7e..7427bda4a5f4 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Đã chụp ảnh màn hình."</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Chạm để xem ảnh chụp màn hình của bạn."</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Không thể chụp ảnh màn hình."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Đã gặp phải sự cố khi đang lưu ảnh chụp màn hình."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Tùy chọn truyền tệp USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Chế độ làm việc bật."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Chế độ làm việc đã tắt."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Chế độ làm việc đã bật."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Đã tắt Trình tiết kiệm dữ liệu."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Đã bật Trình tiết kiệm dữ liệu."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Độ sáng màn hình"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"Đã tạm dừng dữ liệu 2G-3G"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Đã tạm dừng dữ liệu 4G"</string> diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml index e4cbc485f0e2..727dcb89fae6 100644 --- a/packages/SystemUI/res/values-vi/strings_tv.xml +++ b/packages/SystemUI/res/values-vi/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"Đóng PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"Toàn màn hình"</string> <string name="pip_play" msgid="674145557658227044">"Phát"</string> <string name="pip_pause" msgid="8412075640017218862">"Tạm dừng"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"Giữ "<b>"HOME"</b>" để đ.khiển PIP"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 7f7108c821c7..74d787f58c7c 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -73,6 +73,8 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"已抓取屏幕截图。"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"触摸可查看您的屏幕截图。"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"无法抓取屏幕截图。"</string> + <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) --> + <skip /> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由于存储空间有限,无法保存屏幕截图。"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"此应用或贵单位不允许进行屏幕截图。"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB文件传输选项"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml index 2abd3387572d..87b62a03b1ea 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"关闭画中画"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"全屏"</string> <string name="pip_play" msgid="674145557658227044">"播放"</string> <string name="pip_pause" msgid="8412075640017218862">"暂停"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"按住"<b>"主屏幕"</b>"按钮即可控制画中画功能"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"知道了"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 13a668218ab0..602089e68e4c 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"已擷取螢幕畫面。"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"無法擷取螢幕畫面。"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"儲存螢幕擷圖時發生問題。"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"此應用程式或您的機構禁止擷取螢幕畫面。"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式已開啟。"</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"已關閉工作模式。"</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"已開啟工作模式。"</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"已關閉數據節省模式。"</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"已開啟數據節省模式。"</string> <string name="accessibility_brightness" msgid="8003681285547803095">"顯示光暗度"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"已暫停 2G-3G 數據"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"已暫停 4G 數據"</string> @@ -510,9 +509,9 @@ <string name="headset" msgid="4534219457597457353">"耳機"</string> <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已連接至耳機"</string> <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已連接至耳機"</string> - <string name="data_saver" msgid="5037565123367048522">"數據節省程式"</string> - <string name="accessibility_data_saver_on" msgid="8454111686783887148">"數據節省程式已開啟"</string> - <string name="accessibility_data_saver_off" msgid="8841582529453005337">"數據節省程式已關閉"</string> + <string name="data_saver" msgid="5037565123367048522">"數據節省模式"</string> + <string name="accessibility_data_saver_on" msgid="8454111686783887148">"數據節省模式已開啟"</string> + <string name="accessibility_data_saver_off" msgid="8841582529453005337">"數據節省模式已關閉"</string> <string name="switch_bar_on" msgid="1142437840752794229">"開啟"</string> <string name="switch_bar_off" msgid="8803270596930432874">"關閉"</string> <string name="nav_bar" msgid="1993221402773877607">"導覽列"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml index 8707d327dfb7..e419aa190da4 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"關閉 PIP"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"全螢幕"</string> <string name="pip_play" msgid="674145557658227044">"播放"</string> <string name="pip_pause" msgid="8412075640017218862">"暫停"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"按住"<b>"主按鈕"</b>"即可控制 PIP"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"知道了"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index e7172acd56ff..189f404d3ed8 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"已拍攝螢幕擷取畫面。"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"無法拍攝螢幕擷取畫面。"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"儲存螢幕擷圖時發生問題。"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"這個應用程式或貴機構禁止擷取螢幕畫面。"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml index 8707d327dfb7..94a83b939121 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml @@ -19,15 +19,12 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <!-- no translation found for pip_close (3480680679023423574) --> - <skip /> + <string name="pip_close" msgid="3480680679023423574">"關閉子母畫面"</string> <string name="pip_fullscreen" msgid="8604643018538487816">"全螢幕"</string> <string name="pip_play" msgid="674145557658227044">"播放"</string> <string name="pip_pause" msgid="8412075640017218862">"暫停"</string> - <!-- no translation found for pip_hold_home (340086535668778109) --> - <skip /> - <!-- no translation found for pip_onboarding_description (2627737116380318292) --> - <skip /> - <!-- no translation found for pip_onboarding_button (3957426748484904611) --> + <string name="pip_hold_home" msgid="340086535668778109">"按住「主畫面」"<b></b>"按鈕即可控制子母畫面"</string> + <!-- no translation found for pip_onboarding_description (2882896641362814195) --> <skip /> + <string name="pip_onboarding_button" msgid="3957426748484904611">"我知道了"</string> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 5868b2a474c3..60c4479bfb4c 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -73,6 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"Umfanekiso weskrini uqoshiwe"</string> <string name="screenshot_saved_text" msgid="1152839647677558815">"Thinta ukubona imifanekiso yakho yeskrini"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"Yehlulekile ukulondoloza umfanekiso weskrini."</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Inkinga ivelile ngenkathi ilondoloza isithombe sikrini."</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe."</string> <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho."</string> <string name="usb_preference_title" msgid="6551050377388882787">"Okukhethwa kokudluliswa kwefayela ye-USB"</string> @@ -220,10 +221,8 @@ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Imodi yomsebenzi ivuliwe."</string> <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Imodi yomsebenzi ivaliwe."</string> <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Imodi yomsebenzi ivuliwe."</string> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_off (650231949881093289) --> - <skip /> - <!-- no translation found for accessibility_quick_settings_data_saver_changed_on (4218725402373934151) --> - <skip /> + <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Iseva yedatha ivaliwe."</string> + <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Iseva yedatha ivuliwe."</string> <string name="accessibility_brightness" msgid="8003681285547803095">"Bonisa ukukhanya"</string> <string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G-3G idatha imisiwe"</string> <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4G idatha imisiwe"</string> diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml index b901f906b583..b0105560d877 100644 --- a/packages/SystemUI/res/values-zu/strings_tv.xml +++ b/packages/SystemUI/res/values-zu/strings_tv.xml @@ -24,6 +24,6 @@ <string name="pip_play" msgid="674145557658227044">"Dlala"</string> <string name="pip_pause" msgid="8412075640017218862">"Misa isikhashana"</string> <string name="pip_hold_home" msgid="340086535668778109">"Bamba "<b>"IKHAYA"</b>" ukuze ulawule i-PIP"</string> - <string name="pip_onboarding_description" msgid="2627737116380318292">"Cindezela uphinde ubambe inkinobho YASEKHAYA\nukuze ulawule i-PIP"</string> + <string name="pip_onboarding_description" msgid="2882896641362814195">"Cindezela futhi ubambe inkinobho EKHAYA ukuze ulawule i-PIP"</string> <string name="pip_onboarding_button" msgid="3957426748484904611">"Ngiyezwa"</string> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index d65ab04b110f..eeed0cf62287 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -155,6 +155,8 @@ <color name="default_remote_input_background">@*android:color/notification_default_color</color> <color name="remote_input_hint">#4dffffff</color> + <color name="remote_input_accent">#eeeeee</color> + <color name="qs_tile_tint_unavailable">#40ffffff</color> <color name="qs_tile_tint_inactive">#4dffffff</color> <color name="qs_tile_tint_active">#ffffffff</color> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index e50f975c873f..6a9f45606bab 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -178,7 +178,7 @@ <dimen name="qs_date_alarm_anim_translation">22dp</dimen> <dimen name="qs_date_collapsed_text_size">14sp</dimen> <dimen name="qs_date_text_size">16sp</dimen> - <dimen name="qs_header_gear_translation">150dp</dimen> + <dimen name="qs_header_gear_translation">16dp</dimen> <dimen name="qs_page_indicator_size">12dp</dimen> <dimen name="qs_tile_icon_size">24dp</dimen> <dimen name="qs_tile_text_size">12sp</dimen> diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml index b5891107297e..6b153d1117ea 100644 --- a/packages/SystemUI/res/values/dimens_tv.xml +++ b/packages/SystemUI/res/values/dimens_tv.xml @@ -19,7 +19,7 @@ <resources> <!-- Dimens for recents card in the recents view on tv --> <dimen name="recents_tv_card_width">268dip</dimen> - <dimen name="recents_tv_card_height">151dip</dimen> + <dimen name="recents_tv_screenshot_height">151dip</dimen> <dimen name="recents_tv_card_extra_badge_size">20dip</dimen> <dimen name="recents_tv_banner_width">114dip</dimen> <dimen name="recents_tv_banner_height">64dip</dimen> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 8af413c4816c..5295ccb77012 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -715,7 +715,9 @@ <string name="quick_settings_work_mode_label">Work mode</string> <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] --> - <string name="recents_empty_message">Your recent screens appear here</string> + <string name="recents_empty_message">No recent items</string> + <!-- Recents: The empty recents string after dismissing all tasks. [CHAR LIMIT=NONE] --> + <string name="recents_empty_message_dismissed_all">You\'ve cleared everything</string> <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] --> <string name="recents_app_info_button_label">Application Info</string> <!-- Recents: The screen pinning button. [CHAR LIMIT=NONE] --> @@ -1184,11 +1186,6 @@ <!-- Option to use new paging layout in quick settings [CHAR LIMIT=60] --> <string name="qs_paging" translatable="false">Use the new Quick Settings</string> - <!-- Disables fast-toggling recents via the recents button. DO NOT TRANSLATE --> - <string name="overview_disable_fast_toggle_via_button">Disable fast toggle</string> - <!-- Description for the toggle for fast-toggling recents via the recents button. DO NOT TRANSLATE --> - <string name="overview_disable_fast_toggle_via_button_desc">Disable launch timeout while paging</string> - <!-- Toggle to enable the gesture to enter split-screen by swiping up from the Overview button. [CHAR LIMIT=60]--> <string name="overview_nav_bar_gesture">Enable split-screen swipe-up gesture</string> <!-- Description for the toggle to enable the gesture to enter split-screen by swiping up from the Overview button. [CHAR LIMIT=NONE]--> @@ -1435,6 +1432,9 @@ <!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] --> <string name="drag_to_add_tiles">Drag to add tiles</string> + <!-- Label for area where tiles can be dragged in to [CHAR LIMIT=60] --> + <string name="drag_to_remove_tiles">Drag here to remove</string> + <!-- Button to edit the tile ordering of quick settings [CHAR LIMIT=60] --> <string name="qs_edit">Edit</string> diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml index b35038d0776c..0e1fe8fa3384 100644 --- a/packages/SystemUI/res/values/strings_tv.xml +++ b/packages/SystemUI/res/values/strings_tv.xml @@ -27,13 +27,12 @@ <string name="pip_play">Play</string> <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=16] --> <string name="pip_pause">Pause</string> - <!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=25] --> + <!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=52] --> <string name="pip_hold_home">Hold <b>HOME</b> to control PIP</string> <!-- Picture-in-Picture (PIP) onboarding screen --> <eat-comment /> - <!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP. - Line break is needed as if we have CHAR LIMIT=25. [CHAR LIMIT=NONE] --> - <string name="pip_onboarding_description">Press and hold the HOME\nbutton to control PIP</string> + <!-- Description for picture-in-picture (PIP) onboarding screen to indicate that longpress HOME key to control PIP. [CHAR LIMIT=NONE] --> + <string name="pip_onboarding_description">Press and hold the HOME button to control PIP</string> <!-- Button to close picture-in-picture (PIP) onboarding screen. --> <string name="pip_onboarding_button">Got it</string> <!-- Font for Recents --> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 2660926aa38b..b0c1e951f7db 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -201,8 +201,8 @@ <item name="android:colorControlActivated">@color/system_accent_color</item> </style> - <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault"> - <item name="android:colorControlActivated">@android:color/white</item> + <style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light"> + <item name="android:colorAccent">@color/remote_input_accent</item> </style> <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog"> diff --git a/packages/SystemUI/res/values/values_tv.xml b/packages/SystemUI/res/values/values_tv.xml index 1fcc9e4a9d7e..6a72e542482b 100644 --- a/packages/SystemUI/res/values/values_tv.xml +++ b/packages/SystemUI/res/values/values_tv.xml @@ -15,4 +15,5 @@ limitations under the License. --> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <item format="float" type="integer" name="unselected_scale">1.0</item> + <item format="float" type="integer" name="selected_scale">1.1</item> </resources> diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml index ddc03a39d3a7..a130cf9009a9 100644 --- a/packages/SystemUI/res/xml/tuner_prefs.xml +++ b/packages/SystemUI/res/xml/tuner_prefs.xml @@ -138,11 +138,6 @@ android:title="@string/other" > <com.android.systemui.tuner.TunerSwitch - android:key="overview_disable_fast_toggle_via_button" - android:title="@string/overview_disable_fast_toggle_via_button" - android:summary="@string/overview_disable_fast_toggle_via_button_desc" /> - - <com.android.systemui.tuner.TunerSwitch android:key="overview_nav_bar_gesture" android:title="@string/overview_nav_bar_gesture" android:summary="@string/overview_nav_bar_gesture_desc" /> diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java index 358674c809a3..aa3f6e5fe4a3 100644 --- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java @@ -535,31 +535,43 @@ public class ExpandHelper implements Gefingerpoken { boolean nowExpanded; int naturalHeight = mScaler.getNaturalHeight(); if (wasClosed) { - nowExpanded = (force || currentHeight > mOldHeight); + nowExpanded = (force || currentHeight > mOldHeight && velocity >= 0); } else { - nowExpanded = !force && currentHeight >= mOldHeight; + nowExpanded = !force && (currentHeight >= mOldHeight || velocity > 0); } nowExpanded |= mNaturalHeight == mSmallSize; if (mScaleAnimation.isRunning()) { mScaleAnimation.cancel(); } - mCallback.setUserExpandedChild(mResizedView, nowExpanded); mCallback.expansionStateChanged(false); float targetHeight = nowExpanded ? naturalHeight : mSmallSize; if (targetHeight != currentHeight) { mScaleAnimation.setFloatValues(targetHeight); mScaleAnimation.setupStartValues(); final View scaledView = mResizedView; + final boolean expand = nowExpanded; mScaleAnimation.addListener(new AnimatorListenerAdapter() { + public boolean mCancelled; + @Override public void onAnimationEnd(Animator animation) { + if (!mCancelled) { + mCallback.setUserExpandedChild(scaledView, expand); + } mCallback.setUserLockedChild(scaledView, false); mScaleAnimation.removeListener(this); } + + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } }); + velocity = nowExpanded == velocity >= 0 ? velocity : 0; mFlingAnimationUtils.apply(mScaleAnimation, currentHeight, targetHeight, velocity); mScaleAnimation.start(); } else { + mCallback.setUserExpandedChild(mResizedView, nowExpanded); mCallback.setUserLockedChild(mResizedView, false); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java index 937f7d319432..0d822cba1070 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java @@ -166,7 +166,9 @@ public class FalsingManager implements SensorEventListener { */ public boolean isFalseTouch() { if (FalsingLog.ENABLED) { - if (!mSessionActive) { + // We're getting some false wtfs from touches that happen after the device went + // to sleep. Only report missing sessions that happen when the device is interactive. + if (!mSessionActive && mContext.getSystemService(PowerManager.class).isInteractive()) { FalsingLog.wtf("isFalseTouch", new StringBuilder() .append("Session is not active, yet there's a query for a false touch.") .append(" enabled=").append(isEnabled() ? 1 : 0) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 312d3c5dc650..02b860c493cd 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -811,7 +811,7 @@ public class KeyguardViewMediator extends SystemUI { intent.putExtra("seq", mDelayedShowingSequence); PendingIntent sender = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender); + mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, sender); if (DEBUG) Log.d(TAG, "setting alarm to turn off keyguard, seq = " + mDelayedShowingSequence); doKeyguardLaterForChildProfilesLocked(); @@ -828,7 +828,8 @@ public class KeyguardViewMediator extends SystemUI { lockIntent.putExtra(Intent.EXTRA_USER_ID, info.id); PendingIntent lockSender = PendingIntent.getBroadcast( mContext, 0, lockIntent, PendingIntent.FLAG_CANCEL_CURRENT); - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, userWhen, lockSender); + mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, + userWhen, lockSender); } } } @@ -1542,13 +1543,22 @@ public class KeyguardViewMediator extends SystemUI { try { mStatusBarKeyguardViewManager.keyguardGoingAway(); + int flags = 0; + if (mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock() + || mWakeAndUnlocking) { + flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; + } + if (mStatusBarKeyguardViewManager.isGoingToNotificationShade()) { + flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; + } + if (mStatusBarKeyguardViewManager.isUnlockWithWallpaper()) { + flags |= WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; + } + // Don't actually hide the Keyguard at the moment, wait for window // manager until it tells us it's safe to do so with // startKeyguardExitAnimation. - ActivityManagerNative.getDefault().keyguardGoingAway( - mStatusBarKeyguardViewManager.shouldDisableWindowAnimationsForUnlock() - || mWakeAndUnlocking, - mStatusBarKeyguardViewManager.isGoingToNotificationShade()); + ActivityManagerNative.getDefault().keyguardGoingAway(flags); } catch (RemoteException e) { Log.e(TAG, "Error while calling WindowManager", e); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index f601f908be2f..815c6797e0dd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -41,6 +41,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows"; public static final float EXPANDED_TILE_DELAY = .7f; + private static final float LAST_ROW_EXPANDED_DELAY = .84f; private final ArrayList<View> mAllViews = new ArrayList<>(); private final ArrayList<View> mTopFiveQs = new ArrayList<>(); @@ -56,6 +57,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private TouchAnimator mTranslationXAnimator; private TouchAnimator mTranslationYAnimator; private TouchAnimator mNonfirstPageAnimator; + private TouchAnimator mLastRowAnimator; private boolean mOnKeyguard; @@ -87,6 +89,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha public void setHost(QSTileHost qsh) { qsh.addCallback(this); + updateAnimators(); } @Override @@ -129,20 +132,21 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha TouchAnimator.Builder firstPageBuilder = new Builder(); TouchAnimator.Builder translationXBuilder = new Builder(); TouchAnimator.Builder translationYBuilder = new Builder(); - TouchAnimator.Builder firstPageDelayedBuilder = new Builder(); + TouchAnimator.Builder lastRowBuilder = new Builder(); + + if (mQsPanel.getHost() == null) return; Collection<QSTile<?>> tiles = mQsPanel.getHost().getTiles(); int count = 0; int[] loc1 = new int[2]; int[] loc2 = new int[2]; int lastYDiff = 0; - firstPageDelayedBuilder.setStartDelay(EXPANDED_TILE_DELAY); - firstPageBuilder.setListener(this); - // Fade in the tiles/labels as we reach the final position. - firstPageDelayedBuilder.addFloat(mQsPanel.getTileLayout(), "alpha", 0, 1); + clearAnimationState(); mAllViews.clear(); mTopFiveQs.clear(); + mAllViews.add((View) mQsPanel.getTileLayout()); + for (QSTile<?> tile : tiles) { QSTileBaseView tileView = mQsPanel.getTileView(tile); final TextView label = ((QSTileView) tileView).getLabel(); @@ -171,22 +175,30 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha mTopFiveQs.add(tileIcon); mAllViews.add(tileIcon); - mAllViews.add(label); mAllViews.add(quickTileView); } else if (mFullRows && isIconInAnimatedRow(count)) { firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0); translationYBuilder.addFloat(label, "translationY", -lastYDiff, 0); translationYBuilder.addFloat(tileIcon, "translationY", -lastYDiff, 0); mAllViews.add(tileIcon); - mAllViews.add(label); + } else { + lastRowBuilder.addFloat(tileView, "alpha", 0, 1); } mAllViews.add(tileView); mAllViews.add(label); count++; } if (mAllowFancy) { - mFirstPageAnimator = firstPageBuilder.build(); - mFirstPageDelayedAnimator = firstPageDelayedBuilder.build(); + mFirstPageAnimator = firstPageBuilder + .setListener(this) + .build(); + // Fade in the tiles/labels as we reach the final position. + mFirstPageDelayedAnimator = new TouchAnimator.Builder() + .setStartDelay(EXPANDED_TILE_DELAY) + .addFloat(mQsPanel.getTileLayout(), "alpha", 0, 1).build(); + mLastRowAnimator = lastRowBuilder + .setStartDelay(LAST_ROW_EXPANDED_DELAY) + .build(); Path path = new Path(); path.moveTo(0, 0); path.cubicTo(0, 0, 0, 1, 1, 1); @@ -235,6 +247,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha mFirstPageDelayedAnimator.setPosition(position); mTranslationXAnimator.setPosition(position); mTranslationYAnimator.setPosition(position); + mLastRowAnimator.setPosition(position); } else { mNonfirstPageAnimator.setPosition(position); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index d0e034bc4890..ab901795f425 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -26,6 +26,8 @@ import android.widget.Space; import com.android.systemui.R; import com.android.systemui.qs.QSTile.SignalState; import com.android.systemui.qs.QSTile.State; +import com.android.systemui.qs.customize.QSCustomizer; +import com.android.systemui.statusbar.phone.QSTileHost; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; @@ -95,9 +97,17 @@ public class QuickQSPanel extends QSPanel { return new QSTileBaseView(mContext, tile.createTileView(mContext)); } + @Override + public void setHost(QSTileHost host, QSCustomizer customizer) { + super.setHost(host, customizer); + setTiles(mHost.getTiles()); + } + public void setMaxTiles(int maxTiles) { mMaxTiles = maxTiles; - setTiles(mHost.getTiles()); + if (mHost != null) { + setTiles(mHost.getTiles()); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index 72a59d7c16b1..aeca8401633a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -128,6 +128,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene public void hide(int x, int y) { if (isShown) { isShown = false; + mToolbar.dismissPopupMenus(); setCustomizing(false); save(); mClipper.animateCircularClip(x, y, false, mCollapseAnimationListener); diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index d9b3b3f6ed4c..57db3a6acba2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -28,6 +28,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import android.widget.TextView; import com.android.systemui.R; import com.android.systemui.qs.QSIconView; import com.android.systemui.qs.QSTileView; @@ -153,7 +154,12 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta @Override public void onBindViewHolder(final Holder holder, int position) { - if (holder.getItemViewType() == TYPE_EDIT) return; + if (holder.getItemViewType() == TYPE_EDIT) { + ((TextView) holder.itemView.findViewById(android.R.id.title)).setText( + mCurrentDrag != null ? R.string.drag_to_remove_tiles + : R.string.drag_to_add_tiles); + return; + } TileInfo info = mTiles.get(position); holder.mTileView.onStateChanged(info.state); @@ -250,11 +256,13 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta super.onSelectedChanged(viewHolder, actionState); if (mCurrentDrag != null) { mCurrentDrag.stopDrag(); + mCurrentDrag = null; } if (viewHolder != null) { mCurrentDrag = (Holder) viewHolder; mCurrentDrag.startDrag(); } + notifyItemChanged(mDividerIndex); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 473956fbe4d7..f33ef654eaf7 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -26,6 +26,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; @@ -361,7 +362,8 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD RecentsConfiguration config = Recents.getConfiguration(); RecentsActivityLaunchState launchState = config.getLaunchState(); if (!loadPlan.hasTasks()) { - loader.preloadTasks(loadPlan, -1, launchState.launchedFromHome); + loader.preloadTasks(loadPlan, launchState.launchedToTaskId, + launchState.launchedFromHome); } RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options(); @@ -434,6 +436,13 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD } @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + EventBus.getDefault().send(new ConfigurationChangedEvent()); + } + + @Override protected void onStop() { super.onStop(); @@ -740,7 +749,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD public final void onBusEvent(AllTaskViewsDismissedEvent event) { SystemServicesProxy ssp = Recents.getSystemServices(); if (ssp.hasDockedTask()) { - mRecentsView.showEmptyView(); + mRecentsView.showEmptyView(R.string.recents_empty_message_dismissed_all); } else { // Just go straight home (no animation necessary because there are no more task views) dismissRecentsToHome(false /* animateTaskViews */); diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java index 6feda81bc60a..40bf6d3d2447 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java @@ -41,6 +41,8 @@ public class RecentsDebugFlags implements TunerService.Tunable { public static final boolean EnableHistory = false; // Overrides the Tuner flags and enables the timeout private static final boolean EnableFastToggleTimeout = false; + // Overrides the Tuner flags and enables the paging via the Recents button + private static final boolean EnablePaging = false; // Enables us to create mock recents tasks public static final boolean EnableMockTasks = false; @@ -54,10 +56,6 @@ public class RecentsDebugFlags implements TunerService.Tunable { public static final int MockTaskGroupsTaskCount = 12; } - private static final String KEY_ENABLE_PAGING = "overview_enable_paging"; - - private boolean mEnablePaging; - /** * We read the prefs once when we start the activity, then update them as the tuner changes * the flags. @@ -65,7 +63,6 @@ public class RecentsDebugFlags implements TunerService.Tunable { public RecentsDebugFlags(Context context) { // Register all our flags, this will also call onTuningChanged() for each key, which will // initialize the current state of each flag - TunerService.get(context).addTunable(this, KEY_ENABLE_PAGING); } /** @@ -83,16 +80,11 @@ public class RecentsDebugFlags implements TunerService.Tunable { * @return whether we are enabling paging. */ public boolean isPagingEnabled() { - return mEnablePaging; + return Static.EnablePaging; } @Override public void onTuningChanged(String key, String newValue) { - switch (key) { - case KEY_ENABLE_PAGING: - mEnablePaging = (newValue != null) && (Integer.parseInt(newValue) != 0); - break; - } EventBus.getDefault().send(new DebugFlagsChangedEvent()); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index d864df8331e1..9be24def0da4 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -66,6 +66,7 @@ import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskGrouping; import com.android.systemui.recents.model.TaskStack; +import com.android.systemui.recents.tv.views.TaskCardView; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm; import com.android.systemui.recents.views.TaskStackView; import com.android.systemui.recents.views.TaskStackViewScroller; @@ -166,6 +167,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener boolean mCanReuseTaskStackViews = true; boolean mDraggingInRecents; boolean mLaunchedWhileDocking; + private boolean mIsRunningOnTv; // Task launching Rect mSearchBarBounds = new Rect(); @@ -230,8 +232,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE); if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) { mRecentsIntentActivityName = RECENTS_TV_ACTIVITY; + mIsRunningOnTv = true; } else { mRecentsIntentActivityName = RECENTS_ACTIVITY; + mIsRunningOnTv = false; } } @@ -793,6 +797,22 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } } + /** + * Creates the activity options for an app->recents transition on TV. + */ + private ActivityOptions getThumbnailTransitionActivityOptionsForTV( + ActivityManager.RunningTaskInfo topTask) { + Bitmap thumbnail = mThumbnailTransitionBitmapCache; + Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext); + if (thumbnail != null) { + return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, + null, (int) rect.left, (int) rect.top, + (int) rect.width(), (int) rect.height(), mHandler, null); + } + // If both the screenshot and thumbnail fails, then just fall back to the default transition + return getUnknownTransitionActivityOptions(); + } + private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask, TaskViewTransform toTransform) { Bitmap thumbnail; @@ -872,6 +892,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener boolean isTopTaskHome, boolean animate) { RecentsTaskLoader loader = Recents.getTaskLoader(); + // If we are on TV, divert to a different helper method + if (mIsRunningOnTv) { + setUpAndStartTvRecents(topTask, isTopTaskHome, animate); + return; + } // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we // should always preload the tasks now. If we are dragging in recents, reload them as // the stacks might have changed. @@ -947,6 +972,90 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } /** + * Used to set up the animations of Tv Recents, then start the Recents Activity. + * TODO: Add the Transitions for Home -> Recents TV + * TODO: Shift Transition code to separate class under /tv directory and access + * from here + */ + private void setUpAndStartTvRecents(ActivityManager.RunningTaskInfo topTask, + boolean isTopTaskHome, boolean animate) { + RecentsTaskLoader loader = Recents.getTaskLoader(); + + // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we + // should always preload the tasks now. If we are dragging in recents, reload them as + // the stacks might have changed. + if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) { + // Create a new load plan if preloadRecents() was never triggered + sInstanceLoadPlan = loader.createLoadPlan(mContext); + } + if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) { + loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome); + } + TaskStack stack = sInstanceLoadPlan.getTaskStack(); + + // Update the header bar if necessary + updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack); + + // Prepare the dummy stack for the transition + TaskStackLayoutAlgorithm.VisibilityReport stackVr = + mDummyStackView.computeStackVisibilityReport(); + + if (!animate) { + ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1); + startRecentsActivity(topTask, opts, false /* fromHome */, + false /* fromSearchHome */, false /* fromThumbnail*/, stackVr); + return; + } + + boolean hasRecentTasks = stack.getTaskCount() > 0; + boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks; + + if (useThumbnailTransition) { + // Try starting with a thumbnail transition + ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask); + if (opts != null) { + startRecentsActivity(topTask, opts, false /* fromHome */, + false /* fromSearchHome */, true /* fromThumbnail */, stackVr); + } else { + // Fall through below to the non-thumbnail transition + useThumbnailTransition = false; + } + } + + if (!useThumbnailTransition) { + // If there is no thumbnail transition, but is launching from home into recents, then + // use a quick home transition and do the animation from home + if (hasRecentTasks) { + SystemServicesProxy ssp = Recents.getSystemServices(); + String homeActivityPackage = ssp.getHomeActivityPackageName(); + String searchWidgetPackage = null; + if (RecentsDebugFlags.Static.EnableSearchBar) { + searchWidgetPackage = Prefs.getString(mContext, + Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null); + } else { + AppWidgetProviderInfo searchWidgetInfo = ssp.resolveSearchAppWidget(); + if (searchWidgetInfo != null) { + searchWidgetPackage = searchWidgetInfo.provider.getPackageName(); + } + } + + // Determine whether we are coming from a search owned home activity + boolean fromSearchHome = (homeActivityPackage != null) && + homeActivityPackage.equals(searchWidgetPackage); + ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome); + startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome, + false /* fromThumbnail */, stackVr); + } else { + // Otherwise we do the normal fade from an unknown source + ActivityOptions opts = getUnknownTransitionActivityOptions(); + startRecentsActivity(topTask, opts, true /* fromHome */, + false /* fromSearchHome */, false /* fromThumbnail */, stackVr); + } + } + mLastToggleTime = SystemClock.elapsedRealtime(); + } + + /** * Starts the recents activity. */ private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask, diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java index 5e1af1280400..ee4d95e2bf55 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -268,6 +268,14 @@ public class RecentsTaskLoader { BitmapDrawable mDefaultIcon; Bitmap mDefaultThumbnail; + private TaskKeyLruCache.EvictionCallback mClearActivityInfoOnEviction = + new TaskKeyLruCache.EvictionCallback() { + @Override + public void onEntryEvicted(Task.TaskKey key) { + mActivityInfoCache.remove(key.getComponent()); + } + }; + public RecentsTaskLoader(Context context) { Resources res = context.getResources(); mDefaultTaskBarBackgroundColor = @@ -292,10 +300,11 @@ public class RecentsTaskLoader { // Initialize the proxy, cache and loaders int numRecentTasks = ActivityManager.getMaxRecentTasksStatic(); mLoadQueue = new TaskResourceLoadQueue(); - mIconCache = new TaskKeyLruCache<>(iconCacheSize); + mIconCache = new TaskKeyLruCache<>(iconCacheSize, mClearActivityInfoOnEviction); mThumbnailCache = new TaskKeyLruCache<>(thumbnailCacheSize); - mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks); - mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks); + mActivityLabelCache = new TaskKeyLruCache<>(numRecentTasks, mClearActivityInfoOnEviction); + mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks, + mClearActivityInfoOnEviction); mActivityInfoCache = new LruCache(numRecentTasks); mLoader = new BackgroundTaskLoader(mLoadQueue, mIconCache, mThumbnailCache, mDefaultThumbnail, mDefaultIcon); @@ -375,7 +384,6 @@ public class RecentsTaskLoader { mIconCache.remove(t.key); mActivityLabelCache.remove(t.key); mContentDescriptionCache.remove(t.key); - mActivityInfoCache.remove(t.key.getComponent()); if (notifyTaskDataUnloaded) { t.notifyTaskDataUnloaded(null, mDefaultIcon); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java index d433b6c00269..748d8ed75040 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyLruCache.java @@ -30,16 +30,29 @@ import android.util.SparseArray; */ public class TaskKeyLruCache<V> { + public interface EvictionCallback { + public void onEntryEvicted(Task.TaskKey key); + } + private static final String TAG = "TaskKeyLruCache"; private final SparseArray<Task.TaskKey> mKeys = new SparseArray<>(); private final LruCache<Integer, V> mCache; + private final EvictionCallback mEvictionCallback; public TaskKeyLruCache(int cacheSize) { + this(cacheSize, null); + } + + public TaskKeyLruCache(int cacheSize, EvictionCallback evictionCallback) { + mEvictionCallback = evictionCallback; mCache = new LruCache<Integer, V>(cacheSize) { @Override protected void entryRemoved(boolean evicted, Integer taskId, V oldV, V newV) { + if (mEvictionCallback != null) { + mEvictionCallback.onEntryEvicted(mKeys.get(taskId)); + } mKeys.remove(taskId); } }; @@ -84,8 +97,9 @@ public class TaskKeyLruCache<V> { /** Removes a cache entry for a specific key. */ final void remove(Task.TaskKey key) { - mKeys.remove(key.id); + // Remove the key after the cache value because we need it to make the callback mCache.remove(key.id); + mKeys.remove(key.id); } /** Removes all the entries in the cache. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java index 48a1904c03b1..365b29d67676 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java @@ -29,6 +29,7 @@ import com.android.systemui.R; public class ViewFocusAnimator implements View.OnFocusChangeListener { private final float mUnselectedScale; + private final float mSelectedScale; private final float mSelectedScaleDelta; private final float mUnselectedZ; private final float mSelectedZDelta; @@ -49,8 +50,9 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener { TypedValue out = new TypedValue(); res.getValue(R.integer.unselected_scale, out, true); mUnselectedScale = out.getFloat(); - mSelectedScaleDelta = res.getFraction(R.fraction.lb_focus_zoom_factor_medium, 1, 1) - - mUnselectedScale; + res.getValue(R.integer.selected_scale, out, true); + mSelectedScale = out.getFloat(); + mSelectedScaleDelta = mSelectedScale - mUnselectedScale; mUnselectedZ = res.getDimensionPixelOffset(R.dimen.recents_tv_unselected_item_z); mSelectedZDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_selected_item_z_delta); diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java index ef8d48e7f2cf..bd3143f688cc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java @@ -16,10 +16,8 @@ package com.android.systemui.recents.tv.views; import android.annotation.Nullable; -import android.app.ActivityManager; import android.app.ActivityOptions; import android.content.Context; -import android.graphics.Bitmap; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; @@ -121,10 +119,10 @@ public class RecentsTvTransitionHelper { }; } try { - Rect taskRect = taskView.getGlobalRect(); + Rect taskRect = taskView.getFocusedThumbnailRect(); WindowManagerGlobal.getWindowManagerService() - .overridePendingAppTransitionThumb(task.thumbnail, taskRect.left, - taskRect.top, callback, true); + .overridePendingAppTransitionAspectScaledThumb(task.thumbnail, taskRect.left, + taskRect.top, taskRect.width(), taskRect.height(), callback, true); } catch (RemoteException e) { Log.w(TAG, "Failed to override transition: " + e); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java index 7d8a3ce32f45..5775b60ab308 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java @@ -16,8 +16,13 @@ package com.android.systemui.recents.tv.views; import android.content.Context; +import android.content.res.Resources; +import android.graphics.Point; import android.graphics.Rect; import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Display; +import android.view.WindowManager; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -71,15 +76,46 @@ public class TaskCardView extends LinearLayout { mThumbnailView.getFocusedRect(r); } - public Rect getFocusedRect() { + public Rect getFocusedThumbnailRect() { Rect r = new Rect(); - getFocusedRect(r); + mThumbnailView.getGlobalVisibleRect(r); + TypedValue out = new TypedValue(); + getContext().getResources().getValue(R.integer.selected_scale, out, true); + float deltaScale = (out.getFloat() - 1.0f) / 2; + r.set((int) (r.left - r.left * deltaScale), + (int) (r.top - r.top * deltaScale), + (int) (r.right + r.right * deltaScale), + (int) (r.bottom + r.bottom * deltaScale)); return r; } - public Rect getGlobalRect() { - Rect r = new Rect(); - getGlobalVisibleRect(r); - return r; + public static Rect getStartingCardThumbnailRect(Context context) { + Resources res = context.getResources(); + + TypedValue out = new TypedValue(); + res.getValue(R.integer.selected_scale, out, true); + float scale = out.getFloat(); + + int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width); + int widthDelta = (int) (width * scale - width); + int height = (int) (res.getDimensionPixelOffset( + R.dimen.recents_tv_screenshot_height) * scale); + int padding = res.getDimensionPixelOffset(R.dimen.recents_tv_grid_row_padding); + + int headerHeight = (int) ((res.getDimensionPixelOffset( + R.dimen.recents_tv_card_extra_badge_size) + + res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom)) * scale); + + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + Point size = new Point(); + display.getSize(size); + int screenWidth = size.x; + int screenHeight = size.y; + + return new Rect(screenWidth - width - padding - widthDelta / 2, + screenHeight / 2 - height / 2 + headerHeight / 2, + screenWidth - padding + widthDelta / 2, + screenHeight / 2 + height / 2 + headerHeight / 2); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 8342de547720..92356736763e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -97,7 +97,7 @@ public class RecentsView extends FrameLayout { private RecentsAppWidgetHostView mSearchBar; private TextView mHistoryButton; private TextView mHistoryClearAllButton; - private View mEmptyView; + private TextView mEmptyView; private RecentsHistoryView mHistoryView; private boolean mAwaitingFirstLayout = true; @@ -159,7 +159,7 @@ public class RecentsView extends FrameLayout { } }); } - mEmptyView = inflater.inflate(R.layout.recents_empty, this, false); + mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false); addView(mEmptyView); setBackground(mBackgroundScrim); @@ -206,7 +206,7 @@ public class RecentsView extends FrameLayout { if (stack.getTaskCount() > 0) { hideEmptyView(); } else { - showEmptyView(); + showEmptyView(R.string.recents_empty_message); } } @@ -327,11 +327,12 @@ public class RecentsView extends FrameLayout { /** * Hides the task stack and shows the empty view. */ - public void showEmptyView() { + public void showEmptyView(int msgResId) { if (RecentsDebugFlags.Static.EnableSearchBar && (mSearchBar != null)) { mSearchBar.setVisibility(View.INVISIBLE); } mTaskStackView.setVisibility(View.INVISIBLE); + mEmptyView.setText(msgResId); mEmptyView.setVisibility(View.VISIBLE); mEmptyView.bringToFront(); if (RecentsDebugFlags.Static.EnableHistory) { @@ -400,8 +401,8 @@ public class RecentsView extends FrameLayout { // Measure the empty view to the full size of the screen if (mEmptyView.getVisibility() != GONE) { - measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), + MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); } if (RecentsDebugFlags.Static.EnableHistory) { @@ -449,7 +450,13 @@ public class RecentsView extends FrameLayout { // Layout the empty view if (mEmptyView.getVisibility() != GONE) { - mEmptyView.layout(left, top, right, bottom); + int leftRightInsets = mSystemInsets.left + mSystemInsets.right; + int topBottomInsets = mSystemInsets.top + mSystemInsets.bottom; + int childWidth = mEmptyView.getMeasuredWidth(); + int childHeight = mEmptyView.getMeasuredHeight(); + int childLeft = left + Math.max(0, (right - left - leftRightInsets - childWidth)) / 2; + int childTop = top + Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2; + mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight); } if (RecentsDebugFlags.Static.EnableHistory) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 6c410c3981c6..93b5b6c12904 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -61,6 +61,7 @@ import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimati import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent; import com.android.systemui.recents.events.activity.HideHistoryButtonEvent; import com.android.systemui.recents.events.activity.HideHistoryEvent; +import com.android.systemui.recents.events.activity.HideRecentsEvent; import com.android.systemui.recents.events.activity.IterateRecentsEvent; import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent; import com.android.systemui.recents.events.activity.LaunchTaskEvent; @@ -113,6 +114,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal private static final int DRAG_SCALE_DURATION = 175; private static final float DRAG_SCALE_FACTOR = 1.05f; + private static final int LAUNCH_NEXT_SCROLL_BASE_DURATION = 200; + private static final int LAUNCH_NEXT_SCROLL_INCR_DURATION = 32; + private static final ArraySet<Task.TaskKey> EMPTY_TASK_SET = new ArraySet<>(); LayoutInflater mInflater; @@ -1618,12 +1622,34 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mUIDozeTrigger.stopDozing(); cancelAllTaskViewAnimations(); - Task launchTask = mStack.getStackTasks().get(launchTaskIndex); - EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask), - launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */)); + final Task launchTask = mStack.getStackTasks().get(launchTaskIndex); + if (getChildViewForTask(launchTask) == null) { + List<TaskView> taskViews = getTaskViews(); + int lastTaskIndex = !taskViews.isEmpty() + ? mStack.indexOfStackTask(taskViews.get(taskViews.size() - 1).getTask()) + : mStack.getTaskCount() - 1; + int duration = LAUNCH_NEXT_SCROLL_BASE_DURATION + + Math.abs(mStack.indexOfStackTask(launchTask) - lastTaskIndex) + * LAUNCH_NEXT_SCROLL_INCR_DURATION; + mStackScroller.animateScroll(mLayoutAlgorithm.getStackScrollForTask(launchTask), + duration, new Runnable() { + @Override + public void run() { + EventBus.getDefault().send(new LaunchTaskEvent( + getChildViewForTask(launchTask), launchTask, null, + INVALID_STACK_ID, false /* screenPinningRequested */)); + } + }); + } else { + EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask), + launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */)); + } MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK, launchTask.key.getComponent().toString()); + } else if (mStack.getTaskCount() == 0) { + // If there are no tasks, then just hide recents back to home. + EventBus.getDefault().send(new HideRecentsEvent(false, true)); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java index ad46abd74f7d..9be3542bf59e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java @@ -179,6 +179,13 @@ public class TaskStackViewScroller { /** Animates the stack scroll */ void animateScroll(float newScroll, final Runnable postRunnable) { + int duration = mContext.getResources().getInteger( + R.integer.recents_animate_task_stack_scroll_duration); + animateScroll(newScroll, duration, postRunnable); + } + + /** Animates the stack scroll */ + void animateScroll(float newScroll, int duration, final Runnable postRunnable) { // Finish any current scrolling animations if (mScrollAnimator != null && mScrollAnimator.isRunning()) { setStackScroll(mFinalAnimatedScroll); @@ -190,8 +197,7 @@ public class TaskStackViewScroller { if (Float.compare(mStackScrollP, newScroll) != 0) { mFinalAnimatedScroll = newScroll; mScrollAnimator = ObjectAnimator.ofFloat(this, STACK_SCROLL, getStackScroll(), newScroll); - mScrollAnimator.setDuration(mContext.getResources().getInteger( - R.integer.recents_animate_task_stack_scroll_duration)); + mScrollAnimator.setDuration(duration); mScrollAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); mScrollAnimator.addListener(new AnimatorListenerAdapter() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 2303d86be2a9..bb4a771ec3d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -20,6 +20,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.KeyguardManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -31,6 +32,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -138,6 +140,8 @@ public abstract class BaseStatusBar extends SystemUI implements protected static final boolean ENABLE_HEADS_UP = true; protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up"; + private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF"; + // Should match the values in PhoneWindowManager public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; @@ -146,6 +150,8 @@ public abstract class BaseStatusBar extends SystemUI implements "com.android.systemui.statusbar.banner_action_cancel"; private static final String BANNER_ACTION_SETUP = "com.android.systemui.statusbar.banner_action_setup"; + private static final String WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION + = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action"; protected CommandQueue mCommandQueue; protected IStatusBarService mBarService; @@ -199,6 +205,9 @@ public abstract class BaseStatusBar extends SystemUI implements private UserManager mUserManager; private int mDensity; + private KeyguardManager mKeyguardManager; + private LockPatternUtils mLockPatternUtils; + // UI-specific methods /** @@ -499,6 +508,20 @@ public abstract class BaseStatusBar extends SystemUI implements ); } + } else if (WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION.equals(action)) { + final IntentSender intentSender = (IntentSender) intent + .getParcelableExtra(Intent.EXTRA_INTENT); + final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX); + try { + mContext.startIntentSender(intentSender, null, 0, 0, 0); + } catch (IntentSender.SendIntentException e) { + /* ignore */ + } + try { + mBarService.onNotificationClick(notificationKey); + } catch (RemoteException e) { + /* ignore */ + } } } }; @@ -661,6 +684,8 @@ public abstract class BaseStatusBar extends SystemUI implements mDensity = currentConfig.densityDpi; mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); + mLockPatternUtils = new LockPatternUtils(mContext); // Connect in to the status bar manager service mCommandQueue = new CommandQueue(this); @@ -723,10 +748,14 @@ public abstract class BaseStatusBar extends SystemUI implements filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(Intent.ACTION_USER_ADDED); filter.addAction(Intent.ACTION_USER_PRESENT); - filter.addAction(BANNER_ACTION_CANCEL); - filter.addAction(BANNER_ACTION_SETUP); mContext.registerReceiver(mBroadcastReceiver, filter); + IntentFilter internalFilter = new IntentFilter(); + internalFilter.addAction(WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION); + internalFilter.addAction(BANNER_ACTION_CANCEL); + internalFilter.addAction(BANNER_ACTION_SETUP); + mContext.registerReceiver(mBroadcastReceiver, internalFilter, PERMISSION_SELF, null); + IntentFilter allUsersFilter = new IntentFilter(); allUsersFilter.addAction( DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); @@ -739,8 +768,7 @@ public abstract class BaseStatusBar extends SystemUI implements if (0 != Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) { Log.d(TAG, "user hasn't seen notification about hidden notifications"); - final LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext); - if (!lockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) { + if (!mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) { Log.d(TAG, "insecure lockscreen, skipping notification"); Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0); @@ -1681,7 +1709,6 @@ public abstract class BaseStatusBar extends SystemUI implements ActivityManagerNative.getDefault().resumeAppSwitches(); } catch (RemoteException e) { } - try { intent.send(); } catch (PendingIntent.CanceledException e) { @@ -1774,8 +1801,22 @@ public abstract class BaseStatusBar extends SystemUI implements ActivityManagerNative.getDefault().resumeAppSwitches(); } catch (RemoteException e) { } - if (intent != null) { + // If we are launching a work activity and require to launch + // separate work challenge, we defer the activity action and cancel + // notification until work challenge is unlocked. + if (intent.isActivity()) { + final int userId = intent.getCreatorUserHandle() + .getIdentifier(); + if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId) + && mKeyguardManager.isDeviceLocked(userId)) { + // Show work challenge, do not run pendingintent and + // remove notification + startWorkChallenge(userId, intent.getIntentSender(), + notificationKey); + return; + } + } try { intent.send(); } catch (PendingIntent.CanceledException e) { @@ -1810,6 +1851,23 @@ public abstract class BaseStatusBar extends SystemUI implements }, afterKeyguardGone); } + public void startWorkChallenge(int userId, IntentSender intendSender, + String notificationKey) { + final Intent callBackIntent = new Intent( + WORK_CHALLENGE_UNLOCKED_NOTIFICATION_ACTION); + callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender); + callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey); + callBackIntent.setPackage(mContext.getPackageName()); + + final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, + null, userId); + newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_CLEAR_TASK); + newIntent.putExtra(Intent.EXTRA_INTENT, PendingIntent + .getBroadcast(mContext, 0, callBackIntent, 0).getIntentSender()); + mContext.startActivity(newIntent); + } + public void register(ExpandableNotificationRow row, StatusBarNotification sbn) { Notification notification = sbn.getNotification(); if (notification.contentIntent != null || notification.fullScreenIntent != null) { @@ -1857,15 +1915,16 @@ public abstract class BaseStatusBar extends SystemUI implements /** * The LEDs are turned off when the notification panel is shown, even just a little bit. + * See also NotificationStackScrollLayout.setIsExpanded() for another place where we + * attempt to do this. */ protected void handleVisibleToUserChanged(boolean visibleToUser) { try { if (visibleToUser) { boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp(); boolean clearNotificationEffects = - ((mShowLockscreenNotifications && mState == StatusBarState.KEYGUARD) || - (!pinnedHeadsUp && (mState == StatusBarState.SHADE - || mState == StatusBarState.SHADE_LOCKED))); + !isPanelFullyCollapsed() && + (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED); int notificationLoad = mNotificationData.getActiveNotifications().size(); if (pinnedHeadsUp && isPanelFullyCollapsed()) { notificationLoad = 1; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index de292d66fc5d..22bb8ebb2dc4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -750,6 +750,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { public Animator getTranslateViewAnimator(final float leftTarget, AnimatorUpdateListener listener) { + if (mTranslateAnim != null) { + mTranslateAnim.cancel(); + } if (areGutsExposed()) { // No translation if guts are exposed. return null; @@ -774,19 +777,27 @@ public class ExpandableNotificationRow extends ActivatableNotificationView { if (listener != null) { translateAnim.addUpdateListener(listener); } - } - translateAnim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator anim) { - if (mSettingsIconRow != null && leftTarget == 0) { - mSettingsIconRow.resetState(); + translateAnim.addListener(new AnimatorListenerAdapter() { + boolean cancelled = false; + + @Override + public void onAnimationCancel(Animator anim) { + cancelled = true; } - mTranslateAnim = null; - } - }); + + @Override + public void onAnimationEnd(Animator anim) { + if (!cancelled && mSettingsIconRow != null && leftTarget == 0) { + mSettingsIconRow.resetState(); + mTranslateAnim = null; + } + } + }); + } set.play(translateAnim); } } + mTranslateAnim = set; return set; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index e53f044f4295..99896f8b7f23 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -36,7 +36,6 @@ import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; import android.view.Display; -import android.view.Gravity; import android.view.IDockedStackListener.Stub; import android.view.MotionEvent; import android.view.Surface; @@ -46,7 +45,6 @@ import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.inputmethod.InputMethodManager; import android.widget.LinearLayout; - import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.stackdivider.Divider; @@ -54,7 +52,6 @@ import com.android.systemui.statusbar.policy.DeadZone; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.ArrayList; public class NavigationBarView extends LinearLayout { final static boolean DEBUG = false; @@ -100,6 +97,7 @@ public class NavigationBarView extends LinearLayout { private boolean mDockedStackExists; private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>(); + private int mDensity; private class NavTransitionListener implements TransitionListener { private boolean mBackTransitioning; @@ -190,6 +188,7 @@ public class NavigationBarView extends LinearLayout { mShowMenu = false; mGestureHelper = new NavigationBarGestureHelper(context); + mDensity = context.getResources().getConfiguration().densityDpi; getIcons(context); mBarTransitions = new NavigationBarTransitions(this); @@ -599,6 +598,10 @@ public class NavigationBarView extends LinearLayout { // we are switching to. setNavigationIconHints(mNavigationIconHints, true); } + if (mDensity != newConfig.densityDpi) { + mDensity = newConfig.densityDpi; + getIcons(getContext()); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 906bd0ff4b57..bf5861107b09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1887,10 +1887,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mBackdrop.getVisibility() != View.VISIBLE) { mBackdrop.setVisibility(View.VISIBLE); if (allowEnterAnimation) { - mBackdrop.animate().alpha(1f); + mBackdrop.animate().alpha(1f).withEndAction(new Runnable() { + @Override + public void run() { + mStatusBarWindowManager.setBackdropShowing(true); + } + }); } else { mBackdrop.animate().cancel(); mBackdrop.setAlpha(1f); + mStatusBarWindowManager.setBackdropShowing(true); } metaDataChanged = true; if (DEBUG_MEDIA) { @@ -1948,7 +1954,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // We are unlocking directly - no animation! mBackdrop.setVisibility(View.GONE); mBackdropBack.setImageDrawable(null); + mStatusBarWindowManager.setBackdropShowing(false); } else { + mStatusBarWindowManager.setBackdropShowing(false); mBackdrop.animate() // Never let the alpha become zero - otherwise the RenderNode // won't draw anything and uninitialized memory will show through diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java index b29c807b7ad7..8f329c4f270d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java @@ -83,7 +83,6 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements private float mDateScaleFactor; private float mGearTranslation; - private TouchAnimator mAnimator; private TouchAnimator mSecondHalfAnimator; private TouchAnimator mFirstHalfAnimator; private TouchAnimator mDateSizeAnimator; @@ -154,12 +153,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements mDateScaleFactor = dateExpandedSize / dateCollapsedSize; updateDateTimePosition(); - mAnimator = new TouchAnimator.Builder() - .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0) - .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0) - .build(); mSecondHalfAnimator = new TouchAnimator.Builder() - .addFloat(mSettingsButton, "rotation", -180, 0) .addFloat(mAlarmStatus, "alpha", 0, 1) .addFloat(mEmergencyOnly, "alpha", 0, 1) .setStartDelay(.5f) @@ -174,6 +168,9 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements .setStartDelay(.36f) .build(); mSettingsAlpha = new TouchAnimator.Builder() + .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0) + .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0) + .addFloat(mSettingsButton, "rotation", -90, 0) .addFloat(mSettingsContainer, "alpha", 0, 1) .addFloat(mMultiUserSwitch, "alpha", 0, 1) .setStartDelay(QSAnimator.EXPANDED_TILE_DELAY) @@ -211,7 +208,6 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements @Override public void setExpansion(float headerExpansionFraction) { mExpansionAmount = headerExpansionFraction; - mAnimator.setPosition(headerExpansionFraction); mSecondHalfAnimator.setPosition(headerExpansionFraction); mFirstHalfAnimator.setPosition(headerExpansionFraction); mDateSizeAnimator.setPosition(headerExpansionFraction); 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 2ba1562c39e4..117e2b325ef7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -227,6 +227,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mStatusBarWindowManager.setKeyguardNeedsInput(needsInput); } + public boolean isUnlockWithWallpaper() { + return mStatusBarWindowManager.isShowingWallpaper(); + } + public void setOccluded(boolean occluded) { if (occluded && !mOccluded && mShowing) { if (mPhoneStatusBar.isInLaunchTransition()) { 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 77ece9322583..ada745079fef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -100,12 +100,16 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { private void applyKeyguardFlags(State state) { if (state.keyguardShowing) { - mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; mLpChanged.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; } else { - mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; mLpChanged.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; } + + if (state.keyguardShowing && !state.backdropShowing) { + mLpChanged.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; + } else { + mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; + } } private void adjustScreenOrientation(State state) { @@ -255,6 +259,11 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { apply(mCurrentState); } + public void setBackdropShowing(boolean showing) { + mCurrentState.backdropShowing = showing; + apply(mCurrentState); + } + public void setKeyguardFadingAway(boolean keyguardFadingAway) { mCurrentState.keyguardFadingAway = keyguardFadingAway; apply(mCurrentState); @@ -323,6 +332,10 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { pw.println(mCurrentState); } + public boolean isShowingWallpaper() { + return !mCurrentState.backdropShowing; + } + private static class State { boolean keyguardShowing; boolean keyguardOccluded; @@ -338,6 +351,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback { boolean forceCollapsed; boolean forceDozeBrightness; boolean forceUserActivity; + boolean backdropShowing; /** * The {@link BaseStatusBar} state from the status bar. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java index f03d9e9dce84..c6b1cdf4047c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java @@ -69,18 +69,22 @@ public class HotspotControllerImpl implements HotspotController { @Override public void addCallback(Callback callback) { - if (callback == null || mCallbacks.contains(callback)) return; - if (DEBUG) Log.d(TAG, "addCallback " + callback); - mCallbacks.add(callback); - mReceiver.setListening(!mCallbacks.isEmpty()); + synchronized (mCallbacks) { + if (callback == null || mCallbacks.contains(callback)) return; + if (DEBUG) Log.d(TAG, "addCallback " + callback); + mCallbacks.add(callback); + mReceiver.setListening(!mCallbacks.isEmpty()); + } } @Override public void removeCallback(Callback callback) { if (callback == null) return; if (DEBUG) Log.d(TAG, "removeCallback " + callback); - mCallbacks.remove(callback); - mReceiver.setListening(!mCallbacks.isEmpty()); + synchronized (mCallbacks) { + mCallbacks.remove(callback); + mReceiver.setListening(!mCallbacks.isEmpty()); + } } @Override @@ -110,8 +114,10 @@ public class HotspotControllerImpl implements HotspotController { } private void fireCallback(boolean isEnabled) { - for (Callback callback : mCallbacks) { - callback.onHotspotChanged(isEnabled); + synchronized (mCallbacks) { + for (Callback callback : mCallbacks) { + callback.onHotspotChanged(isEnabled); + } } } 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 eac8c33db2cd..686a71211dc9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -2696,6 +2696,16 @@ public class NotificationStackScrollLayout extends ViewGroup if (changed) { if (!mIsExpanded) { mGroupManager.collapseAllGroups(); + } else { + // XXX: HACK: we should not be clearing notification effects from way down here. + // But at the moment we don't have a reliable way to know when the window is + // actually exposed to the air, so + if (mPhoneStatusBar.getBarState() != StatusBarState.KEYGUARD) { + if (DEBUG) { + Log.v(TAG, "clearing notification effects from scroller"); + } + mPhoneStatusBar.clearNotificationEffects(); + } } updateNotificationAnimationStates(); updateChronometers(); diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index d36a1d702701..d929519bddff 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -1996,6 +1996,22 @@ message MetricsEvent { // Logs that the user docks window via shortcut key. WINDOW_DOCK_SHORTCUTS = 352; + // User already denied access to the request folder; action takes an integer + // representing the folder's index on Environment.STANDARD_DIRECTORIES + ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER = 353; + + // User already denied access to the request folder; action pass package name + // of calling package. + ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE = 354; + + // User denied access to the request folder and checked 'Do not ask again'; + // action takes an integer representing the folder's index on Environment.STANDARD_DIRECTORIES + ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER = 355; + + // User denied access to the request folder and checked 'Do not ask again'; + // action pass package name of calling package. + ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE = 356; + // Add new aosp constants above this line. // END OF AOSP CONSTANTS } diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp index 4e667c659133..e0f5934cab74 100644 --- a/rs/jni/android_renderscript_RenderScript.cpp +++ b/rs/jni/android_renderscript_RenderScript.cpp @@ -2071,6 +2071,8 @@ nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, sc.array4End = 0; sca = ≻ + // sc_size is required, but unused, by the runtime and drivers. + sc_size = sizeof(sc); } rsScriptForEachMulti((RsContext)con, (RsScript)script, slot, diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java index 3ac81f65797f..562d95065cd8 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java @@ -63,14 +63,6 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen void onDoubleTapAndHold(MotionEvent event, int policyFlags); /** - * Called when the user touches the screen on the second tap of a double - * tap. - * - * @return true if the event is consumed, else false - */ - boolean onDoubleTapStarted(); - - /** * Called when the user lifts their finger on the second tap of a double * tap. * @@ -246,13 +238,20 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen mBaseY = y; mBaseTime = time; + // Since the pointer has moved, this is not a double + // tap. + mFirstTapDetected = false; + mDoubleTapDetected = false; + // If this hasn't been confirmed as a gesture yet, send // the event. if (!mGestureStarted) { mGestureStarted = true; return mListener.onGestureStarted(); } - } else { + } else if (!mFirstTapDetected) { + // The finger may not move if they are double tapping. + // In that case, we shouldn't cancel the gesture. final long timeDelta = time - mBaseTime; final long threshold = mGestureStarted ? CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS : @@ -371,7 +370,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen // The processing of the double tap is deferred until the finger is // lifted, so that we can detect a long press on the second tap. mDoubleTapDetected = true; - return mListener.onDoubleTapStarted(); + return false; } private void maybeSendLongPress(MotionEvent event, int policyFlags) { diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java index cd8b792449cc..3cc991cab65d 100644 --- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java @@ -390,11 +390,6 @@ class TouchExplorer implements EventStreamTransformation, AccessibilityGestureDe } @Override - public boolean onDoubleTapStarted() { - return true; - } - - @Override public boolean onDoubleTap(MotionEvent event, int policyFlags) { // Ignore the event if we aren't touch exploring. if (mCurrentState != STATE_TOUCH_EXPLORING) { diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 3659a40d9f6c..a4f85db949cb 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -210,6 +210,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku private final UserManager mUserManager; private final AppOpsManager mAppOpsManager; private final KeyguardManager mKeyguardManager; + private final DevicePolicyManagerInternal mDevicePolicyManagerInternal; private final SecurityPolicy mSecurityPolicy; @@ -232,6 +233,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); mKeyguardManager = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE); + mDevicePolicyManagerInternal = LocalServices.getService(DevicePolicyManagerInternal.class); mSaveStateHandler = BackgroundThread.getHandler(); mCallbackHandler = new CallbackHandler(mContext.getMainLooper()); mBackupRestoreController = new BackupRestoreController(); @@ -298,11 +300,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } private void registerOnCrossProfileProvidersChangedListener() { - DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService( - DevicePolicyManagerInternal.class); // The device policy is an optional component. - if (devicePolicyManager != null) { - devicePolicyManager.addOnCrossProfileWidgetProvidersChangeListener(this); + if (mDevicePolicyManagerInternal != null) { + mDevicePolicyManagerInternal.addOnCrossProfileWidgetProvidersChangeListener(this); } } @@ -588,7 +588,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku try { UserInfo userInfo = mUserManager.getUserInfo(providerUserId); showBadge = userInfo.isManagedProfile(); - onClickIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent( + onClickIntent = mDevicePolicyManagerInternal.createPackageSuspendedDialogIntent( providerPackage, providerUserId); } finally { Binder.restoreCallingIdentity(identity); @@ -3574,15 +3574,12 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } public boolean isProviderWhiteListed(String packageName, int profileId) { - DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService( - DevicePolicyManagerInternal.class); - // If the policy manager is not available on the device we deny it all. - if (devicePolicyManager == null) { + if (mDevicePolicyManagerInternal == null) { return false; } - List<String> crossProfilePackages = devicePolicyManager + List<String> crossProfilePackages = mDevicePolicyManagerInternal .getCrossProfileWidgetProviders(profileId); return crossProfilePackages.contains(packageName); diff --git a/services/core/Android.mk b/services/core/Android.mk index aaa2211c33d1..99c5dd69cda3 100644 --- a/services/core/Android.mk +++ b/services/core/Android.mk @@ -7,7 +7,8 @@ LOCAL_MODULE := services.core LOCAL_SRC_FILES += \ $(call all-java-files-under,java) \ java/com/android/server/EventLogTags.logtags \ - java/com/android/server/am/EventLogTags.logtags + java/com/android/server/am/EventLogTags.logtags \ + ../../../../system/netd/server/binder/android/net/INetd.aidl LOCAL_JAVA_LIBRARIES := services.net telephony-common LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index bfe9e8e74122..a94c8b8ebb31 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -121,6 +121,8 @@ public class AppOpsService extends IAppOpsService.Stub { * - SparseArray w/ mapping: * AppOp code --> Set of packages that are not restricted for this code * + * For efficiency, a core assumption here is that the number of per-package exemptions stored + * here will be relatively small. If this changes, this data structure should be revisited. */ private final ArrayMap<IBinder, SparseArray<Pair<boolean[], SparseArray<ArraySet<String>>>>> mOpUserRestrictions = new ArrayMap<>(); @@ -445,8 +447,12 @@ public class AppOpsService extends IAppOpsService.Stub { int[] ops) { mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, Binder.getCallingPid(), Binder.getCallingUid(), null); + String resolvedPackageName = resolvePackageName(uid, packageName); + if (resolvedPackageName == null) { + return Collections.emptyList(); + } synchronized (this) { - Ops pkgOps = getOpsLocked(uid, packageName, false); + Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false); if (pkgOps == null) { return null; } @@ -464,7 +470,7 @@ public class AppOpsService extends IAppOpsService.Stub { private void pruneOp(Op op, int uid, String packageName) { if (op.time == 0 && op.rejectTime == 0) { - Ops ops = getOpsLocked(uid, packageName, false); + Ops ops = getOpsRawLocked(uid, packageName, false); if (ops != null) { ops.remove(op.op); if (ops.size() <= 0) { @@ -878,8 +884,12 @@ public class AppOpsService extends IAppOpsService.Stub { public int checkOperation(int code, int uid, String packageName) { verifyIncomingUid(uid); verifyIncomingOp(code); + String resolvedPackageName = resolvePackageName(uid, packageName); + if (resolvedPackageName == null) { + return AppOpsManager.MODE_IGNORED; + } synchronized (this) { - if (isOpRestricted(uid, code, packageName)) { + if (isOpRestricted(uid, code, resolvedPackageName)) { return AppOpsManager.MODE_IGNORED; } code = AppOpsManager.opToSwitch(code); @@ -890,7 +900,7 @@ public class AppOpsService extends IAppOpsService.Stub { return uidMode; } } - Op op = getOpLocked(code, uid, packageName, false); + Op op = getOpLocked(code, uid, resolvedPackageName, false); if (op == null) { return AppOpsManager.opToDefaultMode(code); } @@ -966,6 +976,7 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public int checkPackage(int uid, String packageName) { + Preconditions.checkNotNull(packageName); synchronized (this) { if (getOpsRawLocked(uid, packageName, true) != null) { return AppOpsManager.MODE_ALLOWED; @@ -979,26 +990,39 @@ public class AppOpsService extends IAppOpsService.Stub { public int noteProxyOperation(int code, String proxyPackageName, int proxiedUid, String proxiedPackageName) { verifyIncomingOp(code); - final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(), - proxyPackageName, -1, null); + final int proxyUid = Binder.getCallingUid(); + String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName); + if (resolveProxyPackageName == null) { + return AppOpsManager.MODE_IGNORED; + } + final int proxyMode = noteOperationUnchecked(code, proxyUid, + resolveProxyPackageName, -1, null); if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) { return proxyMode; } - return noteOperationUnchecked(code, proxiedUid, proxiedPackageName, - Binder.getCallingUid(), proxyPackageName); + String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName); + if (resolveProxiedPackageName == null) { + return AppOpsManager.MODE_IGNORED; + } + return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName, + proxyMode, resolveProxyPackageName); } @Override public int noteOperation(int code, int uid, String packageName) { verifyIncomingUid(uid); verifyIncomingOp(code); - return noteOperationUnchecked(code, uid, packageName, 0, null); + String resolvedPackageName = resolvePackageName(uid, packageName); + if (resolvedPackageName == null) { + return AppOpsManager.MODE_IGNORED; + } + return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null); } private int noteOperationUnchecked(int code, int uid, String packageName, int proxyUid, String proxyPackageName) { synchronized (this) { - Ops ops = getOpsLocked(uid, packageName, true); + Ops ops = getOpsRawLocked(uid, packageName, true); if (ops == null) { if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid + " package " + packageName); @@ -1046,16 +1070,20 @@ public class AppOpsService extends IAppOpsService.Stub { public int startOperation(IBinder token, int code, int uid, String packageName) { verifyIncomingUid(uid); verifyIncomingOp(code); + String resolvedPackageName = resolvePackageName(uid, packageName); + if (resolvedPackageName == null) { + return AppOpsManager.MODE_IGNORED; + } ClientState client = (ClientState)token; synchronized (this) { - Ops ops = getOpsLocked(uid, packageName, true); + Ops ops = getOpsRawLocked(uid, resolvedPackageName, true); if (ops == null) { if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid - + " package " + packageName); + + " package " + resolvedPackageName); return AppOpsManager.MODE_ERRORED; } Op op = getOpLocked(ops, code, true); - if (isOpRestricted(uid, code, packageName)) { + if (isOpRestricted(uid, code, resolvedPackageName)) { return AppOpsManager.MODE_IGNORED; } final int switchCode = AppOpsManager.opToSwitch(code); @@ -1065,7 +1093,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (uidMode != AppOpsManager.MODE_ALLOWED) { if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " + switchCode + " (" + code + ") uid " + uid + " package " - + packageName); + + resolvedPackageName); op.rejectTime = System.currentTimeMillis(); return uidMode; } @@ -1073,12 +1101,13 @@ public class AppOpsService extends IAppOpsService.Stub { final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code " - + switchCode + " (" + code + ") uid " + uid + " package " + packageName); + + switchCode + " (" + code + ") uid " + uid + " package " + + resolvedPackageName); op.rejectTime = System.currentTimeMillis(); return switchOp.mode; } if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid - + " package " + packageName); + + " package " + resolvedPackageName); if (op.nesting == 0) { op.time = System.currentTimeMillis(); op.rejectTime = 0; @@ -1096,9 +1125,16 @@ public class AppOpsService extends IAppOpsService.Stub { public void finishOperation(IBinder token, int code, int uid, String packageName) { verifyIncomingUid(uid); verifyIncomingOp(code); - ClientState client = (ClientState)token; + String resolvedPackageName = resolvePackageName(uid, packageName); + if (resolvedPackageName == null) { + return; + } + if (!(token instanceof ClientState)) { + return; + } + ClientState client = (ClientState) token; synchronized (this) { - Op op = getOpLocked(code, uid, packageName, true); + Op op = getOpLocked(code, uid, resolvedPackageName, true); if (op == null) { return; } @@ -1114,6 +1150,9 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public int permissionToOpCode(String permission) { + if (permission == null) { + return AppOpsManager.OP_NONE; + } return AppOpsManager.permissionToOpCode(permission); } @@ -1163,15 +1202,6 @@ public class AppOpsService extends IAppOpsService.Stub { return uidState; } - private Ops getOpsLocked(int uid, String packageName, boolean edit) { - if (uid == 0) { - packageName = "root"; - } else if (uid == Process.SHELL_UID) { - packageName = "com.android.shell"; - } - return getOpsRawLocked(uid, packageName, edit); - } - private Ops getOpsRawLocked(int uid, String packageName, boolean edit) { UidState uidState = getUidStateLocked(uid, edit); if (uidState == null) { @@ -1257,7 +1287,7 @@ public class AppOpsService extends IAppOpsService.Stub { } private Op getOpLocked(int code, int uid, String packageName, boolean edit) { - Ops ops = getOpsLocked(uid, packageName, edit); + Ops ops = getOpsRawLocked(uid, packageName, edit); if (ops == null) { return null; } @@ -1304,15 +1334,18 @@ public class AppOpsService extends IAppOpsService.Stub { } if (opRestrictions[code]) { - if (opExceptions != null && opExceptions.get(code) != null && - opExceptions.get(code).contains(packageName)) { - continue; // AppOps code is restricted, but this package is exempt + + if (opExceptions != null) { + ArraySet<String> ex = opExceptions.get(code); + if (ex != null && ex.contains(packageName)) { + continue; // AppOps code is restricted, but this package is exempt + } } if (AppOpsManager.opAllowSystemBypassRestriction(code)) { // If we are the system, bypass user restrictions for certain codes synchronized (this) { - Ops ops = getOpsLocked(uid, packageName, true); + Ops ops = getOpsRawLocked(uid, packageName, true); if ((ops != null) && ops.isPrivileged) { return false; } @@ -1577,7 +1610,7 @@ public class AppOpsService extends IAppOpsService.Stub { out.startTag(null, "uid"); out.attribute(null, "n", Integer.toString(pkg.getUid())); synchronized (this) { - Ops ops = getOpsLocked(pkg.getUid(), pkg.getPackageName(), false); + Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false); // Should always be present as the list of PackageOps is generated // from Ops. if (ops != null) { @@ -2098,6 +2131,7 @@ public class AppOpsService extends IAppOpsService.Stub { @Override public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) { checkSystemUid("setUserRestrictions"); + Preconditions.checkNotNull(restrictions); Preconditions.checkNotNull(token); final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle); for (int i = 0; i < opRestrictions.length; ++i) { @@ -2143,9 +2177,8 @@ public class AppOpsService extends IAppOpsService.Stub { final SparseArray<ArraySet<String>> opExceptions = getUserPackageExemptionsForToken(token, userHandle); - // If exceptionPackages is not null, update the exception packages for this AppOps code ArraySet<String> exceptions = opExceptions.get(code); - if (exceptionPackages != null) { + if (exceptionPackages != null && exceptionPackages.length > 0) { if (exceptions == null) { exceptions = new ArraySet<>(exceptionPackages.length); opExceptions.put(code, exceptions); @@ -2153,7 +2186,11 @@ public class AppOpsService extends IAppOpsService.Stub { exceptions.clear(); } - exceptions.addAll(Arrays.asList(exceptionPackages)); + for (String p : exceptionPackages) { + exceptions.add(p); + } + } else { + opExceptions.remove(code); } } @@ -2219,14 +2256,23 @@ public class AppOpsService extends IAppOpsService.Stub { if (restrictions != null) { final boolean[] opRestrictions = restrictions.first; + final SparseArray<ArraySet<String>> opExceptions = restrictions.second; + boolean stillHasRestrictions = false; if (opRestrictions != null) { - for (boolean restriction : opRestrictions) { + for (int i = 0; i < opRestrictions.length; i++) { + boolean restriction = opRestrictions[i]; if (restriction) { - return; + stillHasRestrictions = true; + } else { + opExceptions.remove(i); } } } + if (stillHasRestrictions) { + return; + } + // No restrictions set for this client perTokenRestrictions.remove(userHandle); if (perTokenRestrictions.size() <= 0) { @@ -2300,6 +2346,15 @@ public class AppOpsService extends IAppOpsService.Stub { } } + private static String resolvePackageName(int uid, String packageName) { + if (uid == 0) { + return "root"; + } else if (uid == Process.SHELL_UID) { + return "com.android.shell"; + } + return packageName; + } + private static String[] getPackagesForUid(int uid) { String[] packageNames = null; try { diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index e241a4aa9926..799a763845d2 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -761,6 +761,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); + } else if (!isNameAndAddressSet()) { + if (DBG) Slog.d(TAG, "Getting adapter name and address"); + enable(); + waitForOnOff(true, false); + disable(true); } } @@ -1001,6 +1006,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } } + // mAddress is accessed from outside. // It is alright without a lock. Here, bluetooth is off, no other thread is // changing mAddress @@ -1181,6 +1187,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.e(TAG,"Unable to call configHciSnoopLog", e); } + if (!isNameAndAddressSet()) { + try { + storeNameAndAddress(mBluetooth.getName(), + mBluetooth.getAddress()); + } catch (RemoteException re) { + Slog.e(TAG, "Unable to grab names", re); + } + } + //Register callback object try { mBluetooth.registerCallback(mBluetoothCallback); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 86040c2842ed..b7fca1a10ffc 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1784,6 +1784,38 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } + private void dumpNetworkDiagnostics(IndentingPrintWriter pw) { + final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>(); + final long DIAG_TIME_MS = 5000; + for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { + // Start gathering diagnostic information. + netDiags.add(new NetworkDiagnostics( + nai.network, + new LinkProperties(nai.linkProperties), // Must be a copy. + DIAG_TIME_MS)); + } + + for (NetworkDiagnostics netDiag : netDiags) { + pw.println(); + netDiag.waitForMeasurements(); + netDiag.dump(pw); + } + } + + private void dumpApf(IndentingPrintWriter pw) { + pw.println("APF filters:"); + pw.increaseIndent(); + for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { + if (nai.apfFilter != null) { + pw.println(nai.name() + ":"); + pw.increaseIndent(); + nai.apfFilter.dump(pw); + pw.decreaseIndent(); + } + } + pw.decreaseIndent(); + } + @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); @@ -1796,23 +1828,13 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } - final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>(); if (argsContain(args, "--diag")) { - final long DIAG_TIME_MS = 5000; - for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { - // Start gathering diagnostic information. - netDiags.add(new NetworkDiagnostics( - nai.network, - new LinkProperties(nai.linkProperties), // Must be a copy. - DIAG_TIME_MS)); - } - - for (NetworkDiagnostics netDiag : netDiags) { - pw.println(); - netDiag.waitForMeasurements(); - netDiag.dump(pw); - } + dumpNetworkDiagnostics(pw); + return; + } + if (argsContain(args, "apf")) { + dumpApf(pw); return; } @@ -1878,6 +1900,9 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.println(); mKeepaliveTracker.dump(pw); + pw.println(); + dumpApf(pw); + if (mInetLog != null && mInetLog.size() > 0) { pw.println(); pw.println("Inet condition reports:"); @@ -3253,8 +3278,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } int user = UserHandle.getUserId(Binder.getCallingUid()); synchronized(mVpns) { - setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, mVpns.get(user), - profile)); + Vpn vpn = mVpns.get(user); + if (vpn == null) { + Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown"); + return false; + } + setLockdownTracker(new LockdownVpnTracker(mContext, mNetd, this, vpn, profile)); } } else { setLockdownTracker(null); diff --git a/services/core/java/com/android/server/ContextHubSystemService.java b/services/core/java/com/android/server/ContextHubSystemService.java new file mode 100644 index 000000000000..1b85632b806c --- /dev/null +++ b/services/core/java/com/android/server/ContextHubSystemService.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.hardware.location.ContextHubService; +import android.content.Context; +import android.util.Log; + +class ContextHubSystemService extends SystemService { + private static final String TAG = "ContextHubSystemService"; + private final ContextHubService mContextHubService; + + public ContextHubSystemService(Context context) { + super(context); + mContextHubService = new ContextHubService(context); + } + + @Override + public void onStart() { + } + + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + Log.d(TAG, "onBootPhase: PHASE_SYSTEM_SERVICES_READY"); + publishBinderService(ContextHubService.CONTEXTHUB_SERVICE, mContextHubService); + } + } +} diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 9b8f2d2d7d57..00a49bdb7273 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -456,6 +456,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub class SettingsObserver extends ContentObserver { int mUserId; boolean mRegistered = false; + @NonNull String mLastEnabled = ""; /** diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 329f716f302f..07c10b09287a 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -49,6 +49,7 @@ import android.annotation.NonNull; import android.app.ActivityManagerNative; import android.content.Context; import android.net.ConnectivityManager; +import android.net.INetd; import android.net.INetworkManagementEventObserver; import android.net.InterfaceConfiguration; import android.net.IpPrefix; @@ -122,7 +123,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub private static final String TAG = "NetworkManagement"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final String NETD_TAG = "NetdConnector"; - private static final String NETD_SOCKET_NAME = "netd"; + private static final String NETD_SERVICE_NAME = "netd"; private static final int MAX_UID_RANGES_PER_COMMAND = 10; @@ -188,6 +189,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub private final Handler mFgHandler; private final Handler mDaemonHandler; + private INetd mNetdService; + private IBatteryStats mBatteryStats; private final Thread mThread; @@ -306,7 +309,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub } public static NetworkManagementService create(Context context) throws InterruptedException { - return create(context, NETD_SOCKET_NAME); + return create(context, NETD_SERVICE_NAME); } public void systemReady() { @@ -515,6 +518,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub * existing in-memory rules. */ private void prepareNativeDaemon() { + boolean nativeServiceAvailable = false; + try { + mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME)); + nativeServiceAvailable = mNetdService.isAlive(); + } catch (RemoteException e) {} + if (!nativeServiceAvailable) { + Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME); + } + mBandwidthControlEnabled = false; // only enable bandwidth control when support exists diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java index 306e9331671e..3eb20a0c580e 100644 --- a/services/core/java/com/android/server/TextServicesManagerService.java +++ b/services/core/java/com/android/server/TextServicesManagerService.java @@ -28,6 +28,7 @@ import com.android.internal.textservice.ITextServicesSessionListener; import org.xmlpull.v1.XmlPullParserException; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManagerNative; import android.app.AppGlobals; @@ -464,9 +465,10 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { return null; } synchronized (mSpellCheckerMap) { - final String subtypeHashCodeStr = mSettings.getSelectedSpellCheckerSubtype(); + final int subtypeHashCode = + mSettings.getSelectedSpellCheckerSubtype(SpellCheckerSubtype.SUBTYPE_ID_NONE); if (DBG) { - Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCodeStr); + Slog.w(TAG, "getCurrentSpellCheckerSubtype: " + subtypeHashCode); } final SpellCheckerInfo sci = getCurrentSpellChecker(null); if (sci == null || sci.getSubtypeCount() == 0) { @@ -475,17 +477,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } return null; } - final int hashCode; - if (!TextUtils.isEmpty(subtypeHashCodeStr)) { - hashCode = Integer.valueOf(subtypeHashCodeStr); - } else { - hashCode = 0; - } - if (hashCode == 0 && !allowImplicitlySelectedSubtype) { + if (subtypeHashCode == SpellCheckerSubtype.SUBTYPE_ID_NONE + && !allowImplicitlySelectedSubtype) { return null; } String candidateLocale = null; - if (hashCode == 0) { + if (subtypeHashCode == 0) { // Spell checker language settings == "auto" final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class); if (imm != null) { @@ -507,7 +504,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { SpellCheckerSubtype candidate = null; for (int i = 0; i < sci.getSubtypeCount(); ++i) { final SpellCheckerSubtype scs = sci.getSubtypeAt(i); - if (hashCode == 0) { + if (subtypeHashCode == 0) { final String scsLocale = scs.getLocale(); if (candidateLocale.equals(scsLocale)) { return scs; @@ -518,7 +515,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { candidate = scs; } } - } else if (scs.hashCode() == hashCode) { + } else if (scs.hashCode() == subtypeHashCode) { if (DBG) { Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale + ", " + scs.getLocale()); @@ -1096,12 +1093,15 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } - private String getString(final String key) { + @Nullable + private String getString(@NonNull final String key, @Nullable final String defaultValue) { + final String result; if (mCopyOnWrite && mCopyOnWriteDataStore.containsKey(key)) { - final String result = mCopyOnWriteDataStore.get(key); - return result != null ? result : ""; + result = mCopyOnWriteDataStore.get(key); + } else { + result = Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId); } - return Settings.Secure.getStringForUser(mResolver, key, mCurrentUserId); + return result != null ? result : defaultValue; } private void putInt(final String key, final int value) { @@ -1149,24 +1149,31 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { return mCurrentUserId; } - public void putSelectedSpellChecker(String sciId) { - putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId); + public void putSelectedSpellChecker(@Nullable String sciId) { + if (TextUtils.isEmpty(sciId)) { + // OK to coalesce to null, since getSelectedSpellChecker() can take care of the + // empty data scenario. + putString(Settings.Secure.SELECTED_SPELL_CHECKER, null); + } else { + putString(Settings.Secure.SELECTED_SPELL_CHECKER, sciId); + } } public void putSelectedSpellCheckerSubtype(int hashCode) { - putString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode)); + putInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, hashCode); } public void setSpellCheckerEnabled(boolean enabled) { putBoolean(Settings.Secure.SPELL_CHECKER_ENABLED, enabled); } + @NonNull public String getSelectedSpellChecker() { - return getString(Settings.Secure.SELECTED_SPELL_CHECKER); + return getString(Settings.Secure.SELECTED_SPELL_CHECKER, ""); } - public String getSelectedSpellCheckerSubtype() { - return getString(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE); + public int getSelectedSpellCheckerSubtype(final int defaultValue) { + return getInt(Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, defaultValue); } public boolean isSpellCheckerEnabled() { diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 11888ff4705c..4198af96d5cd 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -67,7 +67,8 @@ public class Watchdog extends Thread { "/system/bin/audioserver", "/system/bin/mediaserver", "/system/bin/sdcard", - "/system/bin/surfaceflinger" + "/system/bin/surfaceflinger", + "media.log" }; static Watchdog sWatchdog; diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index d4dd50590c8a..8310c97de4aa 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -597,7 +597,7 @@ public class AccountManagerService if (sharedAccounts == null || sharedAccounts.length == 0) return; Account[] accounts = getAccountsAsUser(null, userId, mContext.getOpPackageName()); int parentUserId = UserManager.isSplitSystemUser() - ? mUserManager.getUserInfo(userId).restrictedProfileParentId + ? getUserManager().getUserInfo(userId).restrictedProfileParentId : UserHandle.USER_SYSTEM; if (parentUserId < 0) { Log.w(TAG, "User " + userId + " has shared accounts, but no parent user"); @@ -1061,7 +1061,7 @@ public class AccountManagerService for (UserInfo user : users) { if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) { addSharedAccountAsUser(account, user.id); - if (mUserManager.isUserUnlocked(user.id)) { + if (getUserManager().isUserUnlocked(user.id)) { mMessageHandler.sendMessage(mMessageHandler.obtainMessage( MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account)); } @@ -1270,7 +1270,7 @@ public class AccountManagerService * Owner or system user account was renamed, rename the account for * those users with which the account was shared. */ - List<UserInfo> users = mUserManager.getUsers(true); + List<UserInfo> users = getUserManager().getUsers(true); for (UserInfo user : users) { if (user.isRestricted() && (user.restrictedProfileParentId == parentUserId)) { @@ -1286,7 +1286,7 @@ public class AccountManagerService } private boolean canHaveProfile(final int parentUserId) { - final UserInfo userInfo = mUserManager.getUserInfo(parentUserId); + final UserInfo userInfo = getUserManager().getUserInfo(parentUserId); return userInfo != null && userInfo.canHaveProfile(); } @@ -1477,7 +1477,7 @@ public class AccountManagerService int parentUserId = accounts.userId; if (canHaveProfile(parentUserId)) { // Remove from any restricted profiles that are sharing this account. - List<UserInfo> users = mUserManager.getUsers(true); + List<UserInfo> users = getUserManager().getUsers(true); for (UserInfo user : users) { if (user.isRestricted() && parentUserId == (user.restrictedProfileParentId)) { removeSharedAccountAsUser(account, user.id, callingUid); @@ -4730,7 +4730,7 @@ public class AccountManagerService || callingUid == Process.myUid()) { return unfiltered; } - UserInfo user = mUserManager.getUserInfo(userAccounts.userId); + UserInfo user = getUserManager().getUserInfo(userAccounts.userId); if (user != null && user.isRestricted()) { String[] packages = mPackageManager.getPackagesForUid(callingUid); // If any of the packages is a white listed package, return the full set, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 07f668bf691f..6361db59b0f5 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5347,6 +5347,7 @@ public final class ActivityManagerService extends ActivityManagerNative Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED, Uri.fromParts("package", packageName, null)); intent.putExtra(Intent.EXTRA_UID, pkgUid); + intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(pkgUid)); broadcastIntentInPackage("android", Process.SYSTEM_UID, intent, null, null, 0, null, null, null, null, false, false, userId); } catch (RemoteException e) { @@ -6496,15 +6497,13 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) { + public void keyguardGoingAway(int flags) { enforceNotIsolatedCaller("keyguardGoingAway"); final long token = Binder.clearCallingIdentity(); try { synchronized (this) { if (DEBUG_LOCKSCREEN) logLockScreen(""); - mWindowManager.keyguardGoingAway(disableWindowAnimations, - keyguardGoingToNotificationShade); + mWindowManager.keyguardGoingAway(flags); if (mLockScreenShown == LOCK_SCREEN_SHOWN) { mLockScreenShown = LOCK_SCREEN_HIDDEN; updateSleepIfNeededLocked(); @@ -6914,6 +6913,14 @@ public final class ActivityManagerService extends ActivityManagerNative } } + // We're going to be splicing together extras before sending, so we're + // okay poking into any contained extras. + if (intents != null) { + for (int i = 0; i < intents.length; i++) { + intents[i].setDefusable(true); + } + } + final boolean noCreate = (flags&PendingIntent.FLAG_NO_CREATE) != 0; final boolean cancelCurrent = (flags&PendingIntent.FLAG_CANCEL_CURRENT) != 0; final boolean updateCurrent = (flags&PendingIntent.FLAG_UPDATE_CURRENT) != 0; @@ -11197,7 +11204,6 @@ public final class ActivityManagerService extends ActivityManagerNative } void finishRunningVoiceLocked() { - Slog.d(TAG, "finishRunningVoiceLocked() >>>>"); if (mRunningVoice != null) { mRunningVoice = null; mVoiceWakeLock.release(); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 09542cbdf3e1..26eaa8a2b186 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2213,10 +2213,11 @@ final class ActivityStack { ActivityStack lastStack = mStackSupervisor.getLastStack(); if (next.app != null && next.app.thread != null) { - if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next); + if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next + + " stopped=" + next.stopped + " visible=" + next.visible); // This activity is now becoming visible. - if (!next.visible) { + if (!next.visible || next.stopped) { mWindowManager.setAppVisibility(next.appToken, true); } diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java index e4b4c2dcfad7..13d90e3f2672 100644 --- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java +++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java @@ -29,6 +29,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED; import android.app.KeyguardManager; +import android.app.admin.DevicePolicyManagerInternal; import android.content.IIntentSender; import android.content.Intent; import android.content.IntentSender; @@ -40,6 +41,7 @@ import android.os.UserHandle; import android.os.UserManager; import com.android.internal.app.UnlaunchableAppActivity; +import com.android.server.LocalServices; /** * A class that contains activity intercepting logic for {@link ActivityStarter#startActivityLocked} @@ -133,8 +135,10 @@ class ActivityStartInterceptor { (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) == 0) { return false; } - mIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(mAInfo.packageName, - mUserId); + DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService( + DevicePolicyManagerInternal.class); + mIntent = devicePolicyManager.createPackageSuspendedDialogIntent( + mAInfo.packageName, mUserId); mCallingPid = mRealCallingPid; mCallingUid = mRealCallingUid; mResolvedType = null; diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 83ad2a7ebfdd..fa62c9867168 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1327,19 +1327,31 @@ class ActivityStarter { intentActivity.setTaskToAffiliateWith(mSourceRecord.task); } mMovedHome = true; - final ActivityStack launchStack = - getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.task, - mOptions, true); - if (launchStack == null || launchStack == mTargetStack) { - // We only want to move to the front, if we aren't going to launch on a - // different stack. If we launch on a different stack, we will put the - // task on top there. - mTargetStack.moveTaskToFrontLocked(intentActivity.task, mNoAnimation, - mOptions, mStartActivity.appTimeTracker, "bringingFoundTaskToFront"); - mMovedToFront = true; + + // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities + // will be cleared soon by ActivityStarter in setTaskFromIntentActivity(). + // So no point resuming any of the activities here, it just wastes one extra + // resuming, plus enter AND exit transitions. + // Here we only want to bring the target stack forward. Transition will be applied + // to the new activity that's started after the old ones are gone. + final boolean willClearTask = + (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK)) + == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); + if (!willClearTask) { + final ActivityStack launchStack = getLaunchStack( + mStartActivity, mLaunchFlags, mStartActivity.task, mOptions, true); + if (launchStack == null || launchStack == mTargetStack) { + // We only want to move to the front, if we aren't going to launch on a + // different stack. If we launch on a different stack, we will put the + // task on top there. + mTargetStack.moveTaskToFrontLocked( + intentActivity.task, mNoAnimation, mOptions, + mStartActivity.appTimeTracker, "bringingFoundTaskToFront"); + mMovedToFront = true; + } + mOptions = null; } updateTaskReturnToType(intentActivity.task, mLaunchFlags, focusStack); - mOptions = null; } } if (!mMovedToFront && mDoResume) { diff --git a/services/core/java/com/android/server/am/ProcessStartLogger.java b/services/core/java/com/android/server/am/ProcessStartLogger.java index d2aa96670bb9..39fbeb5e1614 100644 --- a/services/core/java/com/android/server/am/ProcessStartLogger.java +++ b/services/core/java/com/android/server/am/ProcessStartLogger.java @@ -4,7 +4,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.app.AppGlobals; -import android.auditing.SecurityLog; +import android.app.admin.SecurityLog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index d919737c28e2..b4df689b14a8 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -28,6 +28,7 @@ import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; import android.app.AppGlobals; import android.app.AppOpsManager; +import android.app.NotificationManager; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; @@ -40,6 +41,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; @@ -105,9 +107,6 @@ import android.util.MathUtils; import android.util.Slog; import android.util.SparseIntArray; import android.view.KeyEvent; -import android.view.OrientationEventListener; -import android.view.Surface; -import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; import com.android.internal.util.XmlUtils; @@ -206,7 +205,6 @@ public class AudioService extends IAudioService.Stub { private static final int MSG_SET_FORCE_USE = 8; private static final int MSG_BT_HEADSET_CNCT_FAILED = 9; private static final int MSG_SET_ALL_VOLUMES = 10; - private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 11; private static final int MSG_REPORT_NEW_ROUTES = 12; private static final int MSG_SET_FORCE_BT_A2DP_USE = 13; private static final int MSG_CHECK_MUSIC_ACTIVE = 14; @@ -218,7 +216,6 @@ public class AudioService extends IAudioService.Stub { private static final int MSG_UNLOAD_SOUND_EFFECTS = 20; private static final int MSG_SYSTEM_READY = 21; private static final int MSG_PERSIST_MUSIC_ACTIVE_MS = 22; - private static final int MSG_PERSIST_MICROPHONE_MUTE = 23; private static final int MSG_UNMUTE_STREAM = 24; private static final int MSG_DYN_POLICY_MIX_STATE_UPDATE = 25; private static final int MSG_INDICATE_SYSTEM_READY = 26; @@ -557,6 +554,7 @@ public class AudioService extends IAudioService.Stub { private static Long mLastDeviceConnectMsgTime = new Long(0); + private NotificationManager mNm; private AudioManagerInternal.RingerModeDelegate mRingerModeDelegate; private VolumePolicy mVolumePolicy = VolumePolicy.DEFAULT; private long mLoweredFromNormalToVibrateTime; @@ -665,6 +663,7 @@ public class AudioService extends IAudioService.Stub { // array initialized by updateStreamVolumeAlias() updateStreamVolumeAlias(false /*updateVolumes*/, TAG); readPersistedSettings(); + readUserRestrictions(); mSettingsObserver = new SettingsObserver(); createStreamStates(); @@ -751,6 +750,8 @@ public class AudioService extends IAudioService.Stub { } } + mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); + sendMsg(mAudioHandler, MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED, SENDMSG_REPLACE, @@ -1109,14 +1110,27 @@ public class AudioService extends IAudioService.Stub { System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED, UserHandle.USER_CURRENT); + updateMasterMono(cr); + + // Each stream will read its own persisted settings + + // Broadcast the sticky intents + broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal); + broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode); + + // Broadcast vibrate settings + broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); + broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); + + // Load settings for the volume controller + mVolumeController.loadSettings(cr); + } + + private void readUserRestrictions() { final int currentUser = getCurrentUserId(); - // In addition to checking the system setting, also check the current user restriction. - // Because of the delay before persisting VOLUME_MASTER_MUTE, there's a window where - // DISALLOW_ADJUST_VOLUME will be ignored when it's set right before switching users. - boolean masterMute = (System.getIntForUser(cr, System.VOLUME_MASTER_MUTE, - 0, UserHandle.USER_CURRENT) == 1) - || mUserManagerInternal.getUserRestriction( + // Check the current user restriction. + boolean masterMute = mUserManagerInternal.getUserRestriction( currentUser, UserManager.DISALLOW_ADJUST_VOLUME); if (mUseFixedVolume) { masterMute = false; @@ -1129,29 +1143,12 @@ public class AudioService extends IAudioService.Stub { AudioSystem.setMasterMute(masterMute); broadcastMasterMuteStatus(masterMute); - boolean microphoneMute = - (System.getIntForUser(cr, System.MICROPHONE_MUTE, 0, UserHandle.USER_CURRENT) == 1) - || mUserManagerInternal.getUserRestriction( - currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE); + boolean microphoneMute = mUserManagerInternal.getUserRestriction( + currentUser, UserManager.DISALLOW_UNMUTE_MICROPHONE); if (DEBUG_VOL) { Log.d(TAG, String.format("Mic mute %s, user=%d", microphoneMute, currentUser)); } AudioSystem.muteMicrophone(microphoneMute); - - updateMasterMono(cr); - - // Each stream will read its own persisted settings - - // Broadcast the sticky intents - broadcastRingerMode(AudioManager.RINGER_MODE_CHANGED_ACTION, mRingerModeExternal); - broadcastRingerMode(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, mRingerMode); - - // Broadcast vibrate settings - broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); - broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION); - - // Load settings for the volume controller - mVolumeController.loadSettings(cr); } private int rescaleIndex(int index, int srcStream, int dstStream) { @@ -1309,7 +1306,6 @@ public class AudioService extends IAudioService.Stub { && (mRingerModeMutedStreams & (1 << AudioSystem.STREAM_MUSIC)) != 0) { adjustVolume = false; } - int oldIndex = mStreamStates[streamType].getIndex(device); if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) { @@ -1453,10 +1449,7 @@ public class AudioService extends IAudioService.Stub { } }; - private void onSetStreamVolume(int streamType, int index, int flags, int device, - String caller) { - final int stream = mStreamVolumeAlias[streamType]; - setStreamVolumeInt(stream, index, device, false, caller); + private int getNewRingerMode(int stream, int index, int flags) { // setting volume on ui sounds stream type also controls silent mode if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || (stream == getUiSoundsStreamType())) { @@ -1464,11 +1457,49 @@ public class AudioService extends IAudioService.Stub { if (index == 0) { newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE : mVolumePolicy.volumeDownToEnterSilent ? AudioManager.RINGER_MODE_SILENT - : AudioManager.RINGER_MODE_NORMAL; + : AudioManager.RINGER_MODE_NORMAL; } else { newRingerMode = AudioManager.RINGER_MODE_NORMAL; } - setRingerMode(newRingerMode, TAG + ".onSetStreamVolume", false /*external*/); + return newRingerMode; + } + return getRingerModeExternal(); + } + + private boolean isAndroidNPlus(String caller) { + try { + final ApplicationInfo applicationInfo = + mContext.getPackageManager().getApplicationInfoAsUser( + caller, 0, UserHandle.getUserId(Binder.getCallingUid())); + if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) { + return true; + } + return false; + } catch (PackageManager.NameNotFoundException e) { + return true; + } + } + + private boolean wouldToggleZenMode(int newMode) { + if (getRingerModeExternal() == AudioManager.RINGER_MODE_SILENT + && newMode != AudioManager.RINGER_MODE_SILENT) { + return true; + } else if (getRingerModeExternal() != AudioManager.RINGER_MODE_SILENT + && newMode == AudioManager.RINGER_MODE_SILENT) { + return true; + } + return false; + } + + private void onSetStreamVolume(int streamType, int index, int flags, int device, + String caller) { + final int stream = mStreamVolumeAlias[streamType]; + setStreamVolumeInt(stream, index, device, false, caller); + // setting volume on ui sounds stream type also controls silent mode + if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || + (stream == getUiSoundsStreamType())) { + setRingerMode(getNewRingerMode(stream, index, flags), + TAG + ".onSetStreamVolume", false /*external*/); } // setting non-zero volume for a muted stream unmutes the stream and vice versa mStreamStates[stream].mute(index == 0); @@ -1509,6 +1540,12 @@ public class AudioService extends IAudioService.Stub { return; } + if (isAndroidNPlus(callingPackage) + && wouldToggleZenMode(getNewRingerMode(streamTypeAlias, index, flags)) + && !mNm.isNotificationPolicyAccessGrantedForPackage(callingPackage)) { + throw new SecurityException("Not allowed to change Do Not Disturb state"); + } + synchronized (mSafeMediaVolumeState) { // reset any pending volume command mPendingVolumeCommand = null; @@ -1869,20 +1906,12 @@ public class AudioService extends IAudioService.Stub { if (mute != AudioSystem.getMasterMute()) { setSystemAudioMute(mute); AudioSystem.setMasterMute(mute); - // Post a persist master volume msg - sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1 - : 0, userId, null, PERSIST_DELAY); sendMasterMuteUpdate(mute, flags); Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute); sendBroadcastToAll(intent); } - } else { - // If not the current user just persist the setting which will be loaded - // on user switch. - sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1 - : 0, userId, null, PERSIST_DELAY); } } @@ -1975,8 +2004,6 @@ public class AudioService extends IAudioService.Stub { AudioSystem.muteMicrophone(on); } // Post a persist microphone msg. - sendMsg(mAudioHandler, MSG_PERSIST_MICROPHONE_MUTE, SENDMSG_REPLACE, on ? 1 - : 0, userId, null, PERSIST_DELAY); } @Override @@ -2005,6 +2032,11 @@ public class AudioService extends IAudioService.Stub { } public void setRingerModeExternal(int ringerMode, String caller) { + if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode) + && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) { + throw new SecurityException("Not allowed to change Do Not Disturb state"); + } + setRingerMode(ringerMode, caller, true /*external*/); } @@ -2560,6 +2592,7 @@ public class AudioService extends IAudioService.Stub { private void readAudioSettings(boolean userSwitch) { // restore ringer mode, ringer mode affected streams, mute affected streams and vibrate settings readPersistedSettings(); + readUserRestrictions(); // restore volume settings int numStreamTypes = AudioSystem.getNumStreamTypes(); @@ -4492,16 +4525,6 @@ public class AudioService extends IAudioService.Stub { persistVolume((VolumeStreamState) msg.obj, msg.arg1); break; - case MSG_PERSIST_MASTER_VOLUME_MUTE: - if (mUseFixedVolume) { - return; - } - Settings.System.putIntForUser(mContentResolver, - Settings.System.VOLUME_MASTER_MUTE, - msg.arg1, - msg.arg2); - break; - case MSG_PERSIST_RINGER_MODE: // note that the value persisted is the current ringer mode, not the // value of ringer mode as of the time the request was made to persist @@ -4624,15 +4647,11 @@ public class AudioService extends IAudioService.Stub { Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, musicActiveMs, UserHandle.USER_CURRENT); break; - case MSG_PERSIST_MICROPHONE_MUTE: - Settings.System.putIntForUser(mContentResolver, - Settings.System.MICROPHONE_MUTE, - msg.arg1, - msg.arg2); - break; + case MSG_UNMUTE_STREAM: onUnmuteStream(msg.arg1, msg.arg2); break; + case MSG_DYN_POLICY_MIX_STATE_UPDATE: onDynPolicyMixStateUpdate((String) msg.obj, msg.arg1); break; diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java index 25c84e132804..8195319dd289 100644 --- a/services/core/java/com/android/server/connectivity/ApfFilter.java +++ b/services/core/java/com/android/server/connectivity/ApfFilter.java @@ -29,14 +29,19 @@ import android.util.Log; import android.util.Pair; import com.android.internal.util.HexDump; +import com.android.internal.util.IndentingPrintWriter; import com.android.server.ConnectivityService; import java.io.FileDescriptor; import java.io.IOException; import java.lang.Thread; +import java.net.Inet6Address; +import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; +import java.net.UnknownHostException; import java.nio.ByteBuffer; +import java.nio.BufferUnderflowException; import java.util.ArrayList; import java.util.Arrays; @@ -85,6 +90,7 @@ public class ApfFilter { } private static final String TAG = "ApfFilter"; + private static final boolean VDBG = true; private final ConnectivityService mConnectivityService; private final NetworkAgentInfo mNai; @@ -152,9 +158,14 @@ public class ApfFilter { private static final int ETH_HEADER_LEN = 14; private static final int IPV6_HEADER_LEN = 40; + private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8; + private static final int IPV6_DST_ADDR_OFFSET = ETH_HEADER_LEN + 24; // From RFC4861: private static final int ICMP6_RA_HEADER_LEN = 16; + private static final int ICMP6_RA_CHECKSUM_OFFSET = + ETH_HEADER_LEN + IPV6_HEADER_LEN + 2; + private static final int ICMP6_RA_CHECKSUM_LEN = 2; private static final int ICMP6_RA_OPTION_OFFSET = ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN; private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET = @@ -189,6 +200,66 @@ public class ApfFilter { // When the packet was last captured, in seconds since Unix Epoch long mLastSeen; + // For debugging only. Offsets into the packet where PIOs are. + private final ArrayList<Integer> mPrefixOptionOffsets; + // For debugging only. How many times this RA was seen. + int seenCount = 0; + + + private String IPv6AddresstoString(int pos) { + try { + byte[] array = mPacket.array(); + // Can't just call copyOfRange() and see if it throws, because if it reads past the + // end it pads with zeros instead of throwing. + if (pos < 0 || pos + 16 > array.length || pos + 16 < pos) { + return "???"; + } + byte[] addressBytes = Arrays.copyOfRange(array, pos, pos + 16); + InetAddress address = (Inet6Address) InetAddress.getByAddress(addressBytes); + return address.getHostAddress(); + } catch (UnsupportedOperationException e) { + // array() failed. Cannot happen, mPacket is array-backed and read-write. + return "???"; + } catch (ClassCastException | UnknownHostException e) { + // Cannot happen. + return "???"; + } + } + + // Can't be static because it's in a non-static inner class. + // TODO: Make this final once RA is its own class. + private int uint8(byte b) { + return b & 0xff; + } + + private int uint16(short s) { + return s & 0xffff; + } + + private long uint32(int s) { + return s & 0xffffffff; + } + + public String toString() { + try { + StringBuffer sb = new StringBuffer(); + sb.append(String.format("RA %s -> %s %d ", + IPv6AddresstoString(IPV6_SRC_ADDR_OFFSET), + IPv6AddresstoString(IPV6_DST_ADDR_OFFSET), + uint16(mPacket.getShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET)))); + for (int i: mPrefixOptionOffsets) { + String prefix = IPv6AddresstoString(i + 16); + int length = uint8(mPacket.get(i + 2)); + long valid = mPacket.getInt(i + 4); + long preferred = mPacket.getInt(i + 8); + sb.append(String.format("%s/%d %d/%d ", prefix, length, valid, preferred)); + } + return sb.toString(); + } catch (BufferUnderflowException | IndexOutOfBoundsException e) { + return "<Malformed RA>"; + } + } + /** * Add a binary range of the packet that does not include a lifetime to mNonLifetimes. * Assumes mPacket.position() is as far as we've parsed the packet. @@ -216,10 +287,18 @@ public class ApfFilter { mPacket.clear(); mLastSeen = curTime(); + // Ignore the checksum. + int lastNonLifetimeStart = addNonLifetime(0, + ICMP6_RA_CHECKSUM_OFFSET, + ICMP6_RA_CHECKSUM_LEN); + // Parse router lifetime - int lastNonLifetimeStart = addNonLifetime(0, ICMP6_RA_ROUTER_LIFETIME_OFFSET, + lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart, + ICMP6_RA_ROUTER_LIFETIME_OFFSET, ICMP6_RA_ROUTER_LIFETIME_LEN); + // Parse ICMP6 options + mPrefixOptionOffsets = new ArrayList<>(); mPacket.position(ICMP6_RA_OPTION_OFFSET); while (mPacket.hasRemaining()) { int optionType = ((int)mPacket.get(mPacket.position())) & 0xff; @@ -234,6 +313,7 @@ public class ApfFilter { lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart, ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET, ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN); + mPrefixOptionOffsets.add(mPacket.position()); break; // These three options have the same lifetime offset and size, so process // together: @@ -282,6 +362,12 @@ public class ApfFilter { ByteBuffer byteBuffer = ByteBuffer.wrap(packet); for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) { int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second; + + // The checksum is in mNonLifetimes, but it's not a lifetime. + if (offset == ICMP6_RA_CHECKSUM_OFFSET) { + continue; + } + int lifetimeLength = mNonLifetimes.get(i+1).first - offset; long val; switch (lifetimeLength) { @@ -329,6 +415,10 @@ public class ApfFilter { if ((i + 1) < mNonLifetimes.size()) { Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1); int offset = nonLifetime.first + nonLifetime.second; + // Skip the checksum. + if (offset == ICMP6_RA_CHECKSUM_OFFSET) { + continue; + } int length = nextNonLifetime.first - offset; switch (length) { case 4: gen.addLoad32(Register.R0, offset); break; @@ -363,6 +453,9 @@ public class ApfFilter { // How long should the last installed filter program live for? In seconds. private long mLastInstalledProgramMinLifetime; + // For debugging only. The length in bytes of the last program. + private long mLastInstalledProgramLength; + private void installNewProgram() { if (mRas.size() == 0) return; final byte[] program; @@ -402,7 +495,12 @@ public class ApfFilter { } mLastTimeInstalledProgram = curTime(); mLastInstalledProgramMinLifetime = programMinLifetime; - hexDump("Installing filter: ", program, program.length); + mLastInstalledProgramLength = program.length; + if (VDBG) { + hexDump("Installing filter: ", program, program.length); + } else { + Log.d(TAG, "Installing filter length=" + program.length); + } mConnectivityService.pushApfProgramToNetwork(mNai, program); } @@ -421,16 +519,17 @@ public class ApfFilter { } private void processRa(byte[] packet, int length) { - hexDump("Read packet = ", packet, length); + if (VDBG) hexDump("Read packet = ", packet, length); // Have we seen this RA before? for (int i = 0; i < mRas.size(); i++) { Ra ra = mRas.get(i); if (ra.matches(packet, length)) { - log("matched RA"); + if (VDBG) log("matched RA " + ra); // Update lifetimes. ra.mLastSeen = curTime(); ra.mMinLifetime = ra.minLifetime(packet, length); + ra.seenCount++; // Keep mRas in LRU order so as to prioritize generating filters for recently seen // RAs. LRU prioritizes this because RA filters are generated in order from mRas @@ -448,7 +547,7 @@ public class ApfFilter { // Purge expired RAs. for (int i = 0; i < mRas.size();) { if (mRas.get(i).isExpired()) { - log("expired RA"); + log("Expired RA " + mRas.get(i)); mRas.remove(i); } else { i++; @@ -457,8 +556,9 @@ public class ApfFilter { // TODO: figure out how to proceed when we've received more then MAX_RAS RAs. if (mRas.size() >= MAX_RAS) return; try { - log("adding RA"); - mRas.add(new Ra(packet, length)); + Ra ra = new Ra(packet, length); + log("Adding " + ra); + mRas.add(ra); } catch (Exception e) { Log.e(TAG, "Error parsing RA: " + e); return; @@ -473,8 +573,8 @@ public class ApfFilter { public static void maybeInstall(ConnectivityService connectivityService, NetworkAgentInfo nai) { if (nai.networkMisc == null) return; if (nai.networkMisc.apfVersionSupported == 0) return; - if (nai.networkMisc.maximumApfProgramSize < 200) { - Log.e(TAG, "Uselessly small APF size limit: " + nai.networkMisc.maximumApfProgramSize); + if (nai.networkMisc.maximumApfProgramSize < 512) { + Log.e(TAG, "Unacceptably small APF limit: " + nai.networkMisc.maximumApfProgramSize); return; } // For now only support generating programs for Ethernet frames. If this restriction is @@ -491,9 +591,35 @@ public class ApfFilter { public void shutdown() { if (mReceiveThread != null) { - log("shuting down"); + log("shutting down"); mReceiveThread.halt(); // Also closes socket. mReceiveThread = null; } } + + public void dump(IndentingPrintWriter pw) { + pw.println("APF version: " + mNai.networkMisc.apfVersionSupported); + pw.println("Max program size: " + mNai.networkMisc.maximumApfProgramSize); + pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED")); + if (mLastTimeInstalledProgram == 0) { + pw.println("No program installed."); + return; + } + + pw.println(String.format( + "Last program length %d, installed %ds ago, lifetime %d", + mLastInstalledProgramLength, curTime() - mLastTimeInstalledProgram, + mLastInstalledProgramMinLifetime)); + + pw.println("RA filters:"); + pw.increaseIndent(); + for (Ra ra: mRas) { + pw.println(ra); + pw.increaseIndent(); + pw.println(String.format( + "Seen: %d, last %ds ago", ra.seenCount, curTime() - ra.mLastSeen)); + pw.decreaseIndent(); + } + pw.decreaseIndent(); + } } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index 212e077f4930..03191a0977cc 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -18,12 +18,16 @@ package com.android.server.content; import android.Manifest; import android.accounts.Account; +import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.AppOpsManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.IContentService; import android.content.Intent; +import android.content.IntentFilter; import android.content.ISyncStatusObserver; import android.content.PeriodicSync; import android.content.SyncAdapterType; @@ -32,6 +36,7 @@ import android.content.SyncRequest; import android.content.SyncStatusInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; +import android.content.pm.ProviderInfo; import android.database.IContentObserver; import android.database.sqlite.SQLiteException; import android.net.Uri; @@ -44,30 +49,64 @@ import android.os.ServiceManager; import android.os.SystemProperties; import android.os.UserHandle; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Log; +import android.util.Pair; import android.util.Slog; +import android.util.SparseArray; import android.util.SparseIntArray; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; import java.security.InvalidParameterException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Objects; /** * {@hide} */ public final class ContentService extends IContentService.Stub { private static final String TAG = "ContentService"; + private Context mContext; private boolean mFactoryTest; + private final ObserverNode mRootNode = new ObserverNode(""); + private SyncManager mSyncManager = null; private final Object mSyncManagerLock = new Object(); + /** + * Map from userId to providerPackageName to [clientPackageName, uri] to + * value. This structure is carefully optimized to keep invalidation logic + * as cheap as possible. + */ + @GuardedBy("mCache") + private final SparseArray<ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>>> + mCache = new SparseArray<>(); + + private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final Uri data = intent.getData(); + if (data != null) { + final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, + UserHandle.USER_NULL); + final String packageName = data.getSchemeSpecificPart(); + invalidateCacheLocked(userId, packageName, null); + } + } + }; + private SyncManager getSyncManager() { if (SystemProperties.getBoolean("config.disable_network", false)) { return null; @@ -85,13 +124,15 @@ public final class ContentService extends IContentService.Stub { } @Override - protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + protected synchronized void dump(FileDescriptor fd, PrintWriter pw_, String[] args) { mContext.enforceCallingOrSelfPermission(Manifest.permission.DUMP, "caller doesn't have the DUMP permission"); + final IndentingPrintWriter pw = new IndentingPrintWriter(pw_, " "); + // This makes it so that future permission checks will be in the context of this // process rather than the caller's process. We will restore this before returning. - long identityToken = clearCallingIdentity(); + final long identityToken = clearCallingIdentity(); try { if (mSyncManager == null) { pw.println("No SyncManager created! (Disk full?)"); @@ -132,6 +173,19 @@ public final class ContentService extends IContentService.Stub { pw.print(" Total number of nodes: "); pw.println(counts[0]); pw.print(" Total number of observers: "); pw.println(counts[1]); } + + synchronized (mCache) { + pw.println(); + pw.println("Cached content:"); + pw.increaseIndent(); + for (int i = 0; i < mCache.size(); i++) { + pw.println("User " + mCache.keyAt(i) + ":"); + pw.increaseIndent(); + pw.println(mCache.valueAt(i)); + pw.decreaseIndent(); + } + pw.decreaseIndent(); + } } finally { restoreCallingIdentity(identityToken); } @@ -167,6 +221,15 @@ public final class ContentService extends IContentService.Stub { return getSyncAdapterPackagesForAuthorityAsUser(authority, userId); } }); + + final IntentFilter packageFilter = new IntentFilter(); + packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); + packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); + packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); + packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); + packageFilter.addDataScheme("package"); + mContext.registerReceiverAsUser(mCacheReceiver, UserHandle.ALL, + packageFilter, null, null); } public void systemReady() { @@ -312,6 +375,11 @@ public final class ContentService extends IContentService.Stub { uri.getAuthority()); } } + + synchronized (mCache) { + final String providerPackageName = getProviderPackageName(uri); + invalidateCacheLocked(userHandle, providerPackageName, uri); + } } finally { restoreCallingIdentity(identityToken); } @@ -915,6 +983,86 @@ public final class ContentService extends IContentService.Stub { } } + private @Nullable String getProviderPackageName(Uri uri) { + final ProviderInfo pi = mContext.getPackageManager() + .resolveContentProvider(uri.getAuthority(), 0); + return (pi != null) ? pi.packageName : null; + } + + private ArrayMap<Pair<String, Uri>, Bundle> findOrCreateCacheLocked(int userId, + String providerPackageName) { + ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId); + if (userCache == null) { + userCache = new ArrayMap<>(); + mCache.put(userId, userCache); + } + ArrayMap<Pair<String, Uri>, Bundle> packageCache = userCache.get(providerPackageName); + if (packageCache == null) { + packageCache = new ArrayMap<>(); + userCache.put(providerPackageName, packageCache); + } + return packageCache; + } + + private void invalidateCacheLocked(int userId, String providerPackageName, Uri uri) { + ArrayMap<String, ArrayMap<Pair<String, Uri>, Bundle>> userCache = mCache.get(userId); + if (userCache == null) return; + + ArrayMap<Pair<String, Uri>, Bundle> packageCache = userCache.get(providerPackageName); + if (packageCache == null) return; + + if (uri != null) { + for (int i = 0; i < packageCache.size();) { + final Uri key = packageCache.keyAt(i).second; + if (Objects.equals(key, uri)) { + packageCache.removeAt(i); + } else { + i++; + } + } + } else { + packageCache.clear(); + } + } + + @Override + public void putCache(String packageName, Uri key, Bundle value, int userId) { + enforceCrossUserPermission(userId, TAG); + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG); + mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(), + packageName); + + final String providerPackageName = getProviderPackageName(key); + final Pair<String, Uri> fullKey = Pair.create(packageName, key); + + synchronized (mCache) { + final ArrayMap<Pair<String, Uri>, Bundle> cache = findOrCreateCacheLocked(userId, + providerPackageName); + if (value != null) { + cache.put(fullKey, value); + } else { + cache.remove(fullKey); + } + } + } + + @Override + public Bundle getCache(String packageName, Uri key, int userId) { + enforceCrossUserPermission(userId, TAG); + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG); + mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(), + packageName); + + final String providerPackageName = getProviderPackageName(key); + final Pair<String, Uri> fullKey = Pair.create(packageName, key); + + synchronized (mCache) { + final ArrayMap<Pair<String, Uri>, Bundle> cache = findOrCreateCacheLocked(userId, + providerPackageName); + return cache.get(fullKey); + } + } + public static ContentService main(Context context, boolean factoryTest) { ContentService service = new ContentService(context, factoryTest); ServiceManager.addService(ContentResolver.CONTENT_SERVICE_NAME, service); diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index e1d208eb19fd..e5342ceec1dc 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -78,8 +78,9 @@ import android.util.EventLog; import android.util.Log; import android.util.Pair; import android.util.Slog; -import android.util.SparseArray; +import com.android.server.LocalServices; +import com.android.server.job.JobSchedulerInternal; import com.google.android.collect.Lists; import com.google.android.collect.Maps; @@ -113,9 +114,7 @@ import java.util.Set; * All scheduled syncs will be passed on to JobScheduler as jobs * (See {@link #scheduleSyncOperationH(SyncOperation, long)}. This function schedules a job * with JobScheduler with appropriate delay and constraints (according to backoffs and extras). - * A local copy of each scheduled SyncOperation object is stored in {@link mScheduledSyncs}.This - * acts as a cache, so that we don't have to query JobScheduler every time we want to get a list of - * all scheduled operations. The scheduleSyncOperationH function also assigns a unique jobId to each + * The scheduleSyncOperationH function also assigns a unique jobId to each * SyncOperation. * * Periodic Syncs: @@ -129,14 +128,6 @@ import java.util.Set; * run at a later time. Similarly, when a sync succeeds, backoff is cleared and all associated syncs * are rescheduled. A rescheduled sync will get a new jobId. * - * State of {@link mScheduledSyncs}: - * Every one-off SyncOperation will be put into this SparseArray when it is scheduled with - * JobScheduler. And it will be removed once JobScheduler has started the job. Periodic syncs work - * differently. They will always be present in mScheduledSyncs until the periodic sync is removed. - * This is to ensure that if a request to add a periodic sync comes in, we add a new one only if a - * duplicate doesn't exist. At every point of time, mScheduledSyncs and JobScheduler will show the - * same pending syncs. - * * @hide */ public class SyncManager { @@ -220,6 +211,7 @@ public class SyncManager { private final NotificationManager mNotificationMgr; private final IBatteryStats mBatteryStats; private JobScheduler mJobScheduler; + private JobSchedulerInternal mJobSchedulerInternal; private SyncJobService mSyncJobService; private SyncStorageEngine mSyncStorageEngine; @@ -235,14 +227,13 @@ public class SyncManager { protected SyncAdaptersCache mSyncAdapters; - // Cache of all operations scheduled on the JobScheduler so that JobScheduler doesn't have - // to be queried often. - private SparseArray<SyncOperation> mScheduledSyncs = new SparseArray<SyncOperation>(32); private final Random mRand; - private boolean isJobIdInUseLockedH(int jobId) { - if (mScheduledSyncs.indexOfKey(jobId) >= 0) { - return true; + private boolean isJobIdInUseLockedH(int jobId, List<JobInfo> pendingJobs) { + for (JobInfo job: pendingJobs) { + if (job.getId() == jobId) { + return true; + } } for (ActiveSyncContext asc: mActiveSyncContexts) { if (asc.mSyncOperation.jobId == jobId) { @@ -253,35 +244,25 @@ public class SyncManager { } private int getUnusedJobIdH() { - synchronized (mScheduledSyncs) { - int newJobId; - do { - newJobId = MIN_SYNC_JOB_ID + mRand.nextInt(MAX_SYNC_JOB_ID - MIN_SYNC_JOB_ID); - } while (isJobIdInUseLockedH(newJobId)); - return newJobId; - } + int newJobId; + do { + newJobId = MIN_SYNC_JOB_ID + mRand.nextInt(MAX_SYNC_JOB_ID - MIN_SYNC_JOB_ID); + } while (isJobIdInUseLockedH(newJobId, + mJobSchedulerInternal.getSystemScheduledPendingJobs())); + return newJobId; } - private void addSyncOperationToCache(SyncOperation op) { - synchronized (mScheduledSyncs) { - mScheduledSyncs.put(op.jobId, op); - } - } - - private void removeSyncOperationFromCache(int jobId) { - synchronized (mScheduledSyncs) { - mScheduledSyncs.remove(jobId); - } - } - - private List<SyncOperation> getAllPendingSyncsFromCache() { - synchronized (mScheduledSyncs) { - List<SyncOperation> pending = new ArrayList<SyncOperation>(mScheduledSyncs.size()); - for (int i=0; i<mScheduledSyncs.size(); i++) { - pending.add(mScheduledSyncs.valueAt(i)); + private List<SyncOperation> getAllPendingSyncs() { + verifyJobScheduler(); + List<JobInfo> pendingJobs = mJobSchedulerInternal.getSystemScheduledPendingJobs(); + List<SyncOperation> pendingSyncs = new ArrayList<SyncOperation>(pendingJobs.size()); + for (JobInfo job: pendingJobs) { + SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras()); + if (op != null) { + pendingSyncs.add(op); } - return pending; } + return pendingSyncs; } private final BroadcastReceiver mStorageIntentReceiver = @@ -443,7 +424,7 @@ public class SyncManager { mSyncHandler.postAtFrontOfQueue(new Runnable() { @Override public void run() { - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); Set<String> cleanedKeys = new HashSet<String>(); for (SyncOperation opx: ops) { if (cleanedKeys.contains(opx.key)) { @@ -455,7 +436,6 @@ public class SyncManager { continue; } if (opx.key.equals(opy.key)) { - removeSyncOperationFromCache(opy.jobId); mJobScheduler.cancel(opy.jobId); } } @@ -473,18 +453,16 @@ public class SyncManager { } mJobScheduler = (JobScheduler) mContext.getSystemService( Context.JOB_SCHEDULER_SERVICE); + mJobSchedulerInternal = LocalServices.getService(JobSchedulerInternal.class); // Get all persisted syncs from JobScheduler List<JobInfo> pendingJobs = mJobScheduler.getAllPendingJobs(); - synchronized (mScheduledSyncs) { - for (JobInfo job : pendingJobs) { - SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras()); - if (op != null) { - mScheduledSyncs.put(op.jobId, op); - if (!op.isPeriodic) { - // Set the pending status of this EndPoint to true. Pending icon is - // shown on the settings activity. - mSyncStorageEngine.markPending(op.target, true); - } + for (JobInfo job : pendingJobs) { + SyncOperation op = SyncOperation.maybeCreateFromJobExtras(job.getExtras()); + if (op != null) { + if (!op.isPeriodic) { + // Set the pending status of this EndPoint to true. Pending icon is + // shown on the settings activity. + mSyncStorageEngine.markPending(op.target, true); } } } @@ -707,7 +685,7 @@ public class SyncManager { } private void setAuthorityPendingState(EndPoint info) { - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(info)) { getSyncStorageEngine().markPending(info, true); @@ -927,11 +905,10 @@ public class SyncManager { private void removeSyncsForAuthority(EndPoint info) { verifyJobScheduler(); - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.target.matchesSpec(info)) { - removeSyncOperationFromCache(op.jobId); - getJobScheduler().cancel(op.jobId); + getJobScheduler().cancel(op.jobId); } } } @@ -961,7 +938,7 @@ public class SyncManager { * Get a list of periodic syncs corresponding to the given target. */ public List<PeriodicSync> getPeriodicSyncs(EndPoint target) { - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); List<PeriodicSync> periodicSyncs = new ArrayList<PeriodicSync>(); for (SyncOperation op: ops) { @@ -1145,12 +1122,11 @@ public class SyncManager { * to current backoff and delayUntil values of this EndPoint. */ private void rescheduleSyncs(EndPoint target) { - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); int count = 0; for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(target)) { count++; - removeSyncOperationFromCache(op.jobId); getJobScheduler().cancel(op.jobId); postScheduleSyncMessage(op); } @@ -1251,7 +1227,7 @@ public class SyncManager { int duplicatesCount = 0; long now = SystemClock.elapsedRealtime(); syncOperation.expectedRuntime = now + minDelay; - List<SyncOperation> pending = getAllPendingSyncsFromCache(); + List<SyncOperation> pending = getAllPendingSyncs(); SyncOperation opWithLeastExpectedRuntime = syncOperation; for (SyncOperation op : pending) { if (op.isPeriodic) { @@ -1276,7 +1252,6 @@ public class SyncManager { if (isLoggable) { Slog.v(TAG, "Cancelling duplicate sync " + op); } - removeSyncOperationFromCache(op.jobId); getJobScheduler().cancel(op.jobId); } } @@ -1294,7 +1269,6 @@ public class SyncManager { if (syncOperation.jobId == SyncOperation.NO_JOB_ID) { syncOperation.jobId = getUnusedJobIdH(); } - addSyncOperationToCache(syncOperation); if (isLoggable) { Slog.v(TAG, "scheduling sync operation " + syncOperation.toString()); @@ -1335,10 +1309,9 @@ public class SyncManager { * have null account/provider info to specify all accounts/providers. */ public void clearScheduledSyncOperations(SyncStorageEngine.EndPoint info) { - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(info)) { - removeSyncOperationFromCache(op.jobId); getJobScheduler().cancel(op.jobId); getSyncStorageEngine().markPending(op.target, false); } @@ -1353,11 +1326,10 @@ public class SyncManager { * @param extras extras bundle to uniquely identify sync. */ public void cancelScheduledSyncOperation(SyncStorageEngine.EndPoint info, Bundle extras) { - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(info) && syncExtrasEquals(extras, op.extras, false)) { - removeSyncOperationFromCache(op.jobId); getJobScheduler().cancel(op.jobId); } } @@ -1466,10 +1438,9 @@ public class SyncManager { // Clean up the storage engine database mSyncStorageEngine.doDatabaseCleanup(new Account[0], userId); - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.target.userId == userId) { - removeSyncOperationFromCache(op.jobId); getJobScheduler().cancel(op.jobId); } } @@ -1635,7 +1606,7 @@ public class SyncManager { protected void dumpPendingSyncs(PrintWriter pw) { pw.println("Pending Syncs:"); - List<SyncOperation> pendingSyncs = getAllPendingSyncsFromCache(); + List<SyncOperation> pendingSyncs = getAllPendingSyncs(); int count = 0; for (SyncOperation op: pendingSyncs) { if (!op.isPeriodic) { @@ -1649,7 +1620,7 @@ public class SyncManager { protected void dumpPeriodicSyncs(PrintWriter pw) { pw.println("Periodic Syncs:"); - List<SyncOperation> pendingSyncs = getAllPendingSyncsFromCache(); + List<SyncOperation> pendingSyncs = getAllPendingSyncs(); int count = 0; for (SyncOperation op: pendingSyncs) { if (op.isPeriodic) { @@ -2259,10 +2230,6 @@ public class SyncManager { private boolean tryEnqueueMessageUntilReadyToRun(Message msg) { synchronized (this) { if (!mBootCompleted || !mProvisioned) { - if (msg.what == MESSAGE_START_SYNC) { - SyncOperation op = (SyncOperation) msg.obj; - addSyncOperationToCache(op); - } // Need to copy the message bc looper will recycle it. Message m = Message.obtain(msg); mUnreadyQueue.add(m); @@ -2479,7 +2446,6 @@ public class SyncManager { if (op.isPeriodic) { scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay); } else { - removeSyncOperationFromCache(op.jobId); scheduleSyncOperationH(op, delay); } } @@ -2489,7 +2455,6 @@ public class SyncManager { if (op.isPeriodic) { scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay); } else { - removeSyncOperationFromCache(op.jobId); scheduleSyncOperationH(op, delay); } } @@ -2515,7 +2480,7 @@ public class SyncManager { if (op.isPeriodic) { // Don't allow this periodic to run if a previous instance failed and is currently // scheduled according to some backoff criteria. - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation syncOperation: ops) { if (syncOperation.sourcePeriodicId == op.jobId) { mSyncJobService.callJobFinished(op.jobId, false); @@ -2535,9 +2500,6 @@ public class SyncManager { deferSyncH(op, 0 /* No minimum delay */); return; } - } else { - // Remove SyncOperation entry from mScheduledSyncs cache for non periodic jobs. - removeSyncOperationFromCache(op.jobId); } // Check for conflicting syncs. @@ -2616,10 +2578,9 @@ public class SyncManager { } } - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (!containsAccountAndUser(accounts, op.target.account, op.target.userId)) { - removeSyncOperationFromCache(op.jobId); getJobScheduler().cancel(op.jobId); } } @@ -2665,7 +2626,7 @@ public class SyncManager { + " flexMillis: " + flex + " extras: " + extras.toString()); } - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.isPeriodic && op.target.matchesSpec(target) && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) { @@ -2704,7 +2665,7 @@ public class SyncManager { */ private void removePeriodicSyncInternalH(SyncOperation syncOperation) { // Remove this periodic sync and all one-off syncs initiated by it. - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.sourcePeriodicId == syncOperation.jobId || op.jobId == syncOperation.jobId) { ActiveSyncContext asc = findActiveSyncContextH(syncOperation.jobId); @@ -2712,7 +2673,6 @@ public class SyncManager { mSyncJobService.callJobFinished(syncOperation.jobId, false); runSyncFinishedOrCanceledH(null, asc); } - removeSyncOperationFromCache(op.jobId); getJobScheduler().cancel(op.jobId); } } @@ -2720,7 +2680,7 @@ public class SyncManager { private void removePeriodicSyncH(EndPoint target, Bundle extras) { verifyJobScheduler(); - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.isPeriodic && op.target.matchesSpec(target) && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) { @@ -2896,7 +2856,7 @@ public class SyncManager { private void reschedulePeriodicSyncH(SyncOperation syncOperation) { // Ensure that the periodic sync wasn't removed. SyncOperation periodicSync = null; - List<SyncOperation> ops = getAllPendingSyncsFromCache(); + List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.isPeriodic && syncOperation.matchesPeriodicOperation(op)) { periodicSync = op; diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 088d96e4a6e0..4527f1f2cc19 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -381,8 +381,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; } + final Resources res = getContext().getResources(); if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) { - final Resources res = getContext().getResources(); mInfo.name = res.getString( com.android.internal.R.string.display_manager_built_in_display_name); mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY @@ -416,6 +416,11 @@ final class LocalDisplayAdapter extends DisplayAdapter { if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) { mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; } + + if (!res.getBoolean( + com.android.internal.R.bool.config_localDisplaysMirrorContent)) { + mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; + } } } return mInfo; diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java index 8c12060abc06..603402e32bfb 100644 --- a/services/core/java/com/android/server/hdmi/Constants.java +++ b/services/core/java/com/android/server/hdmi/Constants.java @@ -218,6 +218,9 @@ final class Constants { // True by default. static final String PROPERTY_WAKE_ON_HOTPLUG = "ro.hdmi.wake_on_hotplug"; + // TODO(OEM): Set this to true to enable 'Set Menu Language' feature. False by default. + static final String PROPERTY_SET_MENU_LANGUAGE = "ro.hdmi.set_menu_language"; + // Set to false to allow playback device to go to suspend mode even // when it's an active source. True by default. static final String PROPERTY_KEEP_AWAKE = "persist.sys.hdmi.keep_awake"; diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 39c6732861f9..a36e6710887e 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -46,6 +46,9 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { private static final boolean WAKE_ON_HOTPLUG = SystemProperties.getBoolean(Constants.PROPERTY_WAKE_ON_HOTPLUG, true); + private static final boolean SET_MENU_LANGUAGE = + SystemProperties.getBoolean(Constants.PROPERTY_SET_MENU_LANGUAGE, false); + private boolean mIsActiveSource = false; // Used to keep the device awake while it is the active source. For devices that @@ -316,6 +319,9 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleSetMenuLanguage(HdmiCecMessage message) { assertRunOnServiceThread(); + if (!SET_MENU_LANGUAGE) { + return false; + } try { String iso3Language = new String(message.getParams(), 0, 3, "US-ASCII"); @@ -345,6 +351,7 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice { Slog.w(TAG, "Can't handle <Set Menu Language> of " + iso3Language); return false; } catch (UnsupportedEncodingException e) { + Slog.w(TAG, "Can't handle <Set Menu Language>", e); return false; } } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 459c47f028b5..fed7e4b7a8f9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -419,6 +419,7 @@ public final class HdmiControlService extends SystemService { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_SHUTDOWN); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); getContext().registerReceiver(mHdmiControlBroadcastReceiver, filter); diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java new file mode 100644 index 000000000000..75170ec9acad --- /dev/null +++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2016 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.job; + +import android.app.job.JobInfo; + +import java.util.List; + +/** + * JobScheduler local system service interface. + * {@hide} Only for use within the system server. + */ +public interface JobSchedulerInternal { + + /** + * Returns a list of pending jobs scheduled by the system service. + */ + List<JobInfo> getSystemScheduledPendingJobs(); +} diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index d2b77aab70b8..cee461956f63 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -45,6 +45,7 @@ import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.PowerManager; import android.os.RemoteException; import android.os.ResultReceiver; @@ -505,6 +506,7 @@ public final class JobSchedulerService extends com.android.server.SystemService @Override public void onStart() { + publishLocalService(JobSchedulerInternal.class, new LocalService()); publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub); } @@ -1178,6 +1180,28 @@ public final class JobSchedulerService extends com.android.server.SystemService return -1; } + final class LocalService implements JobSchedulerInternal { + + /** + * Returns a list of all pending jobs. A running job is not considered pending. Periodic + * jobs are always considered pending. + */ + public List<JobInfo> getSystemScheduledPendingJobs() { + synchronized (mLock) { + final List<JobInfo> pendingJobs = new ArrayList<JobInfo>(); + mJobs.forEachJob(Process.SYSTEM_UID, new JobStatusFunctor() { + @Override + public void process(JobStatus job) { + if (job.getJob().isPeriodic() || !isCurrentlyActiveLocked(job)) { + pendingJobs.add(job.getJob()); + } + } + }); + return pendingJobs; + } + } + } + /** * Binder stub trampoline implementation */ diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 9837a566eb2d..55f37b82242f 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -210,6 +210,10 @@ public class JobStore { mJobSet.forEachJob(functor); } + public void forEachJob(int uid, JobStatusFunctor functor) { + mJobSet.forEachJob(uid, functor); + } + public interface JobStatusFunctor { public void process(JobStatus jobStatus); } @@ -870,5 +874,14 @@ public class JobStore { } } } + + public void forEachJob(int uid, JobStatusFunctor functor) { + ArraySet<JobStatus> jobs = mJobs.get(uid); + 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/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java index bd06645b2b16..6ef425a57877 100644 --- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java +++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java @@ -185,7 +185,7 @@ public class ConnectivityController extends StateController implements pw.println("Conn."); pw.println("connected: " + mNetworkConnected + " unmetered: " + mNetworkUnmetered); for (JobStatus js: mTrackedJobs) { - pw.println(String.valueOf(js.hashCode()).substring(0, 3) + ".." + pw.println(String.valueOf(js.getJobId() + "," + js.getUid()) + ": C=" + js.hasConnectivityConstraint() + ", UM=" + js.hasUnmeteredConstraint()); } diff --git a/services/core/java/com/android/server/job/controllers/IdleController.java b/services/core/java/com/android/server/job/controllers/IdleController.java index 7638494eccb2..d9eb45c6026d 100644 --- a/services/core/java/com/android/server/job/controllers/IdleController.java +++ b/services/core/java/com/android/server/job/controllers/IdleController.java @@ -197,7 +197,7 @@ public class IdleController extends StateController { for (int i = 0; i < mTrackedTasks.size(); i++) { final JobStatus js = mTrackedTasks.get(i); pw.print(" "); - pw.print(String.valueOf(js.hashCode()).substring(0, 3)); + pw.print(String.valueOf(js.getJobId() + "," + js.getUid())); pw.println(".."); } } diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java index 620800caaf67..36fa9ec68050 100644 --- a/services/core/java/com/android/server/job/controllers/TimeController.java +++ b/services/core/java/com/android/server/job/controllers/TimeController.java @@ -145,6 +145,9 @@ public class TimeController extends StateController { final long jobDeadline = job.getLatestRunTimeElapsed(); if (jobDeadline <= nowElapsedMillis) { + if (job.hasTimingDelayConstraint()) { + job.setTimingDelayConstraintSatisfied(true); + } job.setDeadlineConstraintSatisfied(true); mStateChangedListener.onRunJobNow(job); it.remove(); @@ -281,7 +284,7 @@ public class TimeController extends StateController { + "s"); pw.println("Tracking:"); for (JobStatus ts : mTrackedJobs) { - pw.println(String.valueOf(ts.hashCode()).substring(0, 3) + ".." + pw.println(String.valueOf(ts.getJobId() + "," + ts.getUid()) + ": (" + (ts.hasTimingDelayConstraint() ? ts.getEarliestRunTime() : "N/A") + ", " + (ts.hasDeadlineConstraint() ?ts.getLatestRunTimeElapsed() : "N/A") + ")"); diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index d986e94b0253..673dd8fbbd66 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -17,8 +17,8 @@ package com.android.server.net; import static android.net.NetworkStats.IFACE_ALL; -import static android.net.NetworkStats.ROAMING_DEFAULT; -import static android.net.NetworkStats.ROAMING_ROAMING; +import static android.net.NetworkStats.ROAMING_NO; +import static android.net.NetworkStats.ROAMING_YES; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; @@ -242,7 +242,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; - entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_ROAMING : ROAMING_DEFAULT; + entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; entry.rxBytes = historyEntry.rxBytes; entry.rxPackets = historyEntry.rxPackets; entry.txBytes = historyEntry.txBytes; diff --git a/services/core/java/com/android/server/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java index b13fec19cc66..5bc9b1c71f68 100644 --- a/services/core/java/com/android/server/notification/EventConditionProvider.java +++ b/services/core/java/com/android/server/notification/EventConditionProvider.java @@ -44,6 +44,8 @@ import com.android.server.notification.CalendarTracker.CheckEventResult; import com.android.server.notification.NotificationManagerService.DumpFilter; import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; /** * Built-in zen condition provider for calendar event-based conditions. @@ -96,10 +98,12 @@ public class EventConditionProvider extends SystemConditionProviderService { pw.print(" mRegistered="); pw.println(mRegistered); pw.print(" mBootComplete="); pw.println(mBootComplete); dumpUpcomingTime(pw, "mNextAlarmTime", mNextAlarmTime, System.currentTimeMillis()); - pw.println(" mSubscriptions="); - for (Uri conditionId : mSubscriptions) { - pw.print(" "); - pw.println(conditionId); + synchronized (mSubscriptions) { + pw.println(" mSubscriptions="); + for (Uri conditionId : mSubscriptions) { + pw.print(" "); + pw.println(conditionId); + } } pw.println(" mTrackers="); for (int i = 0; i < mTrackers.size(); i++) { @@ -142,19 +146,23 @@ public class EventConditionProvider extends SystemConditionProviderService { public void onSubscribe(Uri conditionId) { if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId); if (!ZenModeConfig.isValidEventConditionId(conditionId)) { - notifyCondition(conditionId, Condition.STATE_FALSE, "badCondition"); + notifyCondition(createCondition(conditionId, Condition.STATE_FALSE)); return; } - if (mSubscriptions.add(conditionId)) { - evaluateSubscriptions(); + synchronized (mSubscriptions) { + if (mSubscriptions.add(conditionId)) { + evaluateSubscriptions(); + } } } @Override public void onUnsubscribe(Uri conditionId) { if (DEBUG) Slog.d(TAG, "onUnsubscribe " + conditionId); - if (mSubscriptions.remove(conditionId)) { - evaluateSubscriptions(); + synchronized (mSubscriptions) { + if (mSubscriptions.remove(conditionId)) { + evaluateSubscriptions(); + } } } @@ -198,51 +206,61 @@ public class EventConditionProvider extends SystemConditionProviderService { return; } final long now = System.currentTimeMillis(); - for (int i = 0; i < mTrackers.size(); i++) { - mTrackers.valueAt(i).setCallback(mSubscriptions.isEmpty() ? null : mTrackerCallback); - } - setRegistered(!mSubscriptions.isEmpty()); - long reevaluateAt = 0; - for (Uri conditionId : mSubscriptions) { - final EventInfo event = ZenModeConfig.tryParseEventConditionId(conditionId); - if (event == null) { - notifyCondition(conditionId, Condition.STATE_FALSE, "badConditionId"); - continue; + List<Condition> conditionsToNotify = new ArrayList<>(); + synchronized (mSubscriptions) { + for (int i = 0; i < mTrackers.size(); i++) { + mTrackers.valueAt(i).setCallback( + mSubscriptions.isEmpty() ? null : mTrackerCallback); } - CheckEventResult result = null; - if (event.calendar == null) { // any calendar - // event could exist on any tracker - for (int i = 0; i < mTrackers.size(); i++) { - final CalendarTracker tracker = mTrackers.valueAt(i); - final CheckEventResult r = tracker.checkEvent(event, now); - if (result == null) { - result = r; - } else { - result.inEvent |= r.inEvent; - result.recheckAt = Math.min(result.recheckAt, r.recheckAt); + setRegistered(!mSubscriptions.isEmpty()); + long reevaluateAt = 0; + for (Uri conditionId : mSubscriptions) { + final EventInfo event = ZenModeConfig.tryParseEventConditionId(conditionId); + if (event == null) { + conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE)); + continue; + } + CheckEventResult result = null; + if (event.calendar == null) { // any calendar + // event could exist on any tracker + for (int i = 0; i < mTrackers.size(); i++) { + final CalendarTracker tracker = mTrackers.valueAt(i); + final CheckEventResult r = tracker.checkEvent(event, now); + if (result == null) { + result = r; + } else { + result.inEvent |= r.inEvent; + result.recheckAt = Math.min(result.recheckAt, r.recheckAt); + } + } + } else { + // event should exist on one tracker + final int userId = EventInfo.resolveUserId(event.userId); + final CalendarTracker tracker = mTrackers.get(userId); + if (tracker == null) { + Slog.w(TAG, "No calendar tracker found for user " + userId); + conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE)); + continue; } + result = tracker.checkEvent(event, now); } - } else { - // event should exist on one tracker - final int userId = EventInfo.resolveUserId(event.userId); - final CalendarTracker tracker = mTrackers.get(userId); - if (tracker == null) { - Slog.w(TAG, "No calendar tracker found for user " + userId); - notifyCondition(conditionId, Condition.STATE_FALSE, "badUserId"); + if (result.recheckAt != 0 + && (reevaluateAt == 0 || result.recheckAt < reevaluateAt)) { + reevaluateAt = result.recheckAt; + } + if (!result.inEvent) { + conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE)); continue; } - result = tracker.checkEvent(event, now); - } - if (result.recheckAt != 0 && (reevaluateAt == 0 || result.recheckAt < reevaluateAt)) { - reevaluateAt = result.recheckAt; + conditionsToNotify.add(createCondition(conditionId, Condition.STATE_TRUE)); } - if (!result.inEvent) { - notifyCondition(conditionId, Condition.STATE_FALSE, "!inEventNow"); - continue; + rescheduleAlarm(now, reevaluateAt); + } + for (Condition condition : conditionsToNotify) { + if (condition != null) { + notifyCondition(condition); } - notifyCondition(conditionId, Condition.STATE_TRUE, "inEventNow"); } - rescheduleAlarm(now, reevaluateAt); if (DEBUG) Slog.d(TAG, "evaluateSubscriptions took " + (System.currentTimeMillis() - now)); } @@ -266,12 +284,6 @@ public class EventConditionProvider extends SystemConditionProviderService { alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent); } - private void notifyCondition(Uri conditionId, int state, String reason) { - if (DEBUG) Slog.d(TAG, "notifyCondition " + conditionId + " " - + Condition.stateToString(state) + " reason=" + reason); - notifyCondition(createCondition(conditionId, state)); - } - private Condition createCondition(Uri id, int state) { final String summary = NOT_SHOWN; final String line1 = NOT_SHOWN; diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 6cf3940e004c..6d9fed46102b 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -238,7 +238,7 @@ abstract public class ManagedServices { rebuildRestoredPackages(); } // make sure we're still bound to any of our services who may have just upgraded - rebindServices(); + rebindServices(false); } } @@ -249,13 +249,13 @@ abstract public class ManagedServices { if (DEBUG) Slog.d(TAG, "Current profile IDs didn't change, skipping rebindServices()."); return; } - rebindServices(); + rebindServices(true); } public void onUserUnlocked(int user) { if (DEBUG) Slog.d(TAG, "onUserUnlocked u=" + user); rebuildRestoredPackages(); - rebindServices(); + rebindServices(false); } public ManagedServiceInfo getServiceFromTokenLocked(IInterface service) { @@ -543,7 +543,7 @@ abstract public class ManagedServices { * Called whenever packages change, the user switches, or the secure setting * is altered. (For example in response to USER_SWITCHED in our broadcast receiver) */ - private void rebindServices() { + private void rebindServices(boolean forceRebind) { if (DEBUG) Slog.d(TAG, "rebindServices"); final int[] userIds = mUserProfiles.getCurrentProfileIds(); final int nUserIds = userIds.length; @@ -559,15 +559,15 @@ abstract public class ManagedServices { final SparseArray<Set<ComponentName>> toAdd = new SparseArray<>(); synchronized (mMutex) { - // Potentially unbind automatically bound services, retain system services. + // Rebind to non-system services if user switched for (ManagedServiceInfo service : mServices) { if (!service.isSystem && !service.isGuest(this)) { removableBoundServices.add(service); } } - final ArraySet<ComponentName> newEnabled = new ArraySet<>(); - final ArraySet<String> newPackages = new ArraySet<>(); + mEnabledServicesForCurrentProfiles.clear(); + mEnabledServicesPackageNames.clear(); for (int i = 0; i < nUserIds; ++i) { // decode the list of components @@ -591,15 +591,13 @@ abstract public class ManagedServices { toAdd.put(userIds[i], add); - newEnabled.addAll(userComponents); + mEnabledServicesForCurrentProfiles.addAll(userComponents); for (int j = 0; j < userComponents.size(); j++) { final ComponentName component = userComponents.valueAt(j); - newPackages.add(component.getPackageName()); + mEnabledServicesPackageNames.add(component.getPackageName()); } } - mEnabledServicesForCurrentProfiles = newEnabled; - mEnabledServicesPackageNames = newPackages; } for (ManagedServiceInfo info : removableBoundServices) { @@ -607,11 +605,11 @@ abstract public class ManagedServices { final int oldUser = info.userid; final Set<ComponentName> allowedComponents = toAdd.get(info.userid); if (allowedComponents != null) { - if (allowedComponents.contains(component)) { + if (allowedComponents.contains(component) && !forceRebind) { // Already bound, don't need to bind again. allowedComponents.remove(component); } else { - // No longer allowed to be bound. + // No longer allowed to be bound, or must rebind. Slog.v(TAG, "disabling " + getCaption() + " for user " + oldUser + ": " + component); unregisterService(component, oldUser); @@ -622,8 +620,7 @@ abstract public class ManagedServices { for (int i = 0; i < nUserIds; ++i) { final Set<ComponentName> add = toAdd.get(userIds[i]); for (ComponentName component : add) { - Slog.v(TAG, "enabling " + getCaption() + " for user " + userIds[i] + ": " - + component); + Slog.v(TAG, "enabling " + getCaption() + " for " + userIds[i] + ": " + component); registerService(component, userIds[i]); } } @@ -859,7 +856,7 @@ abstract public class ManagedServices { if (uri == null || mSecureSettingsUri.equals(uri)) { if (DEBUG) Slog.d(TAG, "Setting changed: mSecureSettingsUri=" + mSecureSettingsUri + " / uri=" + uri); - rebindServices(); + rebindServices(false); rebuildRestoredPackages(); } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 516602e55e5c..e8a65287b52b 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -43,6 +43,7 @@ import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; import android.Manifest; +import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AppGlobals; @@ -155,9 +156,11 @@ import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; @@ -218,7 +221,7 @@ public class NotificationManagerService extends SystemService { private IActivityManager mAm; AudioManager mAudioManager; AudioManagerInternal mAudioManagerInternal; - StatusBarManagerInternal mStatusBar; + @Nullable StatusBarManagerInternal mStatusBar; Vibrator mVibrator; private VrManagerInternal mVrManagerInternal; @@ -274,9 +277,6 @@ public class NotificationManagerService extends SystemService { // Persistent storage for notification policy private AtomicFile mPolicyFile; - // Temporary holder for <blocked-packages> config coming from old policy files. - private HashSet<String> mBlockedPackages = new HashSet<String>(); - private static final int DB_VERSION = 1; private static final String TAG_NOTIFICATION_POLICY = "notification-policy"; @@ -352,27 +352,7 @@ public class NotificationManagerService extends SystemService { final XmlPullParser parser = Xml.newPullParser(); parser.setInput(stream, StandardCharsets.UTF_8.name()); - int type; - String tag; - int version = DB_VERSION; - while ((type = parser.next()) != END_DOCUMENT) { - tag = parser.getName(); - if (type == START_TAG) { - if (TAG_NOTIFICATION_POLICY.equals(tag)) { - version = Integer.parseInt( - parser.getAttributeValue(null, ATTR_VERSION)); - } else if (TAG_BLOCKED_PKGS.equals(tag)) { - while ((type = parser.next()) != END_DOCUMENT) { - tag = parser.getName(); - if (TAG_PACKAGE.equals(tag)) { - mBlockedPackages.add( - parser.getAttributeValue(null, ATTR_NAME)); - } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) { - break; - } - } - } - } + while (parser.next() != END_DOCUMENT) { mZenModeHelper.readXml(parser, forRestore); mRankingHelper.readXml(parser, forRestore); } @@ -381,7 +361,6 @@ public class NotificationManagerService extends SystemService { private void loadPolicyFile() { if (DBG) Slog.d(TAG, "loadPolicyFile"); synchronized(mPolicyFile) { - mBlockedPackages.clear(); FileInputStream infile = null; try { @@ -795,7 +774,9 @@ public class NotificationManagerService extends SystemService { } else if (action.equals(Intent.ACTION_USER_PRESENT)) { // turn off LED when user passes through lock screen mNotificationLight.turnOff(); - mStatusBar.notificationLightOff(); + if (mStatusBar != null) { + mStatusBar.notificationLightOff(); + } } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL); // reload per-user settings @@ -859,7 +840,9 @@ public class NotificationManagerService extends SystemService { private final Runnable mBuzzBeepBlinked = new Runnable() { @Override public void run() { - mStatusBar.buzzBeepBlinked(); + if (mStatusBar != null) { + mStatusBar.buzzBeepBlinked(); + } } }; @@ -935,7 +918,7 @@ public class NotificationManagerService extends SystemService { final File systemDir = new File(Environment.getDataDirectory(), "system"); mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml")); - importOldBlockDb(); + syncBlockDb(); // This is a MangedServices object that keeps track of the listeners. mListeners = new NotificationListeners(); @@ -943,22 +926,12 @@ public class NotificationManagerService extends SystemService { // This is a MangedServices object that keeps track of the ranker. mRankerServices = new NotificationRankers(); // Find the updatable ranker and register it. - Set<ComponentName> rankerComponents = mRankerServices.queryPackageForServices( - mRankerServicePackageName, UserHandle.USER_SYSTEM, null); - Iterator<ComponentName> iterator = rankerComponents.iterator(); - if (iterator.hasNext()) { - ComponentName rankerComponent = iterator.next(); - if (iterator.hasNext()) { - Slog.e(TAG, "found multiple ranker services:" + rankerComponents); - } else { - mRankerServices.registerSystemService(rankerComponent, UserHandle.USER_SYSTEM); - } - } else { - Slog.w(TAG, "could not start ranker service: none found"); - } + mRankerServices.registerRanker(); mStatusBar = getLocalService(StatusBarManagerInternal.class); - mStatusBar.setNotificationDelegate(mNotificationDelegate); + if (mStatusBar != null) { + mStatusBar.setNotificationDelegate(mNotificationDelegate); + } final LightsManager lights = getLocalService(LightsManager.class); mNotificationLight = lights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS); @@ -1045,22 +1018,43 @@ public class NotificationManagerService extends SystemService { } /** - * Read the old XML-based app block database and import those blockages into the AppOps system. + * Make sure the XML config and the the AppOps system agree about blocks. */ - private void importOldBlockDb() { + private void syncBlockDb() { loadPolicyFile(); - PackageManager pm = getContext().getPackageManager(); - for (String pkg : mBlockedPackages) { - PackageInfo info = null; - try { - info = pm.getPackageInfo(pkg, 0); - setNotificationsEnabledForPackageImpl(pkg, info.applicationInfo.uid, false); - } catch (NameNotFoundException e) { - // forget you + // sync bans from ranker into app opps + Map<Integer, String> packageBans = mRankingHelper.getPackageBans(); + for(Entry<Integer, String> ban : packageBans.entrySet()) { + final int uid = ban.getKey(); + final String packageName = ban.getValue(); + setNotificationsEnabledForPackageImpl(packageName, uid, false); + } + + // sync bans from app opps into ranker + packageBans.clear(); + for (UserInfo user : UserManager.get(getContext()).getUsers()) { + final int userId = user.getUserHandle().getIdentifier(); + final PackageManager packageManager = getContext().getPackageManager(); + List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId); + final int packageCount = packages.size(); + for (int p = 0; p < packageCount; p++) { + final String packageName = packages.get(p).packageName; + try { + final int uid = packageManager.getPackageUidAsUser(packageName, userId); + if (!checkNotificationOp(packageName, uid)) { + packageBans.put(uid, packageName); + } + } catch (NameNotFoundException e) { + // forget you + } } } - mBlockedPackages.clear(); + for (Entry<Integer, String> ban : packageBans.entrySet()) { + mRankingHelper.setImportance(ban.getValue(), ban.getKey(), IMPORTANCE_NONE); + } + + savePolicyFile(); } @Override @@ -1265,6 +1259,8 @@ public class NotificationManagerService extends SystemService { checkCallerIsSystem(); setNotificationsEnabledForPackageImpl(pkg, uid, enabled); + mRankingHelper.setEnabled(pkg, uid, enabled); + savePolicyFile(); } /** @@ -1811,6 +1807,16 @@ public class NotificationManagerService extends SystemService { message); } + private void enforceSystemOrSystemUIOrSamePackage(String pkg, String message) { + try { + checkCallerIsSystemOrSameApp(pkg); + } catch (SecurityException e) { + getContext().enforceCallingPermission( + android.Manifest.permission.STATUS_BAR_SERVICE, + message); + } + } + private void enforcePolicyAccess(int uid, String method) { if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission( android.Manifest.permission.MANAGE_NOTIFICATIONS)) { @@ -1937,8 +1943,9 @@ public class NotificationManagerService extends SystemService { } @Override - public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) { - enforceSystemOrSystemUI("request policy access status for another package"); + public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) {; + enforceSystemOrSystemUIOrSamePackage(pkg, + "request policy access status for another package"); return checkPackagePolicyAccess(pkg); } @@ -2027,21 +2034,8 @@ public class NotificationManagerService extends SystemService { JSONObject dump = new JSONObject(); try { dump.put("service", "Notification Manager"); - JSONArray bans = new JSONArray(); - try { - ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter); - for (Integer userId : packageBans.keySet()) { - for (String packageName : packageBans.get(userId)) { - JSONObject ban = new JSONObject(); - ban.put("userId", userId); - ban.put("packageName", packageName); - bans.put(ban); - } - } - } catch (NameNotFoundException e) { - // pass - } - dump.put("bans", bans); + dump.put("bans", mRankingHelper.dumpBansJson(filter)); + dump.put("ranking", mRankingHelper.dumpJson(filter)); dump.put("stats", mUsageStats.dumpJson(filter)); } catch (JSONException e) { e.printStackTrace(); @@ -2168,47 +2162,9 @@ public class NotificationManagerService extends SystemService { r.dump(pw, " ", getContext(), filter.redact); } } - - try { - pw.println("\n Banned Packages:"); - ArrayMap<Integer, ArrayList<String>> packageBans = getPackageBans(filter); - for (Integer userId : packageBans.keySet()) { - for (String packageName : packageBans.get(userId)) { - pw.println(" " + userId + ": " + packageName); - } - } - } catch (NameNotFoundException e) { - // pass - } } } - private ArrayMap<Integer, ArrayList<String>> getPackageBans(DumpFilter filter) - throws NameNotFoundException { - ArrayMap<Integer, ArrayList<String>> packageBans = new ArrayMap<>(); - ArrayList<String> packageNames = new ArrayList<>(); - for (UserInfo user : UserManager.get(getContext()).getUsers()) { - final int userId = user.getUserHandle().getIdentifier(); - final PackageManager packageManager = getContext().getPackageManager(); - List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId); - final int packageCount = packages.size(); - for (int p = 0; p < packageCount; p++) { - final String packageName = packages.get(p).packageName; - if (filter == null || filter.matches(packageName)) { - final int uid = packageManager.getPackageUidAsUser(packageName, userId); - if (!checkNotificationOp(packageName, uid)) { - packageNames.add(packageName); - } - } - } - if (!packageNames.isEmpty()) { - packageBans.put(userId, packageNames); - packageNames = new ArrayList<>(); - } - } - return packageBans; - } - /** * The private API only accessible to the system process. */ @@ -2291,6 +2247,11 @@ public class NotificationManagerService extends SystemService { // Sanitize inputs notification.priority = clamp(notification.priority, Notification.PRIORITY_MIN, Notification.PRIORITY_MAX); + if (notification.extras != null) { + // If the remote side sent us bad parcelables, they won't get the + // results they want, which is their loss. + notification.extras.setDefusable(true); + } // setup local book-keeping final StatusBarNotification n = new StatusBarNotification( @@ -3301,7 +3262,9 @@ public class NotificationManagerService extends SystemService { // Don't flash while we are in a call or screen is on if (ledNotification == null || mInCall || mScreenOn) { mNotificationLight.turnOff(); - mStatusBar.notificationLightOff(); + if (mStatusBar != null) { + mStatusBar.notificationLightOff(); + } } else { final Notification ledno = ledNotification.sbn.getNotification(); int ledARGB = ledno.ledARGB; @@ -3317,8 +3280,10 @@ public class NotificationManagerService extends SystemService { mNotificationLight.setFlashing(ledARGB, Light.LIGHT_FLASH_TIMED, ledOnMS, ledOffMS); } - // let SystemUI make an independent decision - mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS); + if (mStatusBar != null) { + // let SystemUI make an independent decision + mStatusBar.notificationLightPulse(ledARGB, ledOnMS, ledOffMS); + } } } @@ -3574,6 +3539,45 @@ public class NotificationManagerService extends SystemService { public boolean isEnabled() { return !mServices.isEmpty(); } + + @Override + public void onUserSwitched(int user) { + for (ManagedServiceInfo info : mServices) { + unregisterService(info.service, info.userid); + } + registerRanker(); + } + + @Override + public void onPackagesChanged(boolean queryReplace, String[] pkgList) { + if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace + + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))); + + if (pkgList != null && (pkgList.length > 0)) { + for (String pkgName : pkgList) { + if (mRankerServicePackageName.equals(pkgName)) { + registerRanker(); + } + } + } + } + + protected void registerRanker() { + // Find the updatable ranker and register it. + Set<ComponentName> rankerComponents = queryPackageForServices( + mRankerServicePackageName, UserHandle.USER_SYSTEM, null); + Iterator<ComponentName> iterator = rankerComponents.iterator(); + if (iterator.hasNext()) { + ComponentName rankerComponent = iterator.next(); + if (iterator.hasNext()) { + Slog.e(TAG, "found multiple ranker services:" + rankerComponents); + } else { + registerSystemService(rankerComponent, UserHandle.USER_SYSTEM); + } + } else { + Slog.w(TAG, "could not start ranker service: none found"); + } + } } public class NotificationListeners extends ManagedServices { diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java index 538f95146efc..b853417ac0b3 100644 --- a/services/core/java/com/android/server/notification/NotificationUsageStats.java +++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java @@ -336,6 +336,13 @@ public class NotificationUsageStats { finalImportance = new ImportanceHistogram(context, "note_importance_"); } + public AggregatedStats getPrevious() { + if (mPrevious == null) { + mPrevious = new AggregatedStats(mContext, key); + } + return mPrevious; + } + public void countApiUse(NotificationRecord record) { final Notification n = record.getNotification(); if (n.actions != null) { @@ -411,67 +418,64 @@ public class NotificationUsageStats { } public void emit() { - if (mPrevious == null) { - mPrevious = new AggregatedStats(null, key); - } - - maybeCount("note_post", (numPostedByApp - mPrevious.numPostedByApp)); - maybeCount("note_update", (numUpdatedByApp - mPrevious.numUpdatedByApp)); - maybeCount("note_remove", (numRemovedByApp - mPrevious.numRemovedByApp)); - maybeCount("note_with_people", (numWithValidPeople - mPrevious.numWithValidPeople)); - maybeCount("note_with_stars", (numWithStaredPeople - mPrevious.numWithStaredPeople)); - maybeCount("people_cache_hit", (numPeopleCacheHit - mPrevious.numPeopleCacheHit)); - maybeCount("people_cache_miss", (numPeopleCacheMiss - mPrevious.numPeopleCacheMiss)); - maybeCount("note_blocked", (numBlocked - mPrevious.numBlocked)); - maybeCount("note_suspended", (numSuspendedByAdmin - mPrevious.numSuspendedByAdmin)); - maybeCount("note_with_actions", (numWithActions - mPrevious.numWithActions)); - maybeCount("note_private", (numPrivate - mPrevious.numPrivate)); - maybeCount("note_secret", (numSecret - mPrevious.numSecret)); - maybeCount("note_interupt", (numInterrupt - mPrevious.numInterrupt)); - maybeCount("note_big_text", (numWithBigText - mPrevious.numWithBigText)); - maybeCount("note_big_pic", (numWithBigPicture - mPrevious.numWithBigPicture)); - maybeCount("note_fg", (numForegroundService - mPrevious.numForegroundService)); - maybeCount("note_ongoing", (numOngoing - mPrevious.numOngoing)); - maybeCount("note_auto", (numAutoCancel - mPrevious.numAutoCancel)); - maybeCount("note_large_icon", (numWithLargeIcon - mPrevious.numWithLargeIcon)); - maybeCount("note_inbox", (numWithInbox - mPrevious.numWithInbox)); - maybeCount("note_media", (numWithMediaSession - mPrevious.numWithMediaSession)); - maybeCount("note_title", (numWithTitle - mPrevious.numWithTitle)); - maybeCount("note_text", (numWithText - mPrevious.numWithText)); - maybeCount("note_sub_text", (numWithSubText - mPrevious.numWithSubText)); - maybeCount("note_info_text", (numWithInfoText - mPrevious.numWithInfoText)); - noisyImportance.maybeCount(mPrevious.noisyImportance); - quietImportance.maybeCount(mPrevious.quietImportance); - finalImportance.maybeCount(mPrevious.finalImportance); - - mPrevious.numPostedByApp = numPostedByApp; - mPrevious.numUpdatedByApp = numUpdatedByApp; - mPrevious.numRemovedByApp = numRemovedByApp; - mPrevious.numPeopleCacheHit = numPeopleCacheHit; - mPrevious.numPeopleCacheMiss = numPeopleCacheMiss; - mPrevious.numWithStaredPeople = numWithStaredPeople; - mPrevious.numWithValidPeople = numWithValidPeople; - mPrevious.numBlocked = numBlocked; - mPrevious.numSuspendedByAdmin = numSuspendedByAdmin; - mPrevious.numWithActions = numWithActions; - mPrevious.numPrivate = numPrivate; - mPrevious.numSecret = numSecret; - mPrevious.numInterrupt = numInterrupt; - mPrevious.numWithBigText = numWithBigText; - mPrevious.numWithBigPicture = numWithBigPicture; - mPrevious.numForegroundService = numForegroundService; - mPrevious.numOngoing = numOngoing; - mPrevious.numAutoCancel = numAutoCancel; - mPrevious.numWithLargeIcon = numWithLargeIcon; - mPrevious.numWithInbox = numWithInbox; - mPrevious.numWithMediaSession = numWithMediaSession; - mPrevious.numWithTitle = numWithTitle; - mPrevious.numWithText = numWithText; - mPrevious.numWithSubText = numWithSubText; - mPrevious.numWithInfoText = numWithInfoText; - noisyImportance.update(mPrevious.noisyImportance); - quietImportance.update(mPrevious.quietImportance); - finalImportance.update(mPrevious.finalImportance); + AggregatedStats previous = getPrevious(); + maybeCount("note_post", (numPostedByApp - previous.numPostedByApp)); + maybeCount("note_update", (numUpdatedByApp - previous.numUpdatedByApp)); + maybeCount("note_remove", (numRemovedByApp - previous.numRemovedByApp)); + maybeCount("note_with_people", (numWithValidPeople - previous.numWithValidPeople)); + maybeCount("note_with_stars", (numWithStaredPeople - previous.numWithStaredPeople)); + maybeCount("people_cache_hit", (numPeopleCacheHit - previous.numPeopleCacheHit)); + maybeCount("people_cache_miss", (numPeopleCacheMiss - previous.numPeopleCacheMiss)); + maybeCount("note_blocked", (numBlocked - previous.numBlocked)); + maybeCount("note_suspended", (numSuspendedByAdmin - previous.numSuspendedByAdmin)); + maybeCount("note_with_actions", (numWithActions - previous.numWithActions)); + maybeCount("note_private", (numPrivate - previous.numPrivate)); + maybeCount("note_secret", (numSecret - previous.numSecret)); + maybeCount("note_interupt", (numInterrupt - previous.numInterrupt)); + maybeCount("note_big_text", (numWithBigText - previous.numWithBigText)); + maybeCount("note_big_pic", (numWithBigPicture - previous.numWithBigPicture)); + maybeCount("note_fg", (numForegroundService - previous.numForegroundService)); + maybeCount("note_ongoing", (numOngoing - previous.numOngoing)); + maybeCount("note_auto", (numAutoCancel - previous.numAutoCancel)); + maybeCount("note_large_icon", (numWithLargeIcon - previous.numWithLargeIcon)); + maybeCount("note_inbox", (numWithInbox - previous.numWithInbox)); + maybeCount("note_media", (numWithMediaSession - previous.numWithMediaSession)); + maybeCount("note_title", (numWithTitle - previous.numWithTitle)); + maybeCount("note_text", (numWithText - previous.numWithText)); + maybeCount("note_sub_text", (numWithSubText - previous.numWithSubText)); + maybeCount("note_info_text", (numWithInfoText - previous.numWithInfoText)); + noisyImportance.maybeCount(previous.noisyImportance); + quietImportance.maybeCount(previous.quietImportance); + finalImportance.maybeCount(previous.finalImportance); + + previous.numPostedByApp = numPostedByApp; + previous.numUpdatedByApp = numUpdatedByApp; + previous.numRemovedByApp = numRemovedByApp; + previous.numPeopleCacheHit = numPeopleCacheHit; + previous.numPeopleCacheMiss = numPeopleCacheMiss; + previous.numWithStaredPeople = numWithStaredPeople; + previous.numWithValidPeople = numWithValidPeople; + previous.numBlocked = numBlocked; + previous.numSuspendedByAdmin = numSuspendedByAdmin; + previous.numWithActions = numWithActions; + previous.numPrivate = numPrivate; + previous.numSecret = numSecret; + previous.numInterrupt = numInterrupt; + previous.numWithBigText = numWithBigText; + previous.numWithBigPicture = numWithBigPicture; + previous.numForegroundService = numForegroundService; + previous.numOngoing = numOngoing; + previous.numAutoCancel = numAutoCancel; + previous.numWithLargeIcon = numWithLargeIcon; + previous.numWithInbox = numWithInbox; + previous.numWithMediaSession = numWithMediaSession; + previous.numWithTitle = numWithTitle; + previous.numWithText = numWithText; + previous.numWithSubText = numWithSubText; + previous.numWithInfoText = numWithInfoText; + noisyImportance.update(previous.noisyImportance); + quietImportance.update(previous.quietImportance); + finalImportance.update(previous.finalImportance); } void maybeCount(String name, int value) { @@ -553,6 +557,7 @@ public class NotificationUsageStats { } public JSONObject dumpJson() throws JSONException { + AggregatedStats previous = getPrevious(); JSONObject dump = new JSONObject(); dump.put("key", key); dump.put("duration", SystemClock.elapsedRealtime() - mCreated); @@ -581,9 +586,9 @@ public class NotificationUsageStats { maybePut(dump, "numWithText", numWithText); maybePut(dump, "numWithSubText", numWithSubText); maybePut(dump, "numWithInfoText", numWithInfoText); - noisyImportance.maybePut(dump, mPrevious.noisyImportance); - quietImportance.maybePut(dump, mPrevious.quietImportance); - finalImportance.maybePut(dump, mPrevious.finalImportance); + noisyImportance.maybePut(dump, previous.noisyImportance); + quietImportance.maybePut(dump, previous.quietImportance); + finalImportance.maybePut(dump, previous.finalImportance); return dump; } diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index fd96a784122f..4a41705ea321 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -25,6 +25,11 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Slog; +import com.android.server.notification.NotificationManagerService.DumpFilter; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -33,6 +38,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; public class RankingHelper implements RankingConfig { private static final String TAG = "RankingHelper"; @@ -358,6 +365,14 @@ public class RankingHelper implements RankingConfig { updateConfig(); } + public void setEnabled(String packageName, int uid, boolean enabled) { + boolean wasEnabled = getImportance(packageName, uid) != Ranking.IMPORTANCE_NONE; + if (wasEnabled == enabled) { + return; + } + setImportance(packageName, uid, enabled ? DEFAULT_IMPORTANCE : Ranking.IMPORTANCE_NONE); + } + public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) { if (filter == null) { final int N = mSignalExtractors.length; @@ -398,17 +413,97 @@ public class RankingHelper implements RankingConfig { } if (r.priority != DEFAULT_PRIORITY) { pw.print(" priority="); - pw.print(Ranking.importanceToString(r.priority)); + pw.print(Notification.priorityToString(r.priority)); } if (r.visibility != DEFAULT_VISIBILITY) { pw.print(" visibility="); - pw.print(Ranking.importanceToString(r.visibility)); + pw.print(Notification.visibilityToString(r.visibility)); } pw.println(); } } } + public JSONObject dumpJson(NotificationManagerService.DumpFilter filter) { + JSONObject ranking = new JSONObject(); + JSONArray records = new JSONArray(); + try { + ranking.put("noUid", mRestoredWithoutUids.size()); + } catch (JSONException e) { + // pass + } + final int N = mRecords.size(); + for (int i = 0; i < N; i++) { + final Record r = mRecords.valueAt(i); + if (filter == null || filter.matches(r.pkg)) { + JSONObject record = new JSONObject(); + try { + record.put("userId", UserHandle.getUserId(r.uid)); + record.put("packageName", r.pkg); + if (r.importance != DEFAULT_IMPORTANCE) { + record.put("importance", Ranking.importanceToString(r.importance)); + } + if (r.priority != DEFAULT_PRIORITY) { + record.put("priority", Notification.priorityToString(r.priority)); + } + if (r.visibility != DEFAULT_VISIBILITY) { + record.put("visibility", Notification.visibilityToString(r.visibility)); + } + } catch (JSONException e) { + // pass + } + records.put(record); + } + } + try { + ranking.put("records", records); + } catch (JSONException e) { + // pass + } + return ranking; + } + + /** + * Dump only the ban information as structured JSON for the stats collector. + * + * This is intentionally redundant with {#link dumpJson} because the old + * scraper will expect this format. + * + * @param filter + * @return + */ + public JSONArray dumpBansJson(NotificationManagerService.DumpFilter filter) { + JSONArray bans = new JSONArray(); + Map<Integer, String> packageBans = getPackageBans(); + for(Entry<Integer, String> ban : packageBans.entrySet()) { + final int userId = UserHandle.getUserId(ban.getKey()); + final String packageName = ban.getValue(); + if (filter == null || filter.matches(packageName)) { + JSONObject banJson = new JSONObject(); + try { + banJson.put("userId", userId); + banJson.put("packageName", packageName); + } catch (JSONException e) { + e.printStackTrace(); + } + bans.put(banJson); + } + } + return bans; + } + + public Map<Integer, String> getPackageBans() { + final int N = mRecords.size(); + ArrayMap<Integer, String> packageBans = new ArrayMap<>(N); + for (int i = 0; i < N; i++) { + final Record r = mRecords.valueAt(i); + if (r.importance == Ranking.IMPORTANCE_NONE) { + packageBans.put(r.uid, r.pkg); + } + } + return packageBans; + } + public void onPackagesChanged(boolean queryReplace, String[] pkgList) { if (queryReplace || pkgList == null || pkgList.length == 0 || mRestoredWithoutUids.isEmpty()) { diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index b7cd3185a228..5b0ceca4cb9d 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -28,6 +28,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.ILauncherApps; import android.content.pm.IOnAppsChangedListener; import android.content.pm.IPackageManager; +import android.content.pm.LauncherApps.ShortcutQuery; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -74,9 +75,20 @@ public class LauncherAppsService extends SystemService { @Override public void onStart() { + Binder.LOG_RUNTIME_EXCEPTION = true; publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl); } + static class BroadcastCookie { + public final UserHandle user; + public final String packageName; + + BroadcastCookie(UserHandle userHandle, String packageName) { + this.user = userHandle; + this.packageName = packageName; + } + } + @VisibleForTesting static class LauncherAppsImpl extends ILauncherApps.Stub { private static final boolean DEBUG = false; @@ -99,12 +111,22 @@ public class LauncherAppsService extends SystemService { mShortcutServiceInternal.addListener(mPackageMonitor); } + @VisibleForTesting + int injectBinderCallingUid() { + return getCallingUid(); + } + + private int getCallingUserId() { + return UserHandle.getUserId(injectBinderCallingUid()); + } + /* * @see android.content.pm.ILauncherApps#addOnAppsChangedListener( * android.content.pm.IOnAppsChangedListener) */ @Override - public void addOnAppsChangedListener(IOnAppsChangedListener listener) throws RemoteException { + public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener) + throws RemoteException { synchronized (mListeners) { if (DEBUG) { Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle()); @@ -116,7 +138,8 @@ public class LauncherAppsService extends SystemService { startWatchingPackageBroadcasts(); } mListeners.unregister(listener); - mListeners.register(listener, Binder.getCallingUserHandle()); + mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()), + callingPackage)); } } @@ -296,17 +319,21 @@ public class LauncherAppsService extends SystemService { } } - private void enforceShortcutPermission(UserHandle user) { + private void ensureShortcutPermission(@NonNull String callingPackage, UserHandle user) { + verifyCallingPackage(callingPackage); ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user); - // STOPSHIP Implement it + + if (!mShortcutServiceInternal.hasShortcutHostPermission(callingPackage, + user.getIdentifier())) { + throw new SecurityException("Caller can't access shortcut information"); + } } @Override public ParceledListSlice getShortcuts(String callingPackage, long changedSince, String packageName, ComponentName componentName, int flags, UserHandle user) throws RemoteException { - enforceShortcutPermission(user); - verifyCallingPackage(callingPackage); + ensureShortcutPermission(callingPackage, user); return new ParceledListSlice<>( mShortcutServiceInternal.getShortcuts(callingPackage, changedSince, packageName, @@ -316,8 +343,7 @@ public class LauncherAppsService extends SystemService { @Override public ParceledListSlice getShortcutInfo(String callingPackage, String packageName, List<String> ids, UserHandle user) throws RemoteException { - enforceShortcutPermission(user); - verifyCallingPackage(callingPackage); + ensureShortcutPermission(callingPackage, user); return new ParceledListSlice<>( mShortcutServiceInternal.getShortcutInfo(callingPackage, packageName, @@ -327,8 +353,7 @@ public class LauncherAppsService extends SystemService { @Override public void pinShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle user) throws RemoteException { - enforceShortcutPermission(user); - verifyCallingPackage(callingPackage); + ensureShortcutPermission(callingPackage, user); mShortcutServiceInternal.pinShortcuts(callingPackage, packageName, ids, user.getIdentifier()); @@ -337,8 +362,7 @@ public class LauncherAppsService extends SystemService { @Override public int getShortcutIconResId(String callingPackage, ShortcutInfo shortcut, UserHandle user) { - enforceShortcutPermission(user); - verifyCallingPackage(callingPackage); + ensureShortcutPermission(callingPackage, user); return mShortcutServiceInternal.getShortcutIconResId(callingPackage, shortcut, user.getIdentifier()); @@ -347,19 +371,24 @@ public class LauncherAppsService extends SystemService { @Override public ParcelFileDescriptor getShortcutIconFd(String callingPackage, ShortcutInfo shortcut, UserHandle user) { - enforceShortcutPermission(user); - verifyCallingPackage(callingPackage); + ensureShortcutPermission(callingPackage, user); return mShortcutServiceInternal.getShortcutIconFd(callingPackage, shortcut, user.getIdentifier()); } @Override + public boolean hasShortcutHostPermission(String callingPackage) throws RemoteException { + verifyCallingPackage(callingPackage); + return mShortcutServiceInternal.hasShortcutHostPermission(callingPackage, + getCallingUserId()); + } + + @Override public boolean startShortcut(String callingPackage, String packageName, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, UserHandle user) throws RemoteException { - enforceShortcutPermission(user); - verifyCallingPackage(callingPackage); + ensureShortcutPermission(callingPackage, user); final Intent intent = mShortcutServiceInternal.createShortcutIntent(callingPackage, packageName, shortcutId, user.getIdentifier()); @@ -475,41 +504,44 @@ public class LauncherAppsService extends SystemService { } } - - private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener { - - /** Checks if user is a profile of or same as listeningUser. - * and the user is enabled. */ - private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, - String debugMsg) { - if (user.getIdentifier() == listeningUser.getIdentifier()) { - if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg); - return true; - } - long ident = Binder.clearCallingIdentity(); - try { - UserInfo userInfo = mUm.getUserInfo(user.getIdentifier()); - UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier()); - if (userInfo == null || listeningUserInfo == null - || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID - || userInfo.profileGroupId != listeningUserInfo.profileGroupId - || !userInfo.isEnabled()) { - if (DEBUG) { - Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":" - + debugMsg); - } - return false; - } else { - if (DEBUG) { - Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":" - + debugMsg); - } - return true; + /** Checks if user is a profile of or same as listeningUser. + * and the user is enabled. */ + boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, + String debugMsg) { + if (user.getIdentifier() == listeningUser.getIdentifier()) { + if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg); + return true; + } + long ident = Binder.clearCallingIdentity(); + try { + UserInfo userInfo = mUm.getUserInfo(user.getIdentifier()); + UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier()); + if (userInfo == null || listeningUserInfo == null + || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID + || userInfo.profileGroupId != listeningUserInfo.profileGroupId + || !userInfo.isEnabled()) { + if (DEBUG) { + Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":" + + debugMsg); } - } finally { - Binder.restoreCallingIdentity(ident); + return false; + } else { + if (DEBUG) { + Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":" + + debugMsg); + } + return true; } + } finally { + Binder.restoreCallingIdentity(ident); } + } + + void postToPackageMonitor(Runnable r) { + mPackageMonitor.getRegisteredHandler().post(r); + } + + private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener { // TODO Simplify with lambdas. @@ -519,8 +551,8 @@ public class LauncherAppsService extends SystemService { final int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); - UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isEnabledProfileOf(user, listeningUser, "onPackageAdded")) continue; + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(user, cookie.user, "onPackageAdded")) continue; try { listener.onPackageAdded(user, packageName); } catch (RemoteException re) { @@ -538,8 +570,8 @@ public class LauncherAppsService extends SystemService { final int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); - UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isEnabledProfileOf(user, listeningUser, "onPackageRemoved")) continue; + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(user, cookie.user, "onPackageRemoved")) continue; try { listener.onPackageRemoved(user, packageName); } catch (RemoteException re) { @@ -557,8 +589,8 @@ public class LauncherAppsService extends SystemService { final int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); - UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isEnabledProfileOf(user, listeningUser, "onPackageModified")) continue; + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(user, cookie.user, "onPackageModified")) continue; try { listener.onPackageChanged(user, packageName); } catch (RemoteException re) { @@ -576,8 +608,8 @@ public class LauncherAppsService extends SystemService { final int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); - UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isEnabledProfileOf(user, listeningUser, "onPackagesAvailable")) continue; + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(user, cookie.user, "onPackagesAvailable")) continue; try { listener.onPackagesAvailable(user, packages, isReplacing()); } catch (RemoteException re) { @@ -595,8 +627,8 @@ public class LauncherAppsService extends SystemService { final int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); - UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isEnabledProfileOf(user, listeningUser, "onPackagesUnavailable")) continue; + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnavailable")) continue; try { listener.onPackagesUnavailable(user, packages, isReplacing()); } catch (RemoteException re) { @@ -614,8 +646,8 @@ public class LauncherAppsService extends SystemService { final int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); - UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isEnabledProfileOf(user, listeningUser, "onPackagesSuspended")) continue; + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(user, cookie.user, "onPackagesSuspended")) continue; try { listener.onPackagesSuspended(user, packages); } catch (RemoteException re) { @@ -633,8 +665,8 @@ public class LauncherAppsService extends SystemService { final int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); - UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isEnabledProfileOf(user, listeningUser, "onPackagesUnsuspended")) continue; + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnsuspended")) continue; try { listener.onPackagesUnsuspended(user, packages); } catch (RemoteException re) { @@ -648,17 +680,39 @@ public class LauncherAppsService extends SystemService { @Override public void onShortcutChanged(@NonNull String packageName, - @NonNull List<ShortcutInfo> shortcuts, @UserIdInt int userId) { + @UserIdInt int userId) { + postToPackageMonitor(() -> onShortcutChangedInner(packageName, userId)); + } + + private void onShortcutChangedInner(@NonNull String packageName, + @UserIdInt int userId) { final UserHandle user = UserHandle.of(userId); final int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); - UserHandle listeningUser = (UserHandle) mListeners.getBroadcastCookie(i); - if (!isEnabledProfileOf(user, listeningUser, "onShortcutChanged")) continue; + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(user, cookie.user, "onShortcutChanged")) continue; + + // Make sure the caller has the permission. + if (!mShortcutServiceInternal.hasShortcutHostPermission(cookie.packageName, + cookie.user.getIdentifier())) { + continue; + } + // Each launcher has a different set of pinned shortcuts, so we need to do a + // query in here. + // (As of now, only one launcher has the permission at a time, so it's bit + // moot, but we may change the permission model eventually.) + final List<ShortcutInfo> list = + mShortcutServiceInternal.getShortcuts(cookie.packageName, + /* changedSince= */ 0, packageName, /* component= */ null, + ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY + | ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC + , userId); try { listener.onShortcutChanged(user, packageName, - new ParceledListSlice<>(shortcuts)); + new ParceledListSlice<>(list)); } catch (RemoteException re) { Slog.d(TAG, "Callback failed ", re); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index debe072b7b98..c7578f013957 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -6891,7 +6891,8 @@ public class PackageManagerService extends IPackageManager.Stub { // Extract pacakges only if profile-guided compilation is enabled because // otherwise BackgroundDexOptService will not dexopt them later. - if (!isUpgrade()) { + boolean prunedCache = VMRuntime.didPruneDalvikCache(); + if (!isUpgrade() && !prunedCache) { return; } @@ -6919,8 +6920,11 @@ public class PackageManagerService extends IPackageManager.Stub { } if (PackageDexOptimizer.canOptimizePackage(pkg)) { + // If the cache was pruned, any compiled odex files will likely be out of date + // and would have to be patched (would be SELF_PATCHOAT, which is deprecated). + // Instead, force the extraction in this case. performDexOpt(pkg.packageName, null /* instructionSet */, - false /* useProfiles */, true /* extractOnly */, false /* force */); + false /* useProfiles */, true /* extractOnly */, prunedCache); } } } @@ -10822,25 +10826,41 @@ public class PackageManagerService extends IPackageManager.Stub { } } - // TODO: investigate and add more restrictions for suspending crucial packages. + /** + * TODO: cache and disallow blocking the active dialer. + * + * @see also DefaultPermissionGrantPolicy#grantDefaultSystemHandlerPermissions + */ private boolean canSuspendPackageForUserLocked(String packageName, int userId) { if (isPackageDeviceAdmin(packageName, userId)) { - Slog.w(TAG, "Not suspending/un-suspending package \"" + packageName - + "\": has active device admin"); + Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName + + "\": has an active device admin"); return false; } String activeLauncherPackageName = getActiveLauncherPackageName(userId); if (packageName.equals(activeLauncherPackageName)) { - Slog.w(TAG, "Not suspending/un-suspending package \"" + packageName - + "\" because it is set as the active launcher"); + Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName + + "\": contains the active launcher"); + return false; + } + + if (packageName.equals(mRequiredInstallerPackage)) { + Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName + + "\": required for package installation"); + return false; + } + + if (packageName.equals(mRequiredVerifierPackage)) { + Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName + + "\": required for package verification"); return false; } final PackageParser.Package pkg = mPackages.get(packageName); if (pkg != null && isPrivilegedApp(pkg)) { - Slog.w(TAG, "Not suspending/un-suspending package \"" + packageName - + "\" because it is a privileged app"); + Slog.w(TAG, "Cannot suspend/un-suspend package \"" + packageName + + "\": is a privileged app"); return false; } @@ -16436,14 +16456,29 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); @Override public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) { + return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId()); + } + + private Intent getHomeIntent() { Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); + return intent; + } - final int callingUserId = UserHandle.getCallingUserId(); + private IntentFilter getHomeFilter() { + IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN); + filter.addCategory(Intent.CATEGORY_HOME); + filter.addCategory(Intent.CATEGORY_DEFAULT); + return filter; + } + + ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, + int userId) { + Intent intent = getHomeIntent(); List<ResolveInfo> list = queryIntentActivitiesInternal(intent, null, - PackageManager.GET_META_DATA, callingUserId); + PackageManager.GET_META_DATA, userId); ResolveInfo preferred = findPreferredActivity(intent, null, 0, list, 0, - true, false, false, callingUserId); + true, false, false, userId); allHomeCandidates.clear(); if (list != null) { @@ -16458,6 +16493,32 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } @Override + public void setHomeActivity(ComponentName comp, int userId) { + ArrayList<ResolveInfo> homeActivities = new ArrayList<>(); + getHomeActivitiesAsUser(homeActivities, userId); + + boolean found = false; + + final int size = homeActivities.size(); + final ComponentName[] set = new ComponentName[size]; + for (int i = 0; i < size; i++) { + final ResolveInfo candidate = homeActivities.get(i); + final ActivityInfo info = candidate.activityInfo; + final ComponentName activityName = new ComponentName(info.packageName, info.name); + set[i] = activityName; + if (!found && activityName.equals(comp)) { + found = true; + } + } + if (!found) { + throw new IllegalArgumentException("Component " + comp + " cannot be home on user " + + userId); + } + replacePreferredActivity(getHomeFilter(), IntentFilter.MATCH_CATEGORY_EMPTY, + set, comp, userId); + } + + @Override public void setApplicationEnabledSetting(String appPackageName, int newState, int flags, int userId, String callingPackage) { if (!sUserManager.exists(userId)) return; @@ -16601,6 +16662,22 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } } + @Override + public void flushPackageRestrictionsAsUser(int userId) { + if (!sUserManager.exists(userId)) { + return; + } + enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission*/, + false /* checkShell */, "flushPackageRestrictions"); + synchronized (mPackages) { + mSettings.writePackageRestrictionsLPr(userId); + mDirtyUsers.remove(userId); + if (mDirtyUsers.isEmpty()) { + mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS); + } + } + } + private void sendPackageChangedBroadcast(String packageName, boolean killFlag, ArrayList<String> componentNames, int packageUid) { if (DEBUG_INSTALL) @@ -19232,6 +19309,12 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); public ApplicationInfo getApplicationInfo(String packageName, int userId) { return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId); } + + @Override + public ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates, + int userId) { + return PackageManagerService.this.getHomeActivitiesAsUser(allHomeCandidates, userId); + } } @Override diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index d77168c505f7..319fc3741828 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -117,6 +117,8 @@ class PackageManagerShellCommand extends ShellCommand { return runSuspend(true); case "unsuspend": return runSuspend(false); + case "set-home-activity": + return runSetHomeActivity(); default: return handleDefaultCommands(cmd); } @@ -963,6 +965,39 @@ class PackageManagerShellCommand extends ShellCommand { return params; } + private int runSetHomeActivity() { + final PrintWriter pw = getOutPrintWriter(); + int userId = UserHandle.USER_SYSTEM; + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "--user": + userId = UserHandle.parseUserArg(getNextArgRequired()); + break; + default: + pw.println("Error: Unknown option: " + opt); + return 1; + } + } + + String component = getNextArg(); + ComponentName componentName = + component != null ? ComponentName.unflattenFromString(component) : null; + + if (componentName == null) { + pw.println("Error: component name not specified or invalid"); + return 1; + } + + try { + mInterface.setHomeActivity(componentName, userId); + return 0; + } catch (RemoteException e) { + pw.println(e.toString()); + return 1; + } + } + private static String checkAbiArgument(String abi) { if (TextUtils.isEmpty(abi)) { throw new IllegalArgumentException("Missing ABI argument"); @@ -1303,6 +1338,8 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" Suspends the specified package (as user)."); pw.println(" unsuspend [--user USER_ID] TARGET-PACKAGE"); pw.println(" Unsuspends the specified package (as user)."); + pw.println(" set-home-activity [--user USER_ID] TARGET-COMPONENT"); + pw.println(" set the default home activity (aka launcher)."); pw.println(); Intent.printIntentArgsHelp(pw , ""); } diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 0b0f7abbce4e..197b2faf8236 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -28,7 +28,9 @@ import android.content.pm.LauncherApps; import android.content.pm.LauncherApps.ShortcutQuery; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; +import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutServiceInternal; import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener; @@ -71,6 +73,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import libcore.io.IoUtils; +import libcore.util.Objects; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -88,7 +91,6 @@ import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.function.Predicate; /** @@ -156,6 +158,9 @@ public class ShortcutService extends IShortcutService.Stub { static final String TAG_INTENT_EXTRAS = "intent-extras"; static final String TAG_EXTRAS = "extras"; static final String TAG_SHORTCUT = "shortcut"; + static final String TAG_LAUNCHER = "launcher"; + static final String TAG_PIN = "pin"; + static final String TAG_LAUNCHER_PINS = "launcher-pins"; static final String ATTR_VALUE = "value"; static final String ATTR_NAME = "name"; @@ -171,6 +176,7 @@ public class ShortcutService extends IShortcutService.Stub { static final String ATTR_FLAGS = "flags"; static final String ATTR_ICON_RES = "icon-res"; static final String ATTR_BITMAP_PATH = "bitmap-path"; + static final String ATTR_PACKAGE_NAME = "package-name"; @VisibleForTesting interface ConfigConstants { @@ -251,10 +257,13 @@ public class ShortcutService extends IShortcutService.Stub { private CompressFormat mIconPersistFormat; private int mIconPersistQuality; + private final PackageManagerInternal mPackageManagerInternal; + public ShortcutService(Context context) { mContext = Preconditions.checkNotNull(context); LocalServices.addService(ShortcutServiceInternal.class, new LocalService()); mHandler = new Handler(BackgroundThread.get().getLooper()); + mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); } /** @@ -460,6 +469,11 @@ public class ShortcutService extends IShortcutService.Stub { writeTagValue(out, tag, Long.toString(value)); } + static void writeTagValue(XmlSerializer out, String tag, ComponentName name) throws IOException { + if (name == null) return; + writeTagValue(out, tag, name.flattenToString()); + } + static void writeTagExtra(XmlSerializer out, String tag, PersistableBundle bundle) throws IOException, XmlPullParserException { if (bundle == null) return; @@ -658,7 +672,7 @@ public class ShortcutService extends IShortcutService.Stub { } // TODO Actually make it async. - private void scheduleSaveUser(@UserIdInt int userId) { + void scheduleSaveUser(@UserIdInt int userId) { synchronized (mLock) { saveUserLocked(userId); } @@ -676,6 +690,10 @@ public class ShortcutService extends IShortcutService.Stub { return mRawLastResetTime + mResetInterval; } + static boolean isClockValid(long time) { + return time >= 1420070400; // Thu, 01 Jan 2015 00:00:00 GMT + } + /** * Update the last reset time. */ @@ -690,8 +708,10 @@ public class ShortcutService extends IShortcutService.Stub { mRawLastResetTime = now; } else if (now < mRawLastResetTime) { // Clock rewound. - // TODO Randomize?? - mRawLastResetTime = now; + if (isClockValid(now)) { + // TODO Randomize?? + mRawLastResetTime = now; + } } else { // TODO Do it properly. while ((mRawLastResetTime + mResetInterval) <= now) { @@ -706,7 +726,7 @@ public class ShortcutService extends IShortcutService.Stub { /** Return the per-user state. */ @GuardedBy("mLock") @NonNull - private UserShortcuts getUserShortcutsLocked(@UserIdInt int userId) { + UserShortcuts getUserShortcutsLocked(@UserIdInt int userId) { UserShortcuts userPackages = mUsers.get(userId); if (userPackages == null) { userPackages = loadUserLocked(userId); @@ -721,15 +741,16 @@ public class ShortcutService extends IShortcutService.Stub { /** Return the per-user per-package state. */ @GuardedBy("mLock") @NonNull - private PackageShortcuts getPackageShortcutsLocked( + PackageShortcuts getPackageShortcutsLocked( @NonNull String packageName, @UserIdInt int userId) { - final UserShortcuts userPackages = getUserShortcutsLocked(userId); - PackageShortcuts shortcuts = userPackages.getPackages().get(packageName); - if (shortcuts == null) { - shortcuts = new PackageShortcuts(userId, packageName); - userPackages.getPackages().put(packageName, shortcuts); - } - return shortcuts; + return getUserShortcutsLocked(userId).getPackageShortcuts(packageName); + } + + @GuardedBy("mLock") + @NonNull + LauncherShortcuts getLauncherShortcuts( + @NonNull String packageName, @UserIdInt int userId) { + return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName); } // === Caller validation === @@ -797,7 +818,7 @@ public class ShortcutService extends IShortcutService.Stub { return; } - final long token = Binder.clearCallingIdentity(); + final long token = injectClearCallingIdentity(); try { // Clear icon info on the shortcut. shortcut.setIconResourceId(0); @@ -874,7 +895,7 @@ public class ShortcutService extends IShortcutService.Stub { shortcut.clearIcon(); } } finally { - Binder.restoreCallingIdentity(token); + injectRestoreCallingIdentity(token); } } @@ -975,6 +996,10 @@ public class ShortcutService extends IShortcutService.Stub { } } + void postToHandler(Runnable r) { + mHandler.post(r); + } + /** * Throw if {@code numShortcuts} is bigger than {@link #mMaxDynamicShortcuts}. */ @@ -994,17 +1019,16 @@ public class ShortcutService extends IShortcutService.Stub { } private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) { - final ArrayList<ShortcutChangeListener> copy; - final List<ShortcutInfo> shortcuts = new ArrayList<>(); - synchronized (mLock) { - copy = new ArrayList<>(mListeners); - - getPackageShortcutsLocked(packageName, userId) - .findAll(shortcuts, /* query =*/ null, ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO); - } - for (int i = copy.size() - 1; i >= 0; i--) { - copy.get(i).onShortcutChanged(packageName, shortcuts, userId); - } + postToHandler(() -> { + final ArrayList<ShortcutChangeListener> copy; + synchronized (mLock) { + copy = new ArrayList<>(mListeners); + } + // Note onShortcutChanged() needs to be called with the system service permissions. + for (int i = copy.size() - 1; i >= 0; i--) { + copy.get(i).onShortcutChanged(packageName, userId); + } + }); } /** @@ -1037,7 +1061,7 @@ public class ShortcutService extends IShortcutService.Stub { validatePersistableBundleForXml(shortcut.getIntentPersistableExtras()); validatePersistableBundleForXml(shortcut.getExtras()); - shortcut.setFlags(0); + shortcut.replaceFlags(0); } // KXmlSerializer is strict and doesn't allow certain characters, so we disallow those @@ -1109,8 +1133,7 @@ public class ShortcutService extends IShortcutService.Stub { // Then, add/update all. We need to make sure to take over "pinned" flag. for (int i = 0; i < size; i++) { final ShortcutInfo newShortcut = newShortcuts.get(i); - newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC); - ps.updateShortcutWithCapping(this, newShortcut); + ps.addDynamicShortcut(this, newShortcut); } } userPackageChanged(packageName, userId); @@ -1174,8 +1197,7 @@ public class ShortcutService extends IShortcutService.Stub { fixUpIncomingShortcutInfo(newShortcut, /* forUpdate= */ false); // Add it. - newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC); - ps.updateShortcutWithCapping(this, newShortcut); + ps.addDynamicShortcut(this, newShortcut); } userPackageChanged(packageName, userId); @@ -1231,7 +1253,8 @@ public class ShortcutService extends IShortcutService.Stub { final ArrayList<ShortcutInfo> ret = new ArrayList<>(); - getPackageShortcutsLocked(packageName, userId).findAll(ret, query, cloneFlags); + getPackageShortcutsLocked(packageName, userId).findAll(this, ret, query, cloneFlags, + /* callingLauncher= */ null); return new ParceledListSlice<>(ret); } @@ -1277,18 +1300,98 @@ public class ShortcutService extends IShortcutService.Stub { public void resetThrottling() { enforceSystemOrShell(); - resetThrottlingInner(); + resetThrottlingInner(getCallingUserId()); } - @VisibleForTesting - void resetThrottlingInner() { + void resetThrottlingInner(@UserIdInt int userId) { synchronized (mLock) { - mRawLastResetTime = injectCurrentTimeMillis(); + getUserShortcutsLocked(userId).resetThrottling(); } - scheduleSaveBaseState(); + scheduleSaveUser(userId); Slog.i(TAG, "ShortcutManager: throttling counter reset"); } + // We override this method in unit tests to do a simpler check. + boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) { + return hasShortcutHostPermissionInner(callingPackage, userId); + } + + // This method is extracted so we can directly call this method from unit tests, + // even when hasShortcutPermission() is overridden. + @VisibleForTesting + boolean hasShortcutHostPermissionInner(@NonNull String callingPackage, int userId) { + synchronized (mLock) { + long start = 0; + if (DEBUG) { + start = System.currentTimeMillis(); + } + + final UserShortcuts user = getUserShortcutsLocked(userId); + + final List<ResolveInfo> allHomeCandidates = new ArrayList<>(); + + // Default launcher from package manager. + final ComponentName defaultLauncher = injectPackageManagerInternal() + .getHomeActivitiesAsUser(allHomeCandidates, userId); + + ComponentName detected; + if (defaultLauncher != null) { + detected = defaultLauncher; + if (DEBUG) { + Slog.v(TAG, "Default launcher from PM: " + detected); + } + } else { + detected = user.getLauncherComponent(); + + // TODO: Make sure it's still enabled. + if (DEBUG) { + Slog.v(TAG, "Cached launcher: " + detected); + } + } + + if (detected == null) { + // If we reach here, that means it's the first check since the user was created, + // and there's already multiple launchers and there's no default set. + // Find the system one with the highest priority. + // (We need to check the priority too because of FallbackHome in Settings.) + // If there's no system launcher yet, then no one can access shortcuts, until + // the user explicitly + final int size = allHomeCandidates.size(); + + int lastPriority = Integer.MIN_VALUE; + for (int i = 0; i < size; i++) { + final ResolveInfo ri = allHomeCandidates.get(i); + if (!ri.activityInfo.applicationInfo.isSystemApp()) { + continue; + } + if (DEBUG) { + Slog.d(TAG, String.format("hasShortcutPermissionInner: pkg=%s prio=%d", + ri.activityInfo.getComponentName(), ri.priority)); + } + if (ri.priority < lastPriority) { + continue; + } + detected = ri.activityInfo.getComponentName(); + lastPriority = ri.priority; + } + } + if (DEBUG) { + long end = System.currentTimeMillis(); + Slog.v(TAG, String.format("hasShortcutPermission took %d ms", end - start)); + } + if (detected != null) { + if (DEBUG) { + Slog.v(TAG, "Detected launcher: " + detected); + } + user.setLauncherComponent(this, detected); + return detected.getPackageName().equals(callingPackage); + } else { + // Default launcher not found. + return false; + } + } + } + /** * Entry point from {@link LauncherApps}. */ @@ -1306,25 +1409,27 @@ public class ShortcutService extends IShortcutService.Stub { synchronized (mLock) { if (packageName != null) { - getShortcutsInnerLocked(packageName, changedSince, componentName, queryFlags, - userId, ret, cloneFlag); + getShortcutsInnerLocked( + callingPackage, packageName, changedSince, + componentName, queryFlags, userId, ret, cloneFlag); } else { final ArrayMap<String, PackageShortcuts> packages = getUserShortcutsLocked(userId).getPackages(); for (int i = packages.size() - 1; i >= 0; i--) { getShortcutsInnerLocked( - packages.keyAt(i), - changedSince, componentName, queryFlags, userId, ret, cloneFlag); + callingPackage, packages.keyAt(i), changedSince, + componentName, queryFlags, userId, ret, cloneFlag); } } } return ret; } - private void getShortcutsInnerLocked(@Nullable String packageName,long changedSince, + private void getShortcutsInnerLocked(@NonNull String callingPackage, + @Nullable String packageName,long changedSince, @Nullable ComponentName componentName, int queryFlags, int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) { - getPackageShortcutsLocked(packageName, userId).findAll(ret, + getPackageShortcutsLocked(packageName, userId).findAll(ShortcutService.this, ret, (ShortcutInfo si) -> { if (si.getLastChangedTimestamp() < changedSince) { return false; @@ -1335,12 +1440,12 @@ public class ShortcutService extends IShortcutService.Stub { } final boolean matchDynamic = ((queryFlags & ShortcutQuery.FLAG_GET_DYNAMIC) != 0) - && si.isDynamic(); + && si.isDynamic(); final boolean matchPinned = ((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0) && si.isPinned(); return matchDynamic || matchPinned; - }, cloneFlag); + }, cloneFlag, callingPackage); } @Override @@ -1353,9 +1458,10 @@ public class ShortcutService extends IShortcutService.Stub { final ArrayList<ShortcutInfo> ret = new ArrayList<>(ids.size()); final ArraySet<String> idSet = new ArraySet<>(ids); synchronized (mLock) { - getPackageShortcutsLocked(packageName, userId).findAll(ret, + getPackageShortcutsLocked(packageName, userId).findAll( + ShortcutService.this, ret, (ShortcutInfo si) -> idSet.contains(si.getId()), - ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); + ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage); } return ret; } @@ -1368,8 +1474,8 @@ public class ShortcutService extends IShortcutService.Stub { Preconditions.checkNotNull(shortcutIds, "shortcutIds"); synchronized (mLock) { - getPackageShortcutsLocked(packageName, userId).replacePinned( - ShortcutService.this, callingPackage, shortcutIds); + getLauncherShortcuts(callingPackage, userId).pinShortcuts( + ShortcutService.this, packageName, shortcutIds); } userPackageChanged(packageName, userId); } @@ -1434,6 +1540,11 @@ public class ShortcutService extends IShortcutService.Stub { } } } + + @Override + public boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) { + return ShortcutService.this.hasShortcutHostPermission(callingPackage, userId); + } } // === Dump === @@ -1512,37 +1623,74 @@ public class ShortcutService extends IShortcutService.Stub { (new MyShellCommand()).exec(this, in, out, err, args, resultReceiver); } + static class CommandException extends Exception { + public CommandException(String message) { + super(message); + } + } + /** * Handle "adb shell cmd". */ private class MyShellCommand extends ShellCommand { + + private int mUserId = UserHandle.USER_SYSTEM; + + private void parseOptions(boolean takeUser) + throws CommandException { + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "--user": + if (takeUser) { + mUserId = UserHandle.parseUserArg(getNextArgRequired()); + break; + } + // fallthrough + default: + throw new CommandException("Unknown option: " + opt); + } + } + } + @Override public int onCommand(String cmd) { if (cmd == null) { return handleDefaultCommands(cmd); } final PrintWriter pw = getOutPrintWriter(); - int ret = 1; - switch (cmd) { - case "reset-package-throttling": - ret = handleResetPackageThrottling(); - break; - case "reset-throttling": - ret = handleResetThrottling(); - break; - case "override-config": - ret = handleOverrideConfig(); - break; - case "reset-config": - ret = handleResetConfig(); - break; - default: - return handleDefaultCommands(cmd); - } - if (ret == 0) { - pw.println("Success"); + try { + switch (cmd) { + case "reset-package-throttling": + handleResetPackageThrottling(); + break; + case "reset-throttling": + handleResetThrottling(); + break; + case "override-config": + handleOverrideConfig(); + break; + case "reset-config": + handleResetConfig(); + break; + case "clear-default-launcher": + handleClearDefaultLauncher(); + break; + case "get-default-launcher": + handleGetDefaultLauncher(); + break; + case "refresh-default-launcher": + handleRefreshDefaultLauncher(); + break; + default: + return handleDefaultCommands(cmd); + } + } catch (CommandException e) { + pw.println("Error: " + e.getMessage()); + return 1; } - return ret; + pw.println("Success"); + return 0; } @Override @@ -1562,56 +1710,85 @@ public class ShortcutService extends IShortcutService.Stub { pw.println("cmd shortcut reset-config"); pw.println(" Reset the configuration set with \"update-config\""); pw.println(); + pw.println("cmd shortcut clear-default-launcher [--user USER_ID]"); + pw.println(" Clear the cached default launcher"); + pw.println(); + pw.println("cmd shortcut get-default-launcher [--user USER_ID]"); + pw.println(" Show the cached default launcher"); + pw.println(); + pw.println("cmd shortcut refresh-default-launcher [--user USER_ID]"); + pw.println(" Refresh the cached default launcher"); + pw.println(); } - private int handleResetThrottling() { - resetThrottling(); + private int handleResetThrottling() throws CommandException { + parseOptions(/* takeUser =*/ true); + + resetThrottlingInner(mUserId); return 0; } - private int handleResetPackageThrottling() { - final PrintWriter pw = getOutPrintWriter(); + private void handleResetPackageThrottling() throws CommandException { + parseOptions(/* takeUser =*/ true); - int userId = UserHandle.USER_SYSTEM; - String opt; - while ((opt = getNextOption()) != null) { - switch (opt) { - case "--user": - userId = UserHandle.parseUserArg(getNextArgRequired()); - break; - default: - pw.println("Error: Unknown option: " + opt); - return 1; - } - } final String packageName = getNextArgRequired(); synchronized (mLock) { - getPackageShortcutsLocked(packageName, userId).resetRateLimitingForCommandLine(); - saveUserLocked(userId); + getPackageShortcutsLocked(packageName, mUserId).resetRateLimitingForCommandLine(); + saveUserLocked(mUserId); } - - return 0; } - private int handleOverrideConfig() { - final PrintWriter pw = getOutPrintWriter(); + private void handleOverrideConfig() throws CommandException { final String config = getNextArgRequired(); synchronized (mLock) { if (!updateConfigurationLocked(config)) { - pw.println("override-config failed. See logcat for details."); - return 1; + throw new CommandException("override-config failed. See logcat for details."); } } - return 0; } - private int handleResetConfig() { + private void handleResetConfig() { synchronized (mLock) { loadConfigurationLocked(); } - return 0; + } + + private void clearLauncher() { + synchronized (mLock) { + getUserShortcutsLocked(mUserId).setLauncherComponent( + ShortcutService.this, null); + } + } + + private void showLauncher() { + synchronized (mLock) { + // This ensures to set the cached launcher. Package name doesn't matter. + hasShortcutHostPermissionInner("-", mUserId); + + getOutPrintWriter().println("Launcher: " + + getUserShortcutsLocked(mUserId).getLauncherComponent()); + } + } + + private void handleClearDefaultLauncher() throws CommandException { + parseOptions(/* takeUser =*/ true); + + clearLauncher(); + } + + private void handleGetDefaultLauncher() throws CommandException { + parseOptions(/* takeUser =*/ true); + + showLauncher(); + } + + private void handleRefreshDefaultLauncher() throws CommandException { + parseOptions(/* takeUser =*/ true); + + clearLauncher(); + showLauncher(); } } @@ -1627,6 +1804,28 @@ public class ShortcutService extends IShortcutService.Stub { return getCallingUid(); } + final int getCallingUserId() { + return UserHandle.getUserId(injectBinderCallingUid()); + } + + // Injection point. + long injectClearCallingIdentity() { + return Binder.clearCallingIdentity(); + } + + // Injection point. + void injectRestoreCallingIdentity(long token) { + Binder.restoreCallingIdentity(token); + } + + final void wtf(String message) { + Slog.wtf(TAG, message, /* exception= */ null); + } + + void wtf(String message, Exception e) { + Slog.wtf(TAG, message, e); + } + File injectSystemDataPath() { return Environment.getDataSystemDirectory(); } @@ -1640,6 +1839,10 @@ public class ShortcutService extends IShortcutService.Stub { return ActivityManager.isLowRamDeviceStatic(); } + PackageManagerInternal injectPackageManagerInternal() { + return mPackageManagerInternal; + } + File getUserBitmapFilePath(@UserIdInt int userId) { return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS); } @@ -1687,6 +1890,9 @@ public class ShortcutService extends IShortcutService.Stub { } } +/** + * Per-user information. + */ class UserShortcuts { private static final String TAG = ShortcutService.TAG; @@ -1695,6 +1901,10 @@ class UserShortcuts { private final ArrayMap<String, PackageShortcuts> mPackages = new ArrayMap<>(); + private final ArrayMap<String, LauncherShortcuts> mLaunchers = new ArrayMap<>(); + + private ComponentName mLauncherComponent; + public UserShortcuts(int userId) { mUserId = userId; } @@ -1703,14 +1913,42 @@ class UserShortcuts { return mPackages; } + public ArrayMap<String, LauncherShortcuts> getLaunchers() { + return mLaunchers; + } + + public PackageShortcuts getPackageShortcuts(@NonNull String packageName) { + PackageShortcuts ret = mPackages.get(packageName); + if (ret == null) { + ret = new PackageShortcuts(mUserId, packageName); + mPackages.put(packageName, ret); + } + return ret; + } + + public LauncherShortcuts getLauncherShortcuts(@NonNull String packageName) { + LauncherShortcuts ret = mLaunchers.get(packageName); + if (ret == null) { + ret = new LauncherShortcuts(mUserId, packageName); + mLaunchers.put(packageName, ret); + } + return ret; + } + public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException { out.startTag(null, ShortcutService.TAG_USER); - for (int i = 0; i < mPackages.size(); i++) { - final String packageName = mPackages.keyAt(i); - final PackageShortcuts packageShortcuts = mPackages.valueAt(i); + ShortcutService.writeTagValue(out, ShortcutService.TAG_LAUNCHER, + mLauncherComponent); + + final int lsize = mLaunchers.size(); + for (int i = 0; i < lsize; i++) { + mLaunchers.valueAt(i).saveToXml(out); + } - packageShortcuts.saveToXml(out); + final int psize = mPackages.size(); + for (int i = 0; i < psize; i++) { + mPackages.valueAt(i).saveToXml(out); } out.endTag(null, ShortcutService.TAG_USER); @@ -1730,30 +1968,222 @@ class UserShortcuts { final int depth = parser.getDepth(); final String tag = parser.getName(); switch (tag) { - case ShortcutService.TAG_PACKAGE: + case ShortcutService.TAG_LAUNCHER: { + ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute( + parser, ShortcutService.ATTR_VALUE); + continue; + } + case ShortcutService.TAG_PACKAGE: { final PackageShortcuts shortcuts = PackageShortcuts.loadFromXml(parser, userId); // Don't use addShortcut(), we don't need to save the icon. ret.getPackages().put(shortcuts.mPackageName, shortcuts); continue; + } + + case ShortcutService.TAG_LAUNCHER_PINS: { + final LauncherShortcuts shortcuts = + LauncherShortcuts.loadFromXml(parser, userId); + + ret.getLaunchers().put(shortcuts.mPackageName, shortcuts); + continue; + } } throw ShortcutService.throwForInvalidTag(depth, tag); } return ret; } + public ComponentName getLauncherComponent() { + return mLauncherComponent; + } + + public void setLauncherComponent(ShortcutService s, ComponentName launcherComponent) { + if (Objects.equal(mLauncherComponent, launcherComponent)) { + return; + } + mLauncherComponent = launcherComponent; + s.scheduleSaveUser(mUserId); + } + + public void resetThrottling() { + for (int i = mPackages.size() - 1; i >= 0; i--) { + mPackages.valueAt(i).resetThrottling(); + } + } + public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) { - pw.print(" "); + pw.print(prefix); pw.print("User: "); pw.print(mUserId); pw.println(); + pw.print(prefix); + pw.print(" "); + pw.print("Default launcher: "); + pw.print(mLauncherComponent); + pw.println(); + + for (int i = 0; i < mLaunchers.size(); i++) { + mLaunchers.valueAt(i).dump(s, pw, prefix + " "); + } + for (int i = 0; i < mPackages.size(); i++) { mPackages.valueAt(i).dump(s, pw, prefix + " "); } } } +class LauncherShortcuts { + private static final String TAG = ShortcutService.TAG; + + @UserIdInt + final int mUserId; + + @NonNull + final String mPackageName; + + /** + * Package name -> IDs. + */ + final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>(); + + LauncherShortcuts(@UserIdInt int userId, @NonNull String packageName) { + mUserId = userId; + mPackageName = packageName; + } + + public void pinShortcuts(@NonNull ShortcutService s, @NonNull String packageName, + @NonNull List<String> ids) { + final int idSize = ids.size(); + if (idSize == 0) { + mPinnedShortcuts.remove(packageName); + } else { + final ArraySet<String> prevSet = mPinnedShortcuts.get(packageName); + + // Pin shortcuts. Make sure only pin the ones that were visible to the caller. + // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here. + + final PackageShortcuts packageShortcuts = + s.getPackageShortcutsLocked(packageName, mUserId); + final ArraySet<String> newSet = new ArraySet<>(); + + for (int i = 0; i < idSize; i++) { + final String id = ids.get(i); + final ShortcutInfo si = packageShortcuts.findShortcutById(id); + if (si == null) { + continue; + } + if (si.isDynamic() || (prevSet != null && prevSet.contains(id))) { + newSet.add(id); + } + } + mPinnedShortcuts.put(packageName, newSet); + } + s.getPackageShortcutsLocked(packageName, mUserId).refreshPinnedFlags(s); + } + + /** + * Return the pinned shortcut IDs for the publisher package. + */ + public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName) { + return mPinnedShortcuts.get(packageName); + } + + /** + * Persist. + */ + public void saveToXml(XmlSerializer out) throws IOException { + out.startTag(null, ShortcutService.TAG_LAUNCHER_PINS); + ShortcutService.writeAttr(out, ShortcutService.ATTR_PACKAGE_NAME, + mPackageName); + + final int size = mPinnedShortcuts.size(); + for (int i = 0; i < size; i++) { + out.startTag(null, ShortcutService.TAG_PACKAGE); + ShortcutService.writeAttr(out, ShortcutService.ATTR_PACKAGE_NAME, + mPinnedShortcuts.keyAt(i)); + + final ArraySet<String> ids = mPinnedShortcuts.valueAt(i); + final int idSize = ids.size(); + for (int j = 0; j < idSize; j++) { + ShortcutService.writeTagValue(out, ShortcutService.TAG_PIN, ids.valueAt(j)); + } + out.endTag(null, ShortcutService.TAG_PACKAGE); + } + + out.endTag(null, ShortcutService.TAG_LAUNCHER_PINS); + } + + /** + * Load. + */ + public static LauncherShortcuts loadFromXml(XmlPullParser parser, int userId) + throws IOException, XmlPullParserException { + final String launcherPackageName = ShortcutService.parseStringAttribute(parser, + ShortcutService.ATTR_PACKAGE_NAME); + + final LauncherShortcuts ret = new LauncherShortcuts(userId, launcherPackageName); + + ArraySet<String> ids = null; + final int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type != XmlPullParser.START_TAG) { + continue; + } + final int depth = parser.getDepth(); + final String tag = parser.getName(); + switch (tag) { + case ShortcutService.TAG_PACKAGE: { + final String packageName = ShortcutService.parseStringAttribute(parser, + ShortcutService.ATTR_PACKAGE_NAME); + ids = new ArraySet<>(); + ret.mPinnedShortcuts.put(packageName, ids); + continue; + } + case ShortcutService.TAG_PIN: { + ids.add(ShortcutService.parseStringAttribute(parser, + ShortcutService.ATTR_VALUE)); + continue; + } + } + throw ShortcutService.throwForInvalidTag(depth, tag); + } + return ret; + } + + public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) { + pw.println(); + + pw.print(prefix); + pw.print("Launcher: "); + pw.print(mPackageName); + pw.println(); + + final int size = mPinnedShortcuts.size(); + for (int i = 0; i < size; i++) { + pw.println(); + + pw.print(prefix); + pw.print(" "); + pw.print("Package: "); + pw.println(mPinnedShortcuts.keyAt(i)); + + final ArraySet<String> ids = mPinnedShortcuts.valueAt(i); + final int idSize = ids.size(); + + for (int j = 0; j < idSize; j++) { + pw.print(prefix); + pw.print(" "); + pw.print(ids.valueAt(j)); + pw.println(); + } + } + } +} + /** * All the information relevant to shortcuts from a single package (per-user). */ @@ -1791,7 +2221,6 @@ class PackageShortcuts { mPackageName = packageName; } - @GuardedBy("mLock") @Nullable public ShortcutInfo findShortcutById(String id) { return mShortcuts.get(id); @@ -1818,28 +2247,34 @@ class PackageShortcuts { * * It checks the max number of dynamic shortcuts. */ - @GuardedBy("mLock") - public void updateShortcutWithCapping(@NonNull ShortcutService s, + public void addDynamicShortcut(@NonNull ShortcutService s, @NonNull ShortcutInfo newShortcut) { + newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC); + final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId()); - int oldFlags = 0; - int newDynamicCount = mDynamicShortcutCount; + final boolean wasPinned; + final int newDynamicCount; - if (oldShortcut != null) { - oldFlags = oldShortcut.getFlags(); + if (oldShortcut == null) { + wasPinned = false; + newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut. + } else { + wasPinned = oldShortcut.isPinned(); if (oldShortcut.isDynamic()) { - newDynamicCount--; + newDynamicCount = mDynamicShortcutCount; // not adding a dynamic shortcut. + } else { + newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut. } } - if (newShortcut.isDynamic()) { - newDynamicCount++; - } + // Make sure there's still room. s.enforceMaxDynamicShortcuts(newDynamicCount); // Okay, make it dynamic and add. - newShortcut.addFlags(oldFlags); + if (wasPinned) { + newShortcut.addFlags(ShortcutInfo.FLAG_PINNED); + } addShortcut(s, newShortcut); mDynamicShortcutCount = newDynamicCount; @@ -1868,7 +2303,9 @@ class PackageShortcuts { } } - @GuardedBy("mLock") + /** + * Remove all dynamic shortcuts. + */ public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) { for (int i = mShortcuts.size() - 1; i >= 0; i--) { mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC); @@ -1877,7 +2314,9 @@ class PackageShortcuts { mDynamicShortcutCount = 0; } - @GuardedBy("mLock") + /** + * Remove a dynamic shortcut by ID. + */ public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) { final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId); @@ -1894,37 +2333,51 @@ class PackageShortcuts { } } - @GuardedBy("mLock") - public void replacePinned(@NonNull ShortcutService s, String launcherPackage, - List<String> shortcutIds) { - - // TODO Should be per launcherPackage. - + /** + * Called after a launcher updates the pinned set. For each shortcut in this package, + * set FLAG_PINNED if any launcher has pinned it. Otherwise, clear it. + * + * <p>Then remove all shortcuts that are not dynamic and no longer pinned either. + */ + public void refreshPinnedFlags(@NonNull ShortcutService s) { // First, un-pin all shortcuts for (int i = mShortcuts.size() - 1; i >= 0; i--) { mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED); } - // Then pin ALL - for (int i = shortcutIds.size() - 1; i >= 0; i--) { - final ShortcutInfo shortcut = mShortcuts.get(shortcutIds.get(i)); - if (shortcut != null) { - shortcut.addFlags(ShortcutInfo.FLAG_PINNED); + // Then, for the pinned set for each launcher, set the pin flag one by one. + final ArrayMap<String, LauncherShortcuts> launchers = + s.getUserShortcutsLocked(mUserId).getLaunchers(); + + for (int l = launchers.size() - 1; l >= 0; l--) { + final LauncherShortcuts launcherShortcuts = launchers.valueAt(l); + final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds(mPackageName); + + if (pinned == null || pinned.size() == 0) { + continue; + } + for (int i = pinned.size() - 1; i >= 0; i--) { + final ShortcutInfo si = mShortcuts.get(pinned.valueAt(i)); + if (si == null) { + s.wtf("Shortcut not found"); + } else { + si.addFlags(ShortcutInfo.FLAG_PINNED); + } } } + // Lastly, remove the ones that are no longer pinned nor dynamic. removeOrphans(s); } /** * Number of calls that the caller has made, since the last reset. */ - @GuardedBy("mLock") public int getApiCallCount(@NonNull ShortcutService s) { final long last = s.getLastResetTimeLocked(); final long now = s.injectCurrentTimeMillis(); - if (mLastResetTime > now) { + if (ShortcutService.isClockValid(now) && mLastResetTime > now) { // Clock rewound. // TODO Test it mLastResetTime = now; } @@ -1941,7 +2394,6 @@ class PackageShortcuts { * If the caller app hasn't been throttled yet, increment {@link #mApiCallCount} * and return true. Otherwise just return false. */ - @GuardedBy("mLock") public boolean tryApiCall(@NonNull ShortcutService s) { if (getApiCallCount(s) >= s.mMaxDailyUpdates) { return false; @@ -1950,7 +2402,6 @@ class PackageShortcuts { return true; } - @GuardedBy("mLock") public void resetRateLimitingForCommandLine() { mApiCallCount = 0; mLastResetTime = 0; @@ -1959,18 +2410,51 @@ class PackageShortcuts { /** * Find all shortcuts that match {@code query}. */ - @GuardedBy("mLock") - public void findAll(@NonNull List<ShortcutInfo> result, - @Nullable Predicate<ShortcutInfo> query, int cloneFlag) { + public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result, + @Nullable Predicate<ShortcutInfo> query, int cloneFlag, + @Nullable String callingLauncher) { + + // Set of pinned shortcuts by the calling launcher. + final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null + : s.getLauncherShortcuts(callingLauncher, mUserId) + .getPinnedShortcutIds(mPackageName); + for (int i = 0; i < mShortcuts.size(); i++) { final ShortcutInfo si = mShortcuts.valueAt(i); - if (query == null || query.test(si)) { - result.add(si.clone(cloneFlag)); + + // If it's called by non-launcher (i.e. publisher, always include -> true. + // Otherwise, only include non-dynamic pinned one, if the calling launcher has pinned + // it. + final boolean isPinnedByCaller = (callingLauncher == null) + || ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId())); + if (!si.isDynamic()) { + if (!si.isPinned()) { + s.wtf("Shortcut not pinned here"); + continue; + } + if (!isPinnedByCaller) { + continue; + } + } + final ShortcutInfo clone = si.clone(cloneFlag); + // Fix up isPinned for the caller. Note we need to do it before the "test" callback, + // since it may check isPinned. + if (!isPinnedByCaller) { + clone.clearFlags(ShortcutInfo.FLAG_PINNED); + } + if (query == null || query.test(clone)) { + result.add(clone); } } } + public void resetThrottling() { + mApiCallCount = 0; + } + public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) { + pw.println(); + pw.print(prefix); pw.print("Package: "); pw.print(mPackageName); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 8206bdab255d..5fd196b4eb5b 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -641,7 +641,16 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo getUserInfo(int userId) { - checkManageUsersPermission("query user"); + int callingUserId = UserHandle.getCallingUserId(); + if (callingUserId != userId && !hasManageUsersPermission()) { + synchronized (mPackagesLock) { + if (!isSameProfileGroupLP(callingUserId, userId)) { + throw new SecurityException( + "You need MANAGE_USERS permission to: query users outside profile" + + " group"); + } + } + } synchronized (mUsersLock) { return getUserInfoLU(userId); } @@ -1196,18 +1205,28 @@ public class UserManagerService extends IUserManager.Stub { * * @param message used as message if SecurityException is thrown * @throws SecurityException if the caller is not system or root + * @see #hasManageUsersPermission() */ private static final void checkManageUsersPermission(String message) { - final int uid = Binder.getCallingUid(); - if (!UserHandle.isSameApp(uid, Process.SYSTEM_UID) && uid != Process.ROOT_UID - && ActivityManager.checkComponentPermission( - android.Manifest.permission.MANAGE_USERS, - uid, -1, true) != PackageManager.PERMISSION_GRANTED) { + if (!hasManageUsersPermission()) { throw new SecurityException("You need MANAGE_USERS permission to: " + message); } } /** + * @return whether the calling UID is system UID or root's UID or the calling app has the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}. + */ + private static final boolean hasManageUsersPermission() { + final int callingUid = Binder.getCallingUid(); + return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) + || callingUid == Process.ROOT_UID + || ActivityManager.checkComponentPermission( + android.Manifest.permission.MANAGE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; + } + + /** * Enforces that only the system UID or root's UID (on any user) can make certain calls to the * UserManager. * diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 9af1304afc68..0115a08cefe5 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -4635,7 +4635,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { } // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. - if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR) { + // Also, we don't allow windows in multi-window mode to extend out of the screen. + if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR + && !win.inMultiWindowMode()) { df.left = df.top = -10000; df.right = df.bottom = 10000; if (attrs.type != TYPE_WALLPAPER) { diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index ffdd89ae364c..3cf95900edde 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -730,13 +730,27 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { public void systemRunning() { if (DEBUG) Slog.v(TAG, "systemReady"); WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM); - // No crop file? Make sure we've finished the processing sequence if necessary - if (!wallpaper.cropExists()) { - generateCrop(wallpaper); - } - // Still nothing? Fall back to default. - if (!wallpaper.cropExists()) { - clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null); + // If we think we're going to be using the system image wallpaper imagery, make + // sure we have something to render + if (mImageWallpaper.equals(wallpaper.nextWallpaperComponent)) { + // No crop file? Make sure we've finished the processing sequence if necessary + if (!wallpaper.cropExists()) { + if (DEBUG) { + Slog.i(TAG, "No crop; regenerating from source"); + } + generateCrop(wallpaper); + } + // Still nothing? Fall back to default. + if (!wallpaper.cropExists()) { + if (DEBUG) { + Slog.i(TAG, "Unable to regenerate crop; resetting"); + } + clearWallpaperLocked(false, FLAG_SET_SYSTEM, UserHandle.USER_SYSTEM, null); + } + } else { + if (DEBUG) { + Slog.i(TAG, "Nondefault wallpaper component; gracefully ignoring"); + } } switchWallpaper(wallpaper, null); wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper); diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java index 55b3c7baf4a2..3a5dec939721 100644 --- a/services/core/java/com/android/server/wm/AppWindowAnimator.java +++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java @@ -171,17 +171,21 @@ public class AppWindowAnimator { transformation.setAlpha(mAppToken.isVisible() ? 1 : 0); } + void setNullAnimation() { + animation = null; + usingTransferredAnimation = false; + } + public void clearAnimation() { if (animation != null) { - animation = null; animating = true; } clearThumbnail(); + setNullAnimation(); if (mAppToken.deferClearAllDrawn) { mAppToken.allDrawn = false; mAppToken.deferClearAllDrawn = false; } - usingTransferredAnimation = false; } public boolean isAnimating() { @@ -202,9 +206,9 @@ public class AppWindowAnimator { if (animation != null) { toAppAnimator.animation = animation; - animation = null; toAppAnimator.animating = animating; toAppAnimator.animLayerAdjustment = animLayerAdjustment; + setNullAnimation(); animLayerAdjustment = 0; toAppAnimator.updateLayers(); updateLayers(); @@ -311,7 +315,7 @@ public class AppWindowAnimator { if (mProlongAnimation == PROLONG_ANIMATION_AT_END) { hasMoreFrames = true; } else { - animation = null; + setNullAnimation(); clearThumbnail(); if (DEBUG_ANIM) Slog.v(TAG, "Finished animation in " + mAppToken + " @ " + currentTime); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 9795c93e8e02..4ec297e31015 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -322,23 +322,6 @@ class AppWindowToken extends WindowToken { } } - void setWindowsExiting(boolean exiting) { - for (int i = allAppWindows.size() - 1; i >= 0; i--) { - WindowState win = allAppWindows.get(i); - // If the app already requested to remove its window, we don't modify - // its exiting state. Otherwise the stale window won't get removed on - // exit and could cause focus to be given to the wrong window. - if (!(win.mRemoveOnExit && win.mAnimatingExit)) { - win.mAnimatingExit = exiting; - } - // If we're no longer exiting, remove the window from destroying list - if (!win.mAnimatingExit && win.mDestroying) { - win.mDestroying = false; - service.mDestroySurface.remove(win); - } - } - } - // Here we destroy surfaces which have been marked as eligible by the animator, taking care // to ensure the client has finished with them. If the client could still be using them // we will skip destruction and try again when the client has stopped. diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index e42658e5a2f7..b70218059b74 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -24,6 +24,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.app.ActivityManagerNative; import android.graphics.Rect; +import android.os.Debug; import android.os.RemoteException; import android.util.Log; import android.util.Slog; @@ -36,6 +37,7 @@ import com.android.server.input.InputApplicationHandle; import com.android.server.input.InputManagerService; import com.android.server.input.InputWindowHandle; +import java.io.PrintWriter; import java.util.Arrays; final class InputMonitor implements InputManagerService.WindowManagerCallbacks { @@ -47,6 +49,9 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { // When true, prevents input dispatch from proceeding until set to false again. private boolean mInputDispatchFrozen; + // The reason the input is currently frozen or null if the input isn't frozen. + private String mInputFreezeReason = null; + // When true, input dispatch proceeds normally. Otherwise all events are dropped. // Initially false, so that input does not get dispatched until boot is finished at // which point the ActivityManager will enable dispatching. @@ -474,12 +479,16 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { } public void freezeInputDispatchingLw() { - if (! mInputDispatchFrozen) { + if (!mInputDispatchFrozen) { if (DEBUG_INPUT) { Slog.v(TAG_WM, "Freezing input dispatching"); } mInputDispatchFrozen = true; + + if (DEBUG_INPUT || true) { + mInputFreezeReason = Debug.getCallers(6); + } updateInputDispatchModeLw(); } } @@ -491,6 +500,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { } mInputDispatchFrozen = false; + mInputFreezeReason = null; updateInputDispatchModeLw(); } } @@ -509,4 +519,10 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { private void updateInputDispatchModeLw() { mService.mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen); } + + void dump(PrintWriter pw, String prefix) { + if (mInputFreezeReason != null) { + pw.println(prefix + "mInputFreezeReason=" + mInputFreezeReason); + } + } } diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 2e424d036da7..e44b0f30d9b7 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -508,10 +508,11 @@ class WallpaperController { replacing = replacing || w.mWillReplaceWindow; - // If the app is executing an animation because the keyguard is going away, - // keep the wallpaper during the animation so it doesn't flicker out. + // If the app is executing an animation because the keyguard is going away (and the + // keyguard was showing the wallpaper) keep the wallpaper during the animation so it + // doesn't flicker out. final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0 - || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayAnimation); + || (w.mAppToken != null && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper); if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) { if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: #" + i + "=" + w); result.setWallpaperTarget(w, i); diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 4698e4e173ae..f24376195eb8 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -22,6 +22,9 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; +import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; +import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS; +import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD; @@ -98,8 +101,7 @@ public class WindowAnimator { boolean mInitialized = false; boolean mKeyguardGoingAway; - boolean mKeyguardGoingAwayToNotificationShade; - boolean mKeyguardGoingAwayDisableWindowAnimations; + int mKeyguardGoingAwayFlags; /** Use one animation for all entering activities after keyguard is dismissed. */ Animation mPostKeyguardExitAnimation; @@ -243,6 +245,13 @@ public class WindowAnimator { final WindowList windows = mService.getWindowListLocked(displayId); + final boolean keyguardGoingAwayToShade = + (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0; + final boolean keyguardGoingAwayNoAnimation = + (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0; + final boolean keyguardGoingAwayWithWallpaper = + (mKeyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0; + if (mKeyguardGoingAway) { for (int i = windows.size() - 1; i >= 0; i--) { WindowState win = windows.get(i); @@ -261,6 +270,8 @@ public class WindowAnimator { winAnimator.mAnimationIsEntrance = false; winAnimator.mAnimationStartTime = -1; winAnimator.mKeyguardGoingAwayAnimation = true; + winAnimator.mKeyguardGoingAwayWithWallpaper + = keyguardGoingAwayWithWallpaper; } } else { if (DEBUG_KEYGUARD) Slog.d(TAG, @@ -392,10 +403,13 @@ public class WindowAnimator { if (DEBUG_KEYGUARD) Slog.v(TAG, "Applying existing Keyguard exit animation to new window: win=" + win); - Animation a = mPolicy.createForceHideEnterAnimation( - false, mKeyguardGoingAwayToNotificationShade); + + Animation a = mPolicy.createForceHideEnterAnimation(false, + keyguardGoingAwayToShade); winAnimator.setAnimation(a, mPostKeyguardExitAnimation.getStartTime()); winAnimator.mKeyguardGoingAwayAnimation = true; + winAnimator.mKeyguardGoingAwayWithWallpaper + = keyguardGoingAwayWithWallpaper; } final WindowState currentFocus = mService.mCurrentFocus; if (currentFocus == null || currentFocus.mLayer < win.mLayer) { @@ -463,18 +477,20 @@ public class WindowAnimator { // being force-hidden, apply the appropriate animation to them if animations are not // disabled. if (unForceHiding != null) { - if (!mKeyguardGoingAwayDisableWindowAnimations) { + if (!keyguardGoingAwayNoAnimation) { boolean first = true; for (int i=unForceHiding.size()-1; i>=0; i--) { final WindowStateAnimator winAnimator = unForceHiding.get(i); Animation a = mPolicy.createForceHideEnterAnimation( wallpaperInUnForceHiding && !startingInUnForceHiding, - mKeyguardGoingAwayToNotificationShade); + keyguardGoingAwayToShade); if (a != null) { if (DEBUG_KEYGUARD) Slog.v(TAG, "Starting keyguard exit animation on window " + winAnimator.mWin); winAnimator.setAnimation(a); winAnimator.mKeyguardGoingAwayAnimation = true; + winAnimator.mKeyguardGoingAwayWithWallpaper + = keyguardGoingAwayWithWallpaper; if (first) { mPostKeyguardExitAnimation = a; mPostKeyguardExitAnimation.setStartTime(mCurrentTime); @@ -489,11 +505,10 @@ public class WindowAnimator { // Wallpaper is going away in un-force-hide motion, animate it as well. - if (!wallpaperInUnForceHiding && wallpaper != null - && !mKeyguardGoingAwayDisableWindowAnimations) { + if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) { if (DEBUG_KEYGUARD) Slog.d(TAG, "updateWindowsLocked: wallpaper animating away"); Animation a = mPolicy.createForceHideWallpaperExitAnimation( - mKeyguardGoingAwayToNotificationShade); + keyguardGoingAwayToShade); if (a != null) { wallpaper.mWinAnimator.setAnimation(a); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 304449dd9f98..607a3e96ecba 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2626,7 +2626,8 @@ public class WindowManagerService extends IWindowManager.Stub } // Odd choice but less odd than embedding in copyFrom() - if ((attrs.flags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) != 0) { + if ((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) + != 0) { attrs.x = win.mAttrs.x; attrs.y = win.mAttrs.y; attrs.width = win.mAttrs.width; @@ -2825,10 +2826,12 @@ public class WindowManagerService extends IWindowManager.Stub if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) { focusMayChange = isDefaultDisplay; win.mAnimatingExit = true; + win.mWinAnimator.mAnimating = true; } else if (win.mWinAnimator.isAnimating()) { // Currently in a hide animation... turn this into // an exit. win.mAnimatingExit = true; + win.mWinAnimator.mAnimating = true; } else if (mWallpaperControllerLocked.isWallpaperTarget(win)) { // If the wallpaper is currently behind this // window, we need to change both of them inside @@ -4085,7 +4088,7 @@ public class WindowManagerService extends IWindowManager.Stub if (transit != AppTransition.TRANSIT_UNSET) { if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { - wtoken.mAppAnimator.animation = null; + wtoken.mAppAnimator.setNullAnimation(); } if (applyAnimationLocked(wtoken, lp, transit, visible, isVoiceInteraction)) { delayed = runningAppAnimation = true; @@ -4195,7 +4198,7 @@ public class WindowManagerService extends IWindowManager.Stub void updateTokenInPlaceLocked(AppWindowToken wtoken, int transit) { if (transit != AppTransition.TRANSIT_UNSET) { if (wtoken.mAppAnimator.animation == AppWindowAnimator.sDummyAnimation) { - wtoken.mAppAnimator.animation = null; + wtoken.mAppAnimator.setNullAnimation(); } applyAnimationLocked(wtoken, null, transit, false, false); } @@ -4252,17 +4255,12 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.appDied = false; wtoken.removeAllWindows(); } else if (visible) { - if (DEBUG_ADD_REMOVE) Slog.v( - TAG_WM, "No longer Stopped: " + wtoken); - wtoken.mAppStopped = false; - wtoken.setWindowsExiting(false); mOpeningApps.add(wtoken); wtoken.startingMoved = false; - // If the token is currently hidden (should be the - // common case), then we need to set up to wait for - // its windows to be ready. - if (wtoken.hidden) { + // If the token is currently hidden (should be the common case), or has been + // stopped, then we need to set up to wait for its windows to be ready. + if (wtoken.hidden || wtoken.mAppStopped) { wtoken.allDrawn = false; wtoken.deferClearAllDrawn = false; wtoken.waitingToShow = true; @@ -4278,6 +4276,9 @@ public class WindowManagerService extends IWindowManager.Stub wtoken.sendAppVisibilityToClients(); } } + if (DEBUG_ADD_REMOVE) Slog.v( + TAG_WM, "No longer Stopped: " + wtoken); + wtoken.mAppStopped = false; } // If we are preparing an app transition, then delay changing @@ -4287,6 +4288,11 @@ public class WindowManagerService extends IWindowManager.Stub // animation is going on (in this case an application transition). If the animation // was transferred from another application/animator, no dummy animator should be // created since an animation is already in progress. + if (wtoken.mAppAnimator.usingTransferredAnimation + && wtoken.mAppAnimator.animation == null) { + Slog.wtf(TAG_WM, "Will NOT set dummy animation on: " + wtoken + + ", using null transfered animation!"); + } if (!wtoken.mAppAnimator.usingTransferredAnimation && (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) { if (DEBUG_APP_TRANSITIONS) Slog.v( @@ -4297,7 +4303,6 @@ public class WindowManagerService extends IWindowManager.Stub if (visible) { wtoken.mEnteringAnimation = true; } else { - wtoken.setWindowsExiting(true); mClosingApps.add(wtoken); wtoken.mEnteringAnimation = false; } @@ -5173,18 +5178,16 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) { + public void keyguardGoingAway(int flags) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires DISABLE_KEYGUARD permission"); } - if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "keyguardGoingAway: disableWinAnim=" - + disableWindowAnimations + " kgToNotifShade=" + keyguardGoingToNotificationShade); + if (DEBUG_KEYGUARD) Slog.d(TAG_WM, + "keyguardGoingAway: flags=0x" + Integer.toHexString(flags)); synchronized (mWindowMap) { mAnimator.mKeyguardGoingAway = true; - mAnimator.mKeyguardGoingAwayToNotificationShade = keyguardGoingToNotificationShade; - mAnimator.mKeyguardGoingAwayDisableWindowAnimations = disableWindowAnimations; + mAnimator.mKeyguardGoingAwayFlags = flags; mWindowPlacerLocked.requestTraversal(); } } @@ -9907,6 +9910,9 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(mLastFinishedFreezeSource); } pw.println(); + + mInputMonitor.dump(pw, " "); + if (dumpAll) { pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer); pw.print(" mScreenRect="); pw.println(mScreenRect.toShortString()); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 910788ea8b91..1695615fedda 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -642,18 +642,26 @@ final class WindowState implements WindowManagerPolicy.WindowState { mHaveFrame = true; final Task task = getTask(); - final boolean fullscreenTask = task == null || task.isFullscreen(); + final boolean fullscreenTask = !inMultiWindowMode(); final boolean windowsAreFloating = task != null && task.isFloating(); - if (fullscreenTask || (isChildWindow() - && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0)) { + // If the task has temp inset bounds set, we have to make sure all its windows uses + // the temp inset frame. Otherwise different display frames get applied to the main + // window and the child window, making them misaligned. + if (fullscreenTask) { + mInsetFrame.setEmpty(); + } else { + task.getTempInsetBounds(mInsetFrame); + } + + if (mInsetFrame.isEmpty() && (fullscreenTask + || (isChildWindow() && (mAttrs.privateFlags + & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0))) { // We use the parent frame as the containing frame for fullscreen and child windows mContainingFrame.set(pf); mDisplayFrame.set(df); - mInsetFrame.setEmpty(); } else { task.getBounds(mContainingFrame); - task.getTempInsetBounds(mInsetFrame); if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) { // If the bounds are frozen, we still want to translate the window freely and only @@ -670,8 +678,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { } if (windowsAreFloating) { - // In floating modes (e.g. freeform, pinned) we have only to set the rectangle - // if it wasn't set already. No need to intersect it with the (visible) + // In floating modes (e.g. freeform, pinned) we have only to set the rectangle + // if it wasn't set already. No need to intersect it with the (visible) // "content frame" since it is allowed to be outside the visible desktop. if (mContainingFrame.isEmpty()) { mContainingFrame.set(cf); @@ -2215,6 +2223,12 @@ final class WindowState implements WindowManagerPolicy.WindowState { return task != null && task.inFreeformWorkspace(); } + @Override + public boolean inMultiWindowMode() { + final Task task = getTask(); + return task != null && !task.isFullscreen(); + } + boolean isDragResizeChanged() { return mDragResizing != computeDragResizing(); } @@ -2506,9 +2520,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { final int pw = mContainingFrame.width(); final int ph = mContainingFrame.height(); final Task task = getTask(); - final boolean nonFullscreenTask = task != null && !task.isFullscreen(); - final boolean fitToDisplay = task != null && - !task.isFloating(); + final boolean nonFullscreenTask = inMultiWindowMode(); + final boolean fitToDisplay = task != null && !task.isFloating(); float x, y; int w,h; diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index bf8a62e5787d..41eafe742321 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -160,6 +160,7 @@ class WindowStateAnimator { boolean mEnteringAnimation; boolean mKeyguardGoingAwayAnimation; + boolean mKeyguardGoingAwayWithWallpaper; /** The pixel format of the underlying SurfaceControl */ int mSurfaceFormat; @@ -250,6 +251,7 @@ class WindowStateAnimator { mAnimation.cancel(); mAnimation = null; mKeyguardGoingAwayAnimation = false; + mKeyguardGoingAwayWithWallpaper = false; } } @@ -381,6 +383,7 @@ class WindowStateAnimator { mAnimating = false; mKeyguardGoingAwayAnimation = false; + mKeyguardGoingAwayWithWallpaper = false; mLocalAnimating = false; if (mAnimation != null) { mAnimation.cancel(); @@ -708,8 +711,6 @@ class WindowStateAnimator { // Start a new transaction and apply position & offset. final int layerStack = w.getDisplayContent().getDisplay().getLayerStack(); - if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w, - "POS " + mTmpSize.left + ", " + mTmpSize.top, false); mSurfaceController.setPositionAndLayer(mTmpSize.left, mTmpSize.top, layerStack, mAnimLayer); mLastHidden = true; @@ -1216,17 +1217,17 @@ class WindowStateAnimator { } // We don't apply the stack bounds crop if: - // 1. The window is currently animating docked mode or in freeform mode, otherwise the - // animating window will be suddenly (docked) or for whole animation (freeform) cut off. - // (Note that we still need to apply the crop if the task being docked is non-resizeable, - // in which case the task is running in fullscreen size but cropped to stack bounds.) + // 1. The window is currently animating in freeform mode, otherwise the animating window + // will be suddenly (docked) or for whole animation (freeform) cut off. // 2. The window that is being replaced during animation, because it was living in a // different stack. If we suddenly crop it to the new stack bounds, it might get cut off. // We don't want it to happen, so we let it ignore the stack bounds until it gets removed. // The window that will replace it will abide them. - if (isAnimating() && (w.mWillReplaceWindow - || (w.inDockedWorkspace() && task.isResizeable()) - || w.inFreeformWorkspace())) { + // TODO: identify animations where we don't want to apply docked stack crop to the docked + // task. For example, if the app is going from freeform to docked mode, we may not + // want to apply the crop during the animation, since it will make the app appear + // cropped prematurely. + if (isAnimating() && (w.mWillReplaceWindow || w.inFreeformWorkspace())) { return; } diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index fb07512f16e2..11f37719f047 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -119,6 +119,8 @@ class WindowSurfaceController { mSurfaceY = top; try { + if (SHOW_TRANSACTIONS) logSurface( + "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null); mSurfaceControl.setPosition(left, top); mSurfaceControl.setLayerStack(layerStack); @@ -205,6 +207,9 @@ class WindowSurfaceController { mSurfaceY = top; try { + if (SHOW_TRANSACTIONS) logSurface( + "POS (setPositionInTransaction) @ (" + left + "," + top + ")", null); + mSurfaceControl.setPosition(left, top); } catch (RuntimeException e) { Slog.w(TAG, "Error positioning surface of " + this diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 8ada2f1a1646..5ad771fbcd04 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -1158,7 +1158,7 @@ class WindowSurfacePlacer { if (!appAnimator.usingTransferredAnimation) { appAnimator.clearThumbnail(); - appAnimator.animation = null; + appAnimator.setNullAnimation(); } wtoken.inPendingTransaction = false; @@ -1231,7 +1231,7 @@ class WindowSurfacePlacer { final AppWindowAnimator appAnimator = wtoken.mAppAnimator; if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken); appAnimator.clearThumbnail(); - appAnimator.animation = null; + appAnimator.setNullAnimation(); wtoken.inPendingTransaction = false; mService.setTokenVisibilityLocked(wtoken, animLp, false, transit, false, voiceInteraction); @@ -1494,7 +1494,7 @@ class WindowSurfacePlacer { if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now animating app in place " + wtoken); appAnimator.clearThumbnail(); - appAnimator.animation = null; + appAnimator.setNullAnimation(); mService.updateTokenInPlaceLocked(wtoken, transit); wtoken.updateReportedVisibilityLocked(); diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp index 6c640ba55042..c4316f63220d 100644 --- a/services/core/jni/com_android_server_tv_TvInputHal.cpp +++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp @@ -400,7 +400,7 @@ int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface> connection.mThread->shutdown(); } connection.mThread = new BufferProducerThread(mDevice, deviceId, &stream); - connection.mThread->run(); + connection.mThread->run("BufferProducerThread"); } } connection.mSurface = surface; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index ea1a569b8e5c..6ddc6c83ed23 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -26,13 +26,12 @@ import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.TEXT; -import com.google.android.collect.Sets; - import android.Manifest.permission; import android.accessibilityservice.AccessibilityServiceInfo; import android.accounts.AccountManager; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; @@ -49,10 +48,10 @@ import android.app.admin.DeviceAdminReceiver; import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.IDevicePolicyManager; +import android.app.admin.SecurityLog; +import android.app.admin.SecurityLog.SecurityEvent; import android.app.admin.SystemUpdatePolicy; import android.app.backup.IBackupManager; -import android.auditing.SecurityLog; -import android.auditing.SecurityLog.SecurityEvent; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -83,6 +82,7 @@ import android.net.wifi.WifiManager; import android.os.AsyncTask; import android.os.Binder; import android.os.Build; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Environment; import android.os.FileUtils; @@ -113,6 +113,7 @@ import android.security.IKeyChainService; import android.security.KeyChain; import android.security.KeyChain.KeyChainConnection; import android.service.persistentdata.PersistentDataBlockManager; +import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -139,6 +140,7 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo; import com.android.server.pm.UserRestrictionsUtils; +import com.google.android.collect.Sets; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -304,6 +306,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { final IPackageManager mIPackageManager; final UserManager mUserManager; final UserManagerInternal mUserManagerInternal; + final TelephonyManager mTelephonyManager; private final LockPatternUtils mLockPatternUtils; /** @@ -480,9 +483,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { new MonitoringCertNotificationTask().execute(intent); } if (Intent.ACTION_USER_ADDED.equals(action)) { - disableDeviceLoggingIfNotCompliant(); + disableSecurityLoggingIfNotCompliant(); } else if (Intent.ACTION_USER_REMOVED.equals(action)) { - disableDeviceLoggingIfNotCompliant(); + disableSecurityLoggingIfNotCompliant(); removeUserData(userHandle); } else if (Intent.ACTION_USER_STARTED.equals(action)) { synchronized (DevicePolicyManagerService.this) { @@ -1352,6 +1355,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return LocalServices.getService(PowerManagerInternal.class); } + TelephonyManager getTelephonyManager() { + return TelephonyManager.from(mContext); + } + IWindowManager getIWindowManager() { return IWindowManager.Stub .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE)); @@ -1378,6 +1385,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return new LockPatternUtils(mContext); } + boolean storageManagerIsFileBasedEncryptionEnabled() { + return StorageManager.isFileEncryptedNativeOnly(); + } + + boolean storageManagerIsNonDefaultBlockEncrypted() { + return StorageManager.isNonDefaultBlockEncrypted(); + } + + boolean storageManagerIsEncrypted() { + return StorageManager.isEncrypted(); + } + + boolean storageManagerIsEncryptable() { + return StorageManager.isEncryptable(); + } + Looper getMyLooper() { return Looper.myLooper(); } @@ -1524,6 +1547,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mUserManager = Preconditions.checkNotNull(injector.getUserManager()); mUserManagerInternal = Preconditions.checkNotNull(injector.getUserManagerInternal()); mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager()); + mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager()); mLocalService = new LocalService(); mLockPatternUtils = injector.newLockPatternUtils(); @@ -1646,12 +1670,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else { if (mOwners.hasDeviceOwner()) { mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "true"); - disableDeviceLoggingIfNotCompliant(); + Slog.i(LOG_TAG, "Set ro.device_owner property to true"); + disableSecurityLoggingIfNotCompliant(); if (mInjector.securityLogGetLoggingEnabledProperty()) { mSecurityLogMonitor.start(); } } else { mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, "false"); + Slog.i(LOG_TAG, "Set ro.device_owner property to false"); } } } @@ -2866,13 +2892,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public boolean isSeparateProfileChallengeAllowed(int userHandle) { ComponentName profileOwner = getProfileOwner(userHandle); - try { - // Profile challenge is supported on N or newer release. - return profileOwner != null && - getTargetSdk(profileOwner.getPackageName(), userHandle) > Build.VERSION_CODES.M; - } catch (RemoteException e) { - return false; - } + // Profile challenge is supported on N or newer release. + return profileOwner != null && + getTargetSdk(profileOwner.getPackageName(), userHandle) > Build.VERSION_CODES.M; } @Override @@ -4236,15 +4258,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int userHandle = UserHandle.getCallingUserId(); synchronized (this) { getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - try { - if (getTargetSdk(who.getPackageName(), userHandle) >= Build.VERSION_CODES.N) { - if (installerPackage != null && - !isPackageInstalledForUser(installerPackage, userHandle)) { - throw new IllegalArgumentException("Package " + installerPackage - + " is not installed on the current user"); - } + if (getTargetSdk(who.getPackageName(), userHandle) >= Build.VERSION_CODES.N) { + if (installerPackage != null && + !isPackageInstalledForUser(installerPackage, userHandle)) { + throw new IllegalArgumentException("Package " + installerPackage + + " is not installed on the current user"); } - } catch (RemoteException e) { } DevicePolicyData policy = getUserData(userHandle); policy.mDelegatedCertInstallerPackage = installerPackage; @@ -4835,12 +4854,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Get the current encryption status of the device. */ @Override - public int getStorageEncryptionStatus(int userHandle) { + public int getStorageEncryptionStatus(@Nullable String callerPackage, int userHandle) { if (!mHasFeature) { // Ok to return current status. } enforceFullCrossUsersPermission(userHandle); - return getEncryptionStatus(); + + // It's not critical here, but let's make sure the package name is correct, in case + // we start using it for different purposes. + ensureCallerPackage(callerPackage); + + final int rawStatus = getEncryptionStatus(); + if ((rawStatus == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER) + && (callerPackage != null) + && (getTargetSdk(callerPackage, userHandle) <= VERSION_CODES.M)) { + return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE; + } + return rawStatus; } /** @@ -4858,15 +4888,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Hook to low-levels: Reporting the current status of encryption. * @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED}, * {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE}, - * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY}, or + * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY}, + * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE_PER_USER}, or * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}. */ private int getEncryptionStatus() { - if (StorageManager.isEncrypted()) { - return StorageManager.isNonDefaultBlockEncrypted() ? - DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE - : DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY; - } else if (StorageManager.isEncryptable()) { + if (mInjector.storageManagerIsFileBasedEncryptionEnabled()) { + return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER; + } else if (mInjector.storageManagerIsNonDefaultBlockEncrypted()) { + return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE; + } else if (mInjector.storageManagerIsEncrypted()) { + return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY; + } else if (mInjector.storageManagerIsEncryptable()) { return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE; } else { return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED; @@ -4879,7 +4912,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void setEncryptionRequested(boolean encrypt) { } - /** * Set whether the screen capture is disabled for the user managed by the specified admin. */ @@ -5579,7 +5611,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mOwners.clearDeviceOwner(); mOwners.writeDeviceOwner(); updateDeviceOwnerLocked(); - disableDeviceLoggingIfNotCompliant(); + disableSecurityLoggingIfNotCompliant(); // Reactivate backup service. long ident = mInjector.binderClearCallingIdentity(); try { @@ -6037,6 +6069,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + private void ensureCallerPackage(@Nullable String packageName) { + if (packageName == null) { + Preconditions.checkState(isCallerWithSystemUid(), + "Only caller can omit package name"); + } else { + final int callingUid = mInjector.binderGetCallingUid(); + final int userId = mInjector.userHandleGetCallingUserId(); + try { + final ApplicationInfo ai = mIPackageManager.getApplicationInfo( + packageName, 0, userId); + Preconditions.checkState(ai.uid == callingUid, "Unmatching package name"); + } catch (RemoteException e) { + // Shouldn't happen + } + } + } + private boolean isCallerWithSystemUid() { return UserHandle.isSameApp(mInjector.binderGetCallingUid(), Process.SYSTEM_UID); } @@ -6122,6 +6171,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { pw.println(" "); pw.print(" mPasswordOwner="); pw.println(policy.mPasswordOwner); } + pw.println(); + pw.println("Encryption Status: " + getEncryptionStatusName(getEncryptionStatus())); + } + } + + private String getEncryptionStatusName(int encryptionStatus) { + switch (encryptionStatus) { + case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE: + return "inactive"; + case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY: + return "block default key"; + case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE: + return "block"; + case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER: + return "per-user"; + case DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED: + return "unsupported"; + case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVATING: + return "activating"; + default: + return "unknown"; } } @@ -7831,6 +7901,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } return false; } + + @Override + public Intent createPackageSuspendedDialogIntent(String packageName, int userId) { + Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS); + intent.putExtra(Intent.EXTRA_USER_ID, userId); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + synchronized (DevicePolicyManagerService.this) { + ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); + if (profileOwner != null) { + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, profileOwner); + return intent; + } + + if (mOwners.getDeviceOwnerUserId() == userId) { + ComponentName deviceOwner = mOwners.getDeviceOwnerComponent(); + if (deviceOwner != null) { + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceOwner); + return intent; + } + } + } + return null; + } } /** @@ -8207,11 +8300,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { * Returns the target sdk version number that the given packageName was built for * in the given user. */ - private int getTargetSdk(String packageName, int userId) throws RemoteException { - final ApplicationInfo ai = mIPackageManager - .getApplicationInfo(packageName, 0, userId); - final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion; - return targetSdkVersion; + private int getTargetSdk(String packageName, int userId) { + final ApplicationInfo ai; + try { + ai = mIPackageManager.getApplicationInfo(packageName, 0, userId); + final int targetSdkVersion = ai == null ? 0 : ai.targetSdkVersion; + return targetSdkVersion; + } catch (RemoteException e) { + // Shouldn't happen + return 0; + } } @Override @@ -8242,6 +8340,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } long ident = mInjector.binderClearCallingIdentity(); try { + // Make sure there are no ongoing calls on the device. + if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { + throw new IllegalStateException("Cannot be called with ongoing call on the device"); + } mInjector.powerManagerReboot(PowerManager.REBOOT_REQUESTED_BY_DEVICE_OWNER); } finally { mInjector.binderRestoreCallingIdentity(ident); @@ -8495,15 +8597,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return false; } - private synchronized void disableDeviceLoggingIfNotCompliant() { + private synchronized void disableSecurityLoggingIfNotCompliant() { if (!isDeviceOwnerManagedSingleUserDevice()) { mInjector.securityLogSetLoggingEnabledProperty(false); - Slog.w(LOG_TAG, "Device logging turned off as it's no longer a single user device."); + Slog.w(LOG_TAG, "Security logging turned off as it's no longer a single user device."); } } @Override - public void setDeviceLoggingEnabled(ComponentName admin, boolean enabled) { + public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) { Preconditions.checkNotNull(admin); ensureDeviceOwnerManagingSingleUser(admin); @@ -8521,7 +8623,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public boolean getDeviceLoggingEnabled(ComponentName admin) { + public boolean isSecurityLoggingEnabled(ComponentName admin) { Preconditions.checkNotNull(admin); synchronized (this) { getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); @@ -8530,7 +8632,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public ParceledListSlice<SecurityEvent> retrievePreviousDeviceLogs(ComponentName admin) { + public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) { Preconditions.checkNotNull(admin); ensureDeviceOwnerManagingSingleUser(admin); @@ -8545,7 +8647,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override - public ParceledListSlice<SecurityEvent> retrieveDeviceLogs(ComponentName admin) { + public ParceledListSlice<SecurityEvent> retrieveSecurityLogs(ComponentName admin) { Preconditions.checkNotNull(admin); ensureDeviceOwnerManagingSingleUser(admin); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java index cacc671df393..79702a8de505 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java @@ -17,8 +17,8 @@ package com.android.server.devicepolicy; import android.app.admin.DeviceAdminReceiver; -import android.auditing.SecurityLog; -import android.auditing.SecurityLog.SecurityEvent; +import android.app.admin.SecurityLog; +import android.app.admin.SecurityLog.SecurityEvent; import android.util.Log; import android.util.Slog; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index e7daaa15d247..5975405f5216 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -28,6 +28,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources.Theme; +import android.os.BaseBundle; import android.os.Build; import android.os.Environment; import android.os.FactoryTest; @@ -35,7 +36,6 @@ import android.os.FileUtils; import android.os.IPowerManager; import android.os.Looper; import android.os.PowerManager; -import android.os.RecoverySystem; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StrictMode; @@ -53,6 +53,7 @@ import com.android.internal.R; import com.android.internal.os.BinderInternal; import com.android.internal.os.SamplingProfilerIntegration; import com.android.internal.os.ZygoteInit; +import com.android.internal.widget.ILockSettings; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.accounts.AccountManagerService; import com.android.server.am.ActivityManagerService; @@ -69,10 +70,9 @@ import com.android.server.hdmi.HdmiControlService; import com.android.server.input.InputManagerService; import com.android.server.job.JobSchedulerService; import com.android.server.lights.LightsService; -import com.android.internal.widget.ILockSettings; +import com.android.server.media.MediaResourceMonitorService; import com.android.server.media.MediaRouterService; import com.android.server.media.MediaSessionService; -import com.android.server.media.MediaResourceMonitorService; import com.android.server.media.projection.MediaProjectionManagerService; import com.android.server.net.NetworkPolicyManagerService; import com.android.server.net.NetworkStatsService; @@ -271,6 +271,10 @@ public final class SystemServer { // explicitly specifying a user. Environment.setUserRequired(true); + // Within the system server, any incoming Bundles should be defused + // to avoid throwing BadParcelableException. + BaseBundle.setShouldDefuse(true); + // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); @@ -518,6 +522,16 @@ public final class SystemServer { boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false); boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false); boolean disableRtt = SystemProperties.getBoolean("config.disable_rtt", false); + boolean disableMediaProjection = SystemProperties.getBoolean("config.disable_mediaproj", + false); + boolean disableSerial = SystemProperties.getBoolean("config.disable_serial", false); + boolean disableSearchManager = SystemProperties.getBoolean("config.disable_searchmanager", + false); + boolean disableTrustManager = SystemProperties.getBoolean("config.disable_trustmanager", + false); + boolean disableTextServices = SystemProperties.getBoolean("config.disable_textservices", false); + boolean disableSamplingProfiler = SystemProperties.getBoolean("config.disable_samplingprof", + false); boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1"); try { @@ -761,7 +775,7 @@ public final class SystemServer { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } - if (!disableNonCoreServices) { + if (!disableNonCoreServices && !disableTextServices) { mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class); } @@ -912,7 +926,7 @@ public final class SystemServer { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } - if (!disableNonCoreServices) { + if (!disableNonCoreServices && !disableSearchManager) { traceBeginAndSlog("StartSearchManagerService"); try { mSystemServiceManager.startService(SEARCH_MANAGER_SERVICE_CLASS); @@ -974,15 +988,17 @@ public final class SystemServer { Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } - traceBeginAndSlog("StartSerialService"); - try { - // Serial port support - serial = new SerialService(context); - ServiceManager.addService(Context.SERIAL_SERVICE, serial); - } catch (Throwable e) { - Slog.e(TAG, "Failure starting SerialService", e); + if (!disableSerial) { + traceBeginAndSlog("StartSerialService"); + try { + // Serial port support + serial = new SerialService(context); + ServiceManager.addService(Context.SERIAL_SERVICE, serial); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting SerialService", e); + } + Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } - Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartHardwarePropertiesManagerService"); @@ -1020,6 +1036,7 @@ public final class SystemServer { mSystemServiceManager.startService(GestureLauncherService.class); } mSystemServiceManager.startService(SensorNotificationService.class); + mSystemServiceManager.startService(ContextHubSystemService.class); } traceBeginAndSlog("StartDiskStatsService"); @@ -1030,18 +1047,20 @@ public final class SystemServer { } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); - traceBeginAndSlog("StartSamplingProfilerService"); - try { - // need to add this service even if SamplingProfilerIntegration.isEnabled() - // is false, because it is this service that detects system property change and - // turns on SamplingProfilerIntegration. Plus, when sampling profiler doesn't work, - // there is little overhead for running this service. - ServiceManager.addService("samplingprofiler", - new SamplingProfilerService(context)); - } catch (Throwable e) { - reportWtf("starting SamplingProfiler Service", e); + if (!disableSamplingProfiler) { + traceBeginAndSlog("StartSamplingProfilerService"); + try { + // need to add this service even if SamplingProfilerIntegration.isEnabled() + // is false, because it is this service that detects system property change and + // turns on SamplingProfilerIntegration. Plus, when sampling profiler doesn't work, + // there is little overhead for running this service. + ServiceManager.addService("samplingprofiler", + new SamplingProfilerService(context)); + } catch (Throwable e) { + reportWtf("starting SamplingProfiler Service", e); + } + Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); } - Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); if (!disableNetwork && !disableNetworkTime) { traceBeginAndSlog("StartNetworkTimeUpdateService"); @@ -1122,7 +1141,9 @@ public final class SystemServer { } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); - mSystemServiceManager.startService(TrustManagerService.class); + if (!disableTrustManager) { + mSystemServiceManager.startService(TrustManagerService.class); + } if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { mSystemServiceManager.startService(FingerprintService.class); @@ -1142,7 +1163,7 @@ public final class SystemServer { mSystemServiceManager.startService(LauncherAppsService.class); } - if (!disableNonCoreServices) { + if (!disableNonCoreServices && !disableMediaProjection) { mSystemServiceManager.startService(MediaProjectionManagerService.class); } diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java index 69f12eb5b08c..34f2e2e12594 100644 --- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java @@ -161,9 +161,11 @@ public class ConnectivityServiceTest extends AndroidTestCase { assertNull("BUG: only one idle handler allowed", mIdleHandler); mIdleHandler = new IdleHandler() { public boolean queueIdle() { - cv.open(); - mIdleHandler = null; - return false; // Remove the handler. + synchronized (queue) { + cv.open(); + mIdleHandler = null; + return false; // Remove the handler. + } } }; queue.addIdleHandler(mIdleHandler); diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java index db2a9ad3223c..35777ce86c4a 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java @@ -28,6 +28,8 @@ import android.os.PowerManagerInternal; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; +import android.os.storage.StorageManager; +import android.telephony.TelephonyManager; import android.view.IWindowManager; import java.io.File; @@ -163,6 +165,26 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi } @Override + boolean storageManagerIsFileBasedEncryptionEnabled() { + return context.storageManager.isFileBasedEncryptionEnabled(); + } + + @Override + boolean storageManagerIsNonDefaultBlockEncrypted() { + return context.storageManager.isNonDefaultBlockEncrypted(); + } + + @Override + boolean storageManagerIsEncrypted() { + return context.storageManager.isEncrypted(); + } + + @Override + boolean storageManagerIsEncryptable() { + return context.storageManager.isEncryptable(); + } + + @Override String getDevicePolicyFilePathForSystemUser() { return context.systemUserDataDir.getAbsolutePath() + "/"; } @@ -301,5 +323,10 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi boolean securityLogIsLoggingEnabled() { return context.settings.securityLogIsLoggingEnabled(); } + + @Override + TelephonyManager getTelephonyManager() { + return context.telephonyManager; + } } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index e897e3d20edf..6c2bdda3e21a 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -33,6 +33,7 @@ import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.telephony.TelephonyManager; import android.test.MoreAsserts; import android.test.suitebuilder.annotation.SmallTest; import android.util.ArraySet; @@ -1491,7 +1492,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1)); } - public void testRebootCanOnlyBeCalledByDeviceOwner() throws Exception { + public void testReboot() throws Exception { mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS); mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS); @@ -1524,6 +1525,29 @@ public class DevicePolicyManagerTest extends DpmTestBase { dpm.clearProfileOwner(admin1); assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM)); + // admin1 is DO. + // Set current call state of device to ringing. + when(mContext.telephonyManager.getCallState()) + .thenReturn(TelephonyManager.CALL_STATE_RINGING); + try { + dpm.reboot(admin1); + fail("DPM.reboot() called when receiveing a call, should thrown IllegalStateException"); + } catch (IllegalStateException expected) { + MoreAsserts.assertContainsRegex("ongoing call on the device", expected.getMessage()); + } + + // Set current call state of device to dialing/active. + when(mContext.telephonyManager.getCallState()) + .thenReturn(TelephonyManager.CALL_STATE_OFFHOOK); + try { + dpm.reboot(admin1); + fail("DPM.reboot() called when dialing, should thrown IllegalStateException"); + } catch (IllegalStateException expected) { + MoreAsserts.assertContainsRegex("ongoing call on the device", expected.getMessage()); + } + + // Set current call state of device to idle. + when(mContext.telephonyManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_IDLE); dpm.reboot(admin1); } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java index ef8e420e53f0..8e2ef703f3c6 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java @@ -39,6 +39,8 @@ import android.os.PowerManagerInternal; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; +import android.os.storage.StorageManager; +import android.telephony.TelephonyManager; import android.test.mock.MockContentResolver; import android.test.mock.MockContext; import android.view.IWindowManager; @@ -211,6 +213,24 @@ public class DpmMockContext extends MockContext { } } + public static class StorageManagerForMock { + public boolean isFileBasedEncryptionEnabled() { + return false; + } + + public boolean isNonDefaultBlockEncrypted() { + return false; + } + + public boolean isEncrypted() { + return false; + } + + public boolean isEncryptable() { + return false; + } + } + public final Context realTestContext; /** @@ -239,9 +259,11 @@ public class DpmMockContext extends MockContext { public final IBackupManager ibackupManager; public final IAudioService iaudioService; public final LockPatternUtils lockPatternUtils; + public final StorageManagerForMock storageManager; public final WifiManager wifiManager; public final SettingsForMock settings; public final MockContentResolver contentResolver; + public final TelephonyManager telephonyManager; /** Note this is a partial mock, not a real mock. */ public final PackageManager packageManager; @@ -272,8 +294,10 @@ public class DpmMockContext extends MockContext { ibackupManager = mock(IBackupManager.class); iaudioService = mock(IAudioService.class); lockPatternUtils = mock(LockPatternUtils.class); + storageManager = mock(StorageManagerForMock.class); wifiManager = mock(WifiManager.class); settings = mock(SettingsForMock.class); + telephonyManager = mock(TelephonyManager.class); // Package manager is huge, so we use a partial mock instead. packageManager = spy(context.getPackageManager()); diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java index b9e9aa9b23ed..82c6b6d8804d 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java @@ -25,7 +25,7 @@ import static org.mockito.Matchers.isA; import static org.mockito.Mockito.when; import static android.net.NetworkStats.SET_DEFAULT; -import static android.net.NetworkStats.ROAMING_DEFAULT; +import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; @@ -447,7 +447,7 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -455,7 +455,7 @@ public class NetworkStatsObserversTest extends TestCase { // Delta uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -487,7 +487,7 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -495,7 +495,7 @@ public class NetworkStatsObserversTest extends TestCase { // Delta uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -527,7 +527,7 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -535,7 +535,7 @@ public class NetworkStatsObserversTest extends TestCase { // Delta uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -567,7 +567,7 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -575,7 +575,7 @@ public class NetworkStatsObserversTest extends TestCase { // Delta uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -607,7 +607,7 @@ public class NetworkStatsObserversTest extends TestCase { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, @@ -615,7 +615,7 @@ public class NetworkStatsObserversTest extends TestCase { // Delta uidSnapshot = new NetworkStats(TEST_START+ 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java index 4f6c7b9484c7..74c19845cd00 100644 --- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsServiceTest.java @@ -23,8 +23,8 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.ROAMING_ALL; -import static android.net.NetworkStats.ROAMING_DEFAULT; -import static android.net.NetworkStats.ROAMING_ROAMING; +import static android.net.NetworkStats.ROAMING_NO; +import static android.net.NetworkStats.ROAMING_YES; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; @@ -321,8 +321,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // verify service recorded history assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); - assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, + assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_NO, 512L, 4L, 256L, 2L, 4); + assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, 6); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); verifyAndReset(); @@ -357,8 +357,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // after systemReady(), we should have historical stats loaded again assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); - assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, + assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_NO, 512L, 4L, 256L, 2L, 4); + assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_NO, 512L, 4L, 256L, 2L, 6); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); verifyAndReset(); @@ -711,11 +711,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase { NetworkStats stats = mSession.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(3, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 50L, 5L, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 50L, 5L, 50L, 5L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 10L, 1L, 10L, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 10L, 1L, 10L, 1L, 1); - assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2048L, 16L, + assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 2048L, 16L, 1024L, 8L, 0); // now verify that recent history only contains one uid @@ -723,7 +723,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { stats = mSession.getSummaryForAllUid( sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true); assertEquals(1, stats.size()); - assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_NO, 1024L, 8L, 512L, 4L, 0); verifyAndReset(); @@ -787,13 +787,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase { final NetworkStats stats = mSession.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(4, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 2L, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L, 128L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 1L, 64L, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L, 1L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 2L, + assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, ROAMING_NO, 32L, 2L, 32L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_DEFAULT, 1L, 1L, 1L, + assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_NO, 1L, 1L, 1L, 1L, 1); verifyAndReset(); @@ -818,13 +818,13 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectCurrentTime(); expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); - // Note that all traffic from NetworkManagementService is tagged as ROAMING_DEFAULT, because + // Note that all traffic from NetworkManagementService is tagged as ROAMING_NO, because // roaming isn't tracked at that layer. We layer it on top by inspecting the iface // properties. expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 2L, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L, 128L, 2L, 0L) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 1L, 64L, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L, 1L, 0L)); expectNetworkStatsPoll(); @@ -838,9 +838,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { final NetworkStats stats = mSession.getSummaryForAllUid( sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(2, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 2L, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 2L, 128L, 2L, 0); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_ROAMING, 64L, 1L, 64L, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L, 1L, 0); verifyAndReset(); @@ -1073,9 +1073,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 2L, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128L, 2L, 128L, 2L, 0L) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 1L, 64L, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64L, 1L, 64L, 1L, 0L)); expectNetworkStatsPoll(); @@ -1089,9 +1089,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { NetworkStats stats = mSession.getSummaryForAllUid( sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(2, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 2L, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128L, 2L, 128L, 2L, 0); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_ROAMING, 64L, 1L, 64L, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64L, 1L, 64L, 1L, 0); verifyAndReset(); @@ -1106,9 +1106,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_NO, 128000000L, 2L, 128000000L, 2L, 0L) - .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_NO, 64000000L, 1L, 64000000L, 1L, 0L)); expectNetworkStatsPoll(); @@ -1122,9 +1122,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { stats = mSession.getSummaryForAllUid( sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(2, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_YES, 128000000L, 2L, 128000000L, 2L, 0); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_ROAMING, + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_YES, 64000000L, 1L, 64000000L, 1L, 0); verifyAndReset(); @@ -1180,7 +1180,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // verify summary API final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end); - assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, rxBytes, + assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_NO, rxBytes, rxPackets, txBytes, txPackets, operations); } @@ -1312,11 +1312,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } List<Integer> roamings = new ArrayList<>(); - if (roaming == ROAMING_DEFAULT || roaming == ROAMING_ALL) { - roamings.add(ROAMING_DEFAULT); + if (roaming == ROAMING_NO || roaming == ROAMING_ALL) { + roamings.add(ROAMING_NO); } - if (roaming == ROAMING_ROAMING || roaming == ROAMING_ALL) { - roamings.add(ROAMING_ROAMING); + if (roaming == ROAMING_YES || roaming == ROAMING_ALL) { + roamings.add(ROAMING_YES); } for (int s : sets) { diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java index f2c42dbb012b..5c5113901cad 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java @@ -15,18 +15,27 @@ */ package com.android.server.pm; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.Activity; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ILauncherApps; import android.content.pm.LauncherApps; import android.content.pm.LauncherApps.ShortcutQuery; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; import android.content.pm.ShortcutServiceInternal; @@ -38,13 +47,17 @@ import android.graphics.drawable.Icon; import android.os.BaseBundle; import android.os.Bundle; import android.os.FileUtils; +import android.os.Handler; +import android.os.Looper; import android.os.ParcelFileDescriptor; +import android.os.Process; import android.os.UserHandle; import android.os.UserManager; -import android.test.AndroidTestCase; +import android.test.InstrumentationTestCase; import android.test.mock.MockContext; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; +import android.util.SparseArray; import com.android.frameworks.servicestests.R; import com.android.internal.util.Preconditions; @@ -57,6 +70,7 @@ import com.android.server.pm.ShortcutService.FileOutputStreamWithPath; import libcore.io.IoUtils; import org.junit.Assert; +import org.mockito.ArgumentCaptor; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; @@ -90,7 +104,7 @@ import java.util.Set; * */ @SmallTest -public class ShortcutManagerTest extends AndroidTestCase { +public class ShortcutManagerTest extends InstrumentationTestCase { private static final String TAG = "ShortcutManagerTest"; /** @@ -116,7 +130,14 @@ public class ShortcutManagerTest extends AndroidTestCase { @Override public Resources getResources() { - return ShortcutManagerTest.this.getContext().getResources(); + return getTestContext().getResources(); + } + + @Override + public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, + IntentFilter filter, String broadcastPermission, Handler scheduler) { + // ignore. + return null; } } @@ -130,13 +151,24 @@ public class ShortcutManagerTest extends AndroidTestCase { /** Context used in the service side */ private final class ServiceContext extends BaseContext { + long injectClearCallingIdentity() { + final int prevCallingUid = mInjectedCallingUid; + mInjectedCallingUid = Process.SYSTEM_UID; + return prevCallingUid; + } + + void injectRestoreCallingIdentity(long token) { + mInjectedCallingUid = (int) token; + } } /** ShortcutService with injection override methods. */ private final class ShortcutServiceTestable extends ShortcutService { - public ShortcutServiceTestable(Context context) { - super(context); + final ServiceContext mContext; + public ShortcutServiceTestable(ServiceContext context) { + super(context); + mContext = context; } @Override @@ -152,6 +184,16 @@ public class ShortcutManagerTest extends AndroidTestCase { } @Override + long injectClearCallingIdentity() { + return mContext.injectClearCallingIdentity(); + } + + @Override + void injectRestoreCallingIdentity(long token) { + mContext.injectRestoreCallingIdentity(token); + } + + @Override int injectDipToPixel(int dip) { return dip; } @@ -191,6 +233,30 @@ public class ShortcutManagerTest extends AndroidTestCase { boolean injectIsLowRamDevice() { return mInjectdIsLowRamDevice; } + + @Override + PackageManagerInternal injectPackageManagerInternal() { + return mMockPackageManagerInternal; + } + + @Override + boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) { + // Sort of hack; do a simpler check. + return LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage); + } + + @Override + void postToHandler(Runnable r) { + final long token = mContext.injectClearCallingIdentity(); + r.run(); + mContext.injectRestoreCallingIdentity(token); + } + + @Override + void wtf(String message, Exception e) { + // During tests, WTF is fatal. + fail(message + " exception: " + e); + } } /** ShortcutManager with injection override methods. */ @@ -206,12 +272,20 @@ public class ShortcutManagerTest extends AndroidTestCase { } private class LauncherAppImplTestable extends LauncherAppsImpl { - public LauncherAppImplTestable(Context context) { + final ServiceContext mContext; + + public LauncherAppImplTestable(ServiceContext context) { super(context); + mContext = context; } @Override public void ensureInUserProfiles(UserHandle userToCheck, String message) { + if (getCallingUserId() == userToCheck.getIdentifier()) { + return; // okay + } + + assertEquals(Process.SYSTEM_UID, mInjectedCallingUid); // SKIP } @@ -219,6 +293,20 @@ public class ShortcutManagerTest extends AndroidTestCase { public void verifyCallingPackage(String callingPackage) { // SKIP } + + @Override + boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, String debugMsg) { + // This requires CROSS_USER + assertEquals(Process.SYSTEM_UID, mInjectedCallingUid); + return user.getIdentifier() == listeningUser.getIdentifier(); + } + + @Override + void postToPackageMonitor(Runnable r) { + final long token = mContext.injectClearCallingIdentity(); + r.run(); + mContext.injectRestoreCallingIdentity(token); + } } private class LauncherAppsTestable extends LauncherApps { @@ -258,6 +346,7 @@ public class ShortcutManagerTest extends AndroidTestCase { private Map<String, Integer> mInjectedPackageUidMap; private PackageManager mMockPackageManager; + private PackageManagerInternal mMockPackageManagerInternal; private UserManager mMockUserManager; private static final String CALLING_PACKAGE_1 = "com.android.test.1"; @@ -275,6 +364,7 @@ public class ShortcutManagerTest extends AndroidTestCase { private static final String LAUNCHER_2 = "com.android.launcher.2"; private static final int LAUNCHER_UID_2 = 10012; + private static final int USER_0 = UserHandle.USER_SYSTEM; private static final int USER_10 = 10; private static final int USER_11 = 11; @@ -298,6 +388,7 @@ public class ShortcutManagerTest extends AndroidTestCase { mClientContext = new ClientContext(); mMockPackageManager = mock(PackageManager.class); + mMockPackageManagerInternal = mock(PackageManagerInternal.class); mMockUserManager = mock(UserManager.class); // Prepare injection values. @@ -311,7 +402,7 @@ public class ShortcutManagerTest extends AndroidTestCase { mInjectedPackageUidMap.put(LAUNCHER_1, LAUNCHER_UID_1); mInjectedPackageUidMap.put(LAUNCHER_2, LAUNCHER_UID_2); - mInjectedFilePathRoot = new File(getContext().getCacheDir(), "test-files"); + mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files"); // Empty the data directory. if (mInjectedFilePathRoot.exists()) { @@ -324,6 +415,10 @@ public class ShortcutManagerTest extends AndroidTestCase { setCaller(CALLING_PACKAGE_1); } + private Context getTestContext() { + return getInstrumentation().getContext(); + } + /** (Re-) init the manager and the service. */ private void initService() { LocalServices.removeServiceForTest(ShortcutServiceInternal.class); @@ -427,6 +522,10 @@ public class ShortcutManagerTest extends AndroidTestCase { + "/" + ShortcutService.FILENAME_USER_PACKAGES); } + private void waitOnMainThread() throws Throwable { + runTestOnUiThread(() -> {}); + } + private static Bundle makeBundle(Object... keysAndValues) { Preconditions.checkState((keysAndValues.length % 2) == 0); @@ -864,9 +963,9 @@ public class ShortcutManagerTest extends AndroidTestCase { } public void testSetDynamicShortcuts() { - final Icon icon1 = Icon.createWithResource(mContext, R.drawable.icon1); + final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.icon1); final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource( - mContext.getResources(), R.drawable.icon2)); + getTestContext().getResources(), R.drawable.icon2)); final ShortcutInfo si1 = makeShortcut( "shortcut1", @@ -907,7 +1006,7 @@ public class ShortcutManagerTest extends AndroidTestCase { dumpsysOnLogcat(); mInjectedCurrentTimeLillis++; // Need to advance the clock for reset to work. - mService.resetThrottlingInner(); + mService.resetThrottlingInner(UserHandle.USER_SYSTEM); dumpsysOnLogcat(); @@ -1148,16 +1247,16 @@ public class ShortcutManagerTest extends AndroidTestCase { } public void testIcons() { - final Icon res32x32 = Icon.createWithResource(mContext, R.drawable.black_32x32); - final Icon res64x64 = Icon.createWithResource(mContext, R.drawable.black_64x64); - final Icon res512x512 = Icon.createWithResource(mContext, R.drawable.black_512x512); + final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32); + final Icon res64x64 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64); + final Icon res512x512 = Icon.createWithResource(getTestContext(), R.drawable.black_512x512); final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource( - mContext.getResources(), R.drawable.black_32x32)); + getTestContext().getResources(), R.drawable.black_32x32)); final Icon bmp64x64 = Icon.createWithBitmap(BitmapFactory.decodeResource( - mContext.getResources(), R.drawable.black_64x64)); + getTestContext().getResources(), R.drawable.black_64x64)); final Icon bmp512x512 = Icon.createWithBitmap(BitmapFactory.decodeResource( - mContext.getResources(), R.drawable.black_512x512)); + getTestContext().getResources(), R.drawable.black_512x512)); // Set from package 1 setCaller(CALLING_PACKAGE_1); @@ -1263,7 +1362,7 @@ public class ShortcutManagerTest extends AndroidTestCase { private void checkShrinkBitmap(int expectedWidth, int expectedHeight, int resId, int maxSize) { assertBitmapSize(expectedWidth, expectedHeight, ShortcutService.shrinkBitmap(BitmapFactory.decodeResource( - mContext.getResources(), resId), + getTestContext().getResources(), resId), maxSize)); } @@ -1418,7 +1517,7 @@ public class ShortcutManagerTest extends AndroidTestCase { runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> { ShortcutInfo s2 = makeShortcutBuilder() .setId("s2") - .setIcon(Icon.createWithResource(mContext, R.drawable.black_32x32)) + .setIcon(Icon.createWithResource(getTestContext(), R.drawable.black_32x32)) .build(); ShortcutInfo s4 = makeShortcutBuilder() @@ -1660,68 +1759,320 @@ public class ShortcutManagerTest extends AndroidTestCase { public void testPinShortcutAndGetPinnedShortcuts() { // Create some shortcuts. - setCaller(CALLING_PACKAGE_1); - final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000); - final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000); + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + final ShortcutInfo s1_1 = makeShortcutWithTimestamp("s1", 1000); + final ShortcutInfo s1_2 = makeShortcutWithTimestamp("s2", 2000); - assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2))); + assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s1_1, s1_2))); + }); - setCaller(CALLING_PACKAGE_2); - final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500); - final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000); - final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500); - assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4))); + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + final ShortcutInfo s2_2 = makeShortcutWithTimestamp("s2", 1500); + final ShortcutInfo s2_3 = makeShortcutWithTimestamp("s3", 3000); + final ShortcutInfo s2_4 = makeShortcutWithTimestamp("s4", 500); + assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2, s2_3, s2_4))); + }); - setCaller(CALLING_PACKAGE_3); - final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000); - assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s2_2))); + runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { + final ShortcutInfo s3_2 = makeShortcutWithTimestamp("s2", 1000); + assertTrue(mManager.setDynamicShortcuts(Arrays.asList(s3_2))); + }); // Pin some. - setCaller(LAUNCHER_1); + runWithCaller(LAUNCHER_1, USER_0, () -> { + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, + Arrays.asList("s2", "s3"), getCallingUser()); - mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, - Arrays.asList("s2", "s3"), getCallingUser()); + mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, + Arrays.asList("s3", "s4", "s5"), getCallingUser()); - mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, - Arrays.asList("s3", "s4", "s5"), getCallingUser()); + mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, + Arrays.asList("s3"), getCallingUser()); // Note ID doesn't exist + }); + + // Delete some. + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertShortcutIds(mManager.getPinnedShortcuts(), "s2"); + mManager.deleteDynamicShortcut("s2"); + assertShortcutIds(mManager.getPinnedShortcuts(), "s2"); + }); + + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4"); + mManager.deleteDynamicShortcut("s3"); + assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4"); + }); + + runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { + assertShortcutIds(mManager.getPinnedShortcuts() /* none */); + mManager.deleteDynamicShortcut("s2"); + assertShortcutIds(mManager.getPinnedShortcuts() /* none */); + }); + + // Get pinned shortcuts from launcher + runWithCaller(LAUNCHER_1, USER_0, () -> { + // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists. + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s2"); + + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s3", "s4"); + + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))) + /* none */); + }); + } + + public void testPinShortcutAndGetPinnedShortcuts_multi() { + // Create some shortcuts. + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertTrue(mManager.setDynamicShortcuts(Arrays.asList( + makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); + }); + + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + assertTrue(mManager.setDynamicShortcuts(Arrays.asList( + makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); + }); + + dumpsysOnLogcat(); - mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, - Arrays.asList("s3"), getCallingUser()); // Note ID doesn't exist + // Pin some. + runWithCaller(LAUNCHER_1, USER_0, () -> { + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, + Arrays.asList("s3", "s4"), getCallingUser()); + + mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, + Arrays.asList("s1", "s2", "s4"), getCallingUser()); + }); + + dumpsysOnLogcat(); // Delete some. - setCaller(CALLING_PACKAGE_1); - assertShortcutIds(mManager.getPinnedShortcuts(), "s2"); - mManager.deleteDynamicShortcut("s2"); - assertShortcutIds(mManager.getPinnedShortcuts(), "s2"); + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertShortcutIds(mManager.getPinnedShortcuts(), "s3"); + mManager.deleteDynamicShortcut("s3"); + assertShortcutIds(mManager.getPinnedShortcuts(), "s3"); + }); - setCaller(CALLING_PACKAGE_2); - assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4"); - mManager.deleteDynamicShortcut("s3"); - assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4"); + dumpsysOnLogcat(); - setCaller(CALLING_PACKAGE_3); - assertShortcutIds(mManager.getPinnedShortcuts() /* none */); - mManager.deleteDynamicShortcut("s2"); - assertShortcutIds(mManager.getPinnedShortcuts() /* none */); + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2"); + mManager.deleteDynamicShortcut("s1"); + mManager.deleteDynamicShortcut("s3"); + assertShortcutIds(mManager.getPinnedShortcuts(), "s1", "s2"); + }); + + dumpsysOnLogcat(); // Get pinned shortcuts from launcher - setCaller(LAUNCHER_1); + runWithCaller(LAUNCHER_1, USER_0, () -> { + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s3"); + + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s1", "s2"); + + assertShortcutIds(assertAllDynamicOrPinned( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())), + "s1", "s2", "s3"); + + assertShortcutIds(assertAllDynamicOrPinned( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())), + "s1", "s2"); + }); - // CALLING_PACKAGE_1 deleted s2, but it's pinned, so it still exists. - assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( - mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, - /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), - "s2"); + dumpsysOnLogcat(); - assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( - mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, - /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), - "s3", "s4"); + runWithCaller(LAUNCHER_2, USER_0, () -> { + // Launcher2 still has no pinned ones. + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))) + /* none */); + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))) + /* none */); - assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( - mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_3, - /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))) - /* none */); + assertShortcutIds(assertAllDynamic( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())), + "s1", "s2"); + assertShortcutIds(assertAllDynamic( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())), + "s2"); + + // Now pin some. + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, + Arrays.asList("s1", "s2"), getCallingUser()); + + mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, + Arrays.asList("s1", "s2"), getCallingUser()); + + assertShortcutIds(assertAllDynamic( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())), + "s1", "s2"); + + // S1 was not visible to it, so shouldn't be pinned. + assertShortcutIds(assertAllDynamic( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())), + "s2"); + }); + + // Re-initialize and load from the files. + initService(); + + runWithCaller(LAUNCHER_1, USER_0, () -> { + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s3"); + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s1", "s2"); + }); + runWithCaller(LAUNCHER_2, USER_0, () -> { + assertShortcutIds(assertAllDynamic( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())), + "s1", "s2"); + assertShortcutIds(assertAllDynamic( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED + | ShortcutQuery.FLAG_GET_DYNAMIC), getCallingUser())), + "s2"); + }); + + // Delete all dynamic. + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + mManager.deleteAllDynamicShortcuts(); + + assertEquals(0, mManager.getDynamicShortcuts().size()); + assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3"); + }); + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + mManager.deleteAllDynamicShortcuts(); + + assertEquals(0, mManager.getDynamicShortcuts().size()); + assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2", "s1"); + }); + + runWithCaller(LAUNCHER_1, USER_0, () -> { + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s3"); + + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s1", "s2"); + + // from all packages. + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, null, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s1", "s2", "s3"); + + // Update pined. Note s2 and s3 are actually available, but not visible to this + // launcher, so still can't be pinned. + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"), + getCallingUser()); + + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s3"); + }); + // Re-publish s1. + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertTrue(mManager.addDynamicShortcut(makeShortcut("s1"))); + + assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1"); + assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2", "s3"); + }); + runWithCaller(LAUNCHER_1, USER_0, () -> { + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s3"); + + // Now "s1" is visible, so can be pinned. + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s1", "s2", "s3", "s4"), + getCallingUser()); + + assertShortcutIds(assertAllPinned(assertAllNotKeyFieldsOnly( + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()))), + "s1", "s3"); + }); + + // Now clear pinned shortcuts. First, from launcher 1. + runWithCaller(LAUNCHER_1, USER_0, () -> { + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser()); + mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser()); + + assertEquals(0, + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size()); + assertEquals(0, + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size()); + }); + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1"); + assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s1", "s2"); + }); + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + assertEquals(0, mManager.getDynamicShortcuts().size()); + assertShortcutIds(assertAllPinned(mManager.getPinnedShortcuts()), "s2"); + }); + + // Clear all pins from launcher 2. + runWithCaller(LAUNCHER_2, USER_0, () -> { + mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList(), getCallingUser()); + mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList(), getCallingUser()); + + assertEquals(0, + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_1, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size()); + assertEquals(0, + mLauncherApps.getShortcuts(buildQuery(/* time =*/ 0, CALLING_PACKAGE_2, + /* activity =*/ null, ShortcutQuery.FLAG_GET_PINNED), getCallingUser()).size()); + }); + runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { + assertShortcutIds(assertAllDynamic(mManager.getDynamicShortcuts()), "s1"); + assertEquals(0, mManager.getPinnedShortcuts().size()); + }); + runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { + assertEquals(0, mManager.getDynamicShortcuts().size()); + assertEquals(0, mManager.getPinnedShortcuts().size()); + }); } public void testCreateShortcutIntent() { @@ -1787,6 +2138,128 @@ public class ShortcutManagerTest extends AndroidTestCase { // TODO Check extra, etc } + public void testLauncherCallback() throws Throwable { + + // TODO Add "multi" version -- run the test with two launchers and make sure the callback + // argument only contains the ones that are actually visible to each launcher. + + LauncherApps.Callback c0 = mock(LauncherApps.Callback.class); + + // Set listeners + + runWithCaller(LAUNCHER_1, USER_0, () -> { + mLauncherApps.registerCallback(c0, new Handler(Looper.getMainLooper())); + }); + + runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> { + assertTrue(mManager.setDynamicShortcuts(Arrays.asList( + makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); + }); + + waitOnMainThread(); + ArgumentCaptor<List> shortcuts = ArgumentCaptor.forClass(List.class); + verify(c0).onShortcutsChanged( + eq(CALLING_PACKAGE_1), + shortcuts.capture(), + eq(UserHandle.of(USER_0)) + ); + assertShortcutIds(assertAllDynamic(shortcuts.getValue()), + "s1", "s2", "s3"); + + // From different package. + reset(c0); + runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> { + assertTrue(mManager.setDynamicShortcuts(Arrays.asList( + makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); + }); + waitOnMainThread(); + shortcuts = ArgumentCaptor.forClass(List.class); + verify(c0).onShortcutsChanged( + eq(CALLING_PACKAGE_2), + shortcuts.capture(), + eq(UserHandle.of(USER_0)) + ); + assertShortcutIds(assertAllDynamic(shortcuts.getValue()), + "s1", "s2", "s3"); + + // Different user, callback shouldn't be called. + reset(c0); + runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { + assertTrue(mManager.setDynamicShortcuts(Arrays.asList( + makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3")))); + }); + waitOnMainThread(); + verify(c0, times(0)).onShortcutsChanged( + anyString(), + any(List.class), + any(UserHandle.class) + ); + + // Test for addDynamicShortcut. + reset(c0); + runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> { + assertTrue(mManager.addDynamicShortcut(makeShortcut("s4"))); + }); + + waitOnMainThread(); + shortcuts = ArgumentCaptor.forClass(List.class); + verify(c0).onShortcutsChanged( + eq(CALLING_PACKAGE_1), + shortcuts.capture(), + eq(UserHandle.of(USER_0)) + ); + assertShortcutIds(assertAllDynamic(shortcuts.getValue()), + "s1", "s2", "s3", "s4"); + + // Test for remove + reset(c0); + runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> { + mManager.deleteDynamicShortcut("s1"); + }); + + waitOnMainThread(); + shortcuts = ArgumentCaptor.forClass(List.class); + verify(c0).onShortcutsChanged( + eq(CALLING_PACKAGE_1), + shortcuts.capture(), + eq(UserHandle.of(USER_0)) + ); + assertShortcutIds(assertAllDynamic(shortcuts.getValue()), + "s2", "s3", "s4"); + + // Test for update + reset(c0); + runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> { + assertTrue(mManager.updateShortcuts(Arrays.asList( + makeShortcut("s1"), makeShortcut("s2")))); + }); + + waitOnMainThread(); + shortcuts = ArgumentCaptor.forClass(List.class); + verify(c0).onShortcutsChanged( + eq(CALLING_PACKAGE_1), + shortcuts.capture(), + eq(UserHandle.of(USER_0)) + ); + assertShortcutIds(assertAllDynamic(shortcuts.getValue()), + "s2", "s3", "s4"); + + // Test for deleteAll + reset(c0); + runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> { + mManager.deleteAllDynamicShortcuts(); + }); + + waitOnMainThread(); + shortcuts = ArgumentCaptor.forClass(List.class); + verify(c0).onShortcutsChanged( + eq(CALLING_PACKAGE_1), + shortcuts.capture(), + eq(UserHandle.of(USER_0)) + ); + assertEquals(0, shortcuts.getValue().size()); + } + // === Test for persisting === public void testSaveAndLoadUser_empty() { @@ -1808,9 +2281,9 @@ public class ShortcutManagerTest extends AndroidTestCase { public void testSaveAndLoadUser() { // First, create some shortcuts and save. runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> { - final Icon icon1 = Icon.createWithResource(mContext, R.drawable.black_64x16); + final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x16); final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource( - mContext.getResources(), R.drawable.icon2)); + getTestContext().getResources(), R.drawable.icon2)); final ShortcutInfo si1 = makeShortcut( "s1", @@ -1835,9 +2308,9 @@ public class ShortcutManagerTest extends AndroidTestCase { assertEquals(2, mManager.getRemainingCallCount()); }); runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> { - final Icon icon1 = Icon.createWithResource(mContext, R.drawable.black_16x64); + final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_16x64); final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource( - mContext.getResources(), R.drawable.icon2)); + getTestContext().getResources(), R.drawable.icon2)); final ShortcutInfo si1 = makeShortcut( "s1", @@ -1862,9 +2335,9 @@ public class ShortcutManagerTest extends AndroidTestCase { assertEquals(2, mManager.getRemainingCallCount()); }); runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { - final Icon icon1 = Icon.createWithResource(mContext, R.drawable.black_64x64); + final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64); final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource( - mContext.getResources(), R.drawable.icon2)); + getTestContext().getResources(), R.drawable.icon2)); final ShortcutInfo si1 = makeShortcut( "s1", @@ -1889,6 +2362,9 @@ public class ShortcutManagerTest extends AndroidTestCase { assertEquals(2, mManager.getRemainingCallCount()); }); + mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM).setLauncherComponent( + mService, new ComponentName("pkg1", "class")); + // Restore. initService(); @@ -1918,6 +2394,9 @@ public class ShortcutManagerTest extends AndroidTestCase { assertEquals("title2-2", getCallerShortcut("s2").getTitle()); }); + assertEquals("pkg1", mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM) + .getLauncherComponent().getPackageName()); + // Start another user mService.onStartUserLocked(USER_10); @@ -1932,6 +2411,7 @@ public class ShortcutManagerTest extends AndroidTestCase { assertEquals("title10-1-1", getCallerShortcut("s1").getTitle()); assertEquals("title10-1-2", getCallerShortcut("s2").getTitle()); }); + assertNull(mService.getShortcutsForTest().get(USER_10).getLauncherComponent()); // Try stopping the user mService.onCleanupUserInner(USER_10); @@ -1941,4 +2421,8 @@ public class ShortcutManagerTest extends AndroidTestCase { // TODO Check all other fields } + + // TODO Detailed test for hasShortcutPermissionInner(). + + // TODO Add tests for the command line functions too. } diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java index 3e2b43d2af5c..a3313c9741cd 100644 --- a/services/usage/java/com/android/server/usage/AppIdleHistory.java +++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java @@ -274,6 +274,11 @@ public class AppIdleHistory { - (idle ? mScreenOnTimeThreshold : 0) - 1000 /* just a second more */; } + public void clearUsageLocked(String packageName, int userId) { + ArrayMap<String, PackageHistory> userHistory = getUserHistoryLocked(userId); + userHistory.remove(packageName); + } + private boolean hasPassedThresholdsLocked(PackageHistory packageHistory, long elapsedRealtime) { return (packageHistory.lastUsedScreenTime <= getScreenOnTimeLocked(elapsedRealtime) - mScreenOnTimeThreshold) diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 8da17852b437..beec40f8b0fa 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -180,6 +180,7 @@ public class UsageStatsService extends SystemService implements IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED); + packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); packageFilter.addDataScheme("package"); getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, packageFilter, @@ -266,6 +267,12 @@ public class UsageStatsService extends SystemService implements || Intent.ACTION_PACKAGE_CHANGED.equals(action)) { clearCarrierPrivilegedApps(); } + if ((Intent.ACTION_PACKAGE_REMOVED.equals(action) || + Intent.ACTION_PACKAGE_ADDED.equals(action)) + && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { + clearAppIdleForPackage(intent.getData().getSchemeSpecificPart(), + getSendingUserId()); + } } } @@ -332,6 +339,12 @@ public class UsageStatsService extends SystemService implements } } + void clearAppIdleForPackage(String packageName, int userId) { + synchronized (mLock) { + mAppIdleHistory.clearUsageLocked(packageName, userId); + } + } + private void cleanUpRemovedUsersLocked() { final List<UserInfo> users = mUserManager.getUsers(true); if (users == null || users.size() == 0) { diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index 10808da8785e..afb7d9394679 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -95,6 +95,19 @@ public final class Call { public static final int STATE_DISCONNECTING = 10; /** + * The state of an external call which is in the process of being pulled from a remote device to + * the local device. + * <p> + * A call can only be in this state if the {@link Details#PROPERTY_IS_EXTERNAL_CALL} property + * and {@link Details#CAPABILITY_CAN_PULL_CALL} capability are set on the call. + * <p> + * An {@link InCallService} will only see this state if it has the + * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its + * manifest. + */ + public static final int STATE_PULLING_CALL = 11; + + /** * The key to retrieve the optional {@code PhoneAccount}s Telecom can bundle with its Call * extras. Used to pass the phone accounts to display on the front end to the user in order to * select phone accounts to (for example) place a call. @@ -226,8 +239,23 @@ public final class Call { */ public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00400000; + /** + * When set for an external call, indicates that this {@code Call} can be pulled from a + * remote device to the current device. + * <p> + * Should only be set on a {@code Call} where {@link #PROPERTY_IS_EXTERNAL_CALL} is set. + * <p> + * An {@link InCallService} will only see calls with this capability if it has the + * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} + * in its manifest. + * <p> + * See {@link Connection#CAPABILITY_CAN_PULL_CALL} and + * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}. + */ + public static final int CAPABILITY_CAN_PULL_CALL = 0x00800000; + //****************************************************************************************** - // Next CAPABILITY value: 0x00800000 + // Next CAPABILITY value: 0x01000000 //****************************************************************************************** /** @@ -261,8 +289,25 @@ public final class Call { */ public static final int PROPERTY_WORK_CALL = 0x00000020; + /** + * When set, indicates that this {@code Call} does not actually exist locally for the + * {@link ConnectionService}. + * <p> + * Consider, for example, a scenario where a user has two phones with the same phone number. + * When a user places a call on one device, the telephony stack can represent that call on + * the other device by adding it to the {@link ConnectionService} with the + * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL} capability set. + * <p> + * An {@link InCallService} will only see calls with this property if it has the + * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} + * in its manifest. + * <p> + * See {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}. + */ + public static final int PROPERTY_IS_EXTERNAL_CALL = 0x00000040; + //****************************************************************************************** - // Next PROPERTY value: 0x00000040 + // Next PROPERTY value: 0x00000100 //****************************************************************************************** private final String mTelecomCallId; @@ -362,6 +407,9 @@ public final class Call { if (can(capabilities, CAPABILITY_CAN_PAUSE_VIDEO)) { builder.append(" CAPABILITY_CAN_PAUSE_VIDEO"); } + if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) { + builder.append(" CAPABILITY_CAN_PULL_CALL"); + } builder.append("]"); return builder.toString(); } @@ -411,6 +459,9 @@ public final class Call { if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) { builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE"); } + if (hasProperty(properties, PROPERTY_IS_EXTERNAL_CALL)) { + builder.append(" PROPERTY_IS_EXTERNAL_CALL"); + } builder.append("]"); return builder.toString(); } @@ -723,6 +774,17 @@ public final class Call { * conferenced. */ public void onConferenceableCallsChanged(Call call, List<Call> conferenceableCalls) {} + + /** + * Invoked when a call receives an event from its associated {@link Connection}. + * <p> + * See {@link Connection#sendConnectionEvent(String, Bundle)}. + * + * @param call The {@code Call} receiving the event. + * @param event The event. + * @param extras Extras associated with the connection event. + */ + public void onConnectionEvent(Call call, String event, Bundle extras) {} } /** @@ -889,6 +951,43 @@ public final class Call { } /** + * Initiates a request to the {@link ConnectionService} to pull an external call to the local + * device. + * <p> + * Calls to this method are ignored if the call does not have the + * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property set. + * <p> + * An {@link InCallService} will only see calls which support this method if it has the + * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} + * in its manifest. + */ + public void pullExternalCall() { + // If this isn't an external call, ignore the request. + if (!mDetails.hasProperty(Details.PROPERTY_IS_EXTERNAL_CALL)) { + return; + } + + mInCallAdapter.pullExternalCall(mTelecomCallId); + } + + /** + * Sends a {@code Call} event from this {@code Call} to the associated {@link Connection} in + * the {@link ConnectionService}. + * <p> + * Events are exposed to {@link ConnectionService} implementations via + * {@link android.telecom.Connection#onCallEvent(String, Bundle)}. + * <p> + * No assumptions should be made as to how a {@link ConnectionService} will handle these events. + * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts. + * + * @param event The connection event. + * @param extras Bundle containing extra information associated with the event. + */ + public void sendCallEvent(String event, Bundle extras) { + mInCallAdapter.sendCallEvent(mTelecomCallId, event, extras); + } + + /** * Obtains the parent of this {@code Call} in a conference, if any. * * @return The parent {@code Call}, or {@code null} if this {@code Call} is not a @@ -1211,6 +1310,11 @@ public final class Call { } } + /** {@hide} */ + final void internalOnConnectionEvent(String event, Bundle extras) { + fireOnConnectionEvent(event, extras); + } + private void fireStateChanged(final int newState) { for (CallbackRecord<Callback> record : mCallbackRecords) { final Call call = this; @@ -1358,6 +1462,27 @@ public final class Call { } /** + * Notifies listeners of an incoming connection event. + * <p> + * Connection events are issued via {@link Connection#sendConnectionEvent(String, Bundle)}. + * + * @param event + * @param extras + */ + private void fireOnConnectionEvent(final String event, final Bundle extras) { + for (CallbackRecord<Callback> record : mCallbackRecords) { + final Call call = this; + final Callback callback = record.getCallback(); + record.getHandler().post(new Runnable() { + @Override + public void run() { + callback.onConnectionEvent(call, event, extras); + } + }); + } + } + + /** * Determines if two bundles are equal. * * @param bundle The original bundle. diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 4547c6a6c153..51a65882b802 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -93,6 +93,15 @@ public abstract class Connection extends Conferenceable { public static final int STATE_DISCONNECTED = 6; /** + * The state of an external connection which is in the process of being pulled from a remote + * device to the local device. + * <p> + * A connection can only be in this state if the {@link #CAPABILITY_IS_EXTERNAL_CALL} and + * {@link #CAPABILITY_CAN_PULL_CALL} capability bits are set on the connection. + */ + public static final int STATE_PULLING_CALL = 7; + + /** * Connection can currently be put on hold or unheld. This is distinct from * {@link #CAPABILITY_SUPPORT_HOLD} in that although a connection may support 'hold' most times, * it does not at the moment support the function. This can be true while the call is in the @@ -251,7 +260,6 @@ public abstract class Connection extends Conferenceable { /** * Indicates that the connection itself wants to handle any sort of reply response, rather than * relying on SMS. - * @hide */ public static final int CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION = 0x00400000; @@ -270,8 +278,33 @@ public abstract class Connection extends Conferenceable { */ public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 0x00800000; + /** + * When set, indicates that the {@code Connection} does not actually exist locally for the + * {@link ConnectionService}. + * <p> + * Consider, for example, a scenario where a user has two devices with the same phone number. + * When a user places a call on one devices, the telephony stack can represent that call on the + * other device by adding is to the {@link ConnectionService} with the + * {@code CAPABILITY_IS_EXTERNAL_CALL} capability set. + * <p> + * An {@link ConnectionService} should not assume that all {@link InCallService}s will handle + * external connections. Only those {@link InCallService}s which have the + * {@link TelecomManager#METADATA_INCLUDE_EXTERNAL_CALLS} metadata set to {@code true} in its + * manifest will see external connections. + */ + public static final int CAPABILITY_IS_EXTERNAL_CALL = 0x01000000; + + /** + * When set for an external connection, indicates that this {@code Connection} can be pulled + * from a remote device to the current device. + * <p> + * Should only be set on a {@code Connection} where {@link #CAPABILITY_IS_EXTERNAL_CALL} + * is set. + */ + public static final int CAPABILITY_CAN_PULL_CALL = 0x02000000; + //********************************************************************************************** - // Next CAPABILITY value: 0x01000000 + // Next CAPABILITY value: 0x04000000 //********************************************************************************************** /** @@ -315,6 +348,18 @@ public abstract class Connection extends Conferenceable { public static final String EVENT_ON_HOLD_TONE_END = "android.telecom.event.ON_HOLD_TONE_END"; + /** + * Connection event used to inform {@link InCallService}s when pulling of an external call has + * failed. The user interface should inform the user of the error. + * <p> + * Expected to be used by the {@link ConnectionService} when the {@link Call#pullExternalCall()} + * API is called on a {@link Call} with the properties + * {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} and + * {@link Call.Details#CAPABILITY_CAN_PULL_CALL}, but the {@link ConnectionService} could not + * pull the external call due to an error condition. + */ + public static final String EVENT_CALL_PULL_FAILED = "android.telecom.event.CALL_PULL_FAILED"; + // Flag controlling whether PII is emitted into the logs private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); @@ -434,6 +479,12 @@ public abstract class Connection extends Conferenceable { if (can(capabilities, CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION)) { builder.append(" CAPABILITY_CAN_SEND_RESPONSE_VIA_CONNECTION"); } + if (can(capabilities, CAPABILITY_IS_EXTERNAL_CALL)) { + builder.append(" CAPABILITY_IS_EXTERNAL_CALL"); + } + if (can(capabilities, CAPABILITY_CAN_PULL_CALL)) { + builder.append(" CAPABILITY_CAN_PULL_CALL"); + } builder.append("]"); return builder.toString(); @@ -465,8 +516,7 @@ public abstract class Connection extends Conferenceable { public void onConferenceStarted() {} public void onConferenceMergeFailed(Connection c) {} public void onExtrasChanged(Connection c, Bundle extras) {} - /** @hide */ - public void onConnectionEvent(Connection c, String event) {} + public void onConnectionEvent(Connection c, String event, Bundle extras) {} } /** @@ -1836,9 +1886,8 @@ public abstract class Connection extends Conferenceable { public void onReject() {} /** - * Notifies ths Connection of a request reject with a message. - * - * @hide + * Notifies this Connection, which is in {@link #STATE_RINGING}, of + * a request to reject with a message. */ public void onReject(String replyMessage) {} @@ -1854,6 +1903,31 @@ public abstract class Connection extends Conferenceable { */ public void onPostDialContinue(boolean proceed) {} + /** + * Notifies this Connection of a request to pull an external call to the local device. + * <p> + * The {@link InCallService} issues a request to pull an external call to the local device via + * {@link Call#pullExternalCall()}. + * <p> + * For a Connection to be pulled, both the {@link Connection#CAPABILITY_CAN_PULL_CALL} and + * {@link Connection#CAPABILITY_IS_EXTERNAL_CALL} capability bits must be set. + * <p> + * For more information on external calls, see {@link Connection#CAPABILITY_IS_EXTERNAL_CALL}. + */ + public void onPullExternalCall() {} + + /** + * Notifies this Connection of a {@link Call} event initiated from an {@link InCallService}. + * <p> + * The {@link InCallService} issues a Call event via {@link Call#sendCallEvent(String, Bundle)}. + * <p> + * See also {@link Call#sendCallEvent(String, Bundle)}. + * + * @param event The call event. + * @param extras Extras associated with the call event. + */ + public void onCallEvent(String event, Bundle extras) {} + static String toLogSafePhoneNumber(String number) { // For unknown number, log empty string. if (number == null) { @@ -2008,14 +2082,20 @@ public abstract class Connection extends Conferenceable { } /** - * Sends a connection event to Telecom. + * Sends an event associated with this {@code Connection}, with associated event extras. + * + * Events are exposed to {@link InCallService} implementations via the + * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)} API. + * + * No assumptions should be made as to how an In-Call UI or service will handle these events. + * Events should be fully qualified (e.g., com.example.event.MY_EVENT) to avoid conflicts. * * @param event The connection event. - * @hide + * @param extras Bundle containing extra information associated with the event. */ - protected void sendConnectionEvent(String event) { + public void sendConnectionEvent(String event, Bundle extras) { for (Listener l : mListeners) { - l.onConnectionEvent(this, event); + l.onConnectionEvent(this, event, null); } } } diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 5b62e03350b1..d18b31725aaa 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -103,6 +103,8 @@ public abstract class ConnectionService extends Service { private static final int MSG_SWAP_CONFERENCE = 19; private static final int MSG_REJECT_WITH_MESSAGE = 20; private static final int MSG_SILENCE = 21; + private static final int MSG_PULL_EXTERNAL_CALL = 22; + private static final int MSG_SEND_CALL_EVENT = 23; private static Connection sNullConnection; @@ -245,6 +247,20 @@ public abstract class ConnectionService extends Service { args.argi1 = proceed ? 1 : 0; mHandler.obtainMessage(MSG_ON_POST_DIAL_CONTINUE, args).sendToTarget(); } + + @Override + public void pullExternalCall(String callId) { + mHandler.obtainMessage(MSG_PULL_EXTERNAL_CALL, callId).sendToTarget(); + } + + @Override + public void sendCallEvent(String callId, String event, Bundle extras) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + args.arg2 = event; + args.arg3 = extras; + mHandler.obtainMessage(MSG_SEND_CALL_EVENT, args).sendToTarget(); + } }; private final Handler mHandler = new Handler(Looper.getMainLooper()) { @@ -382,6 +398,22 @@ public abstract class ConnectionService extends Service { } break; } + case MSG_PULL_EXTERNAL_CALL: { + pullExternalCall((String) msg.obj); + break; + } + case MSG_SEND_CALL_EVENT: { + SomeArgs args = (SomeArgs) msg.obj; + try { + String callId = (String) args.arg1; + String event = (String) args.arg2; + Bundle extras = (Bundle) args.arg3; + sendCallEvent(callId, event, extras); + } finally { + args.recycle(); + } + break; + } default: break; } @@ -615,10 +647,10 @@ public abstract class ConnectionService extends Service { } @Override - public void onConnectionEvent(Connection connection, String event) { + public void onConnectionEvent(Connection connection, String event, Bundle extras) { String id = mIdByConnection.get(connection); if (id != null) { - mAdapter.onConnectionEvent(id, event); + mAdapter.onConnectionEvent(id, event, extras); } } }; @@ -864,6 +896,39 @@ public abstract class ConnectionService extends Service { } } + /** + * Notifies a {@link Connection} of a request to pull an external call. + * + * See {@link Call#pullExternalCall()}. + * + * @param callId The ID of the call to pull. + */ + private void pullExternalCall(String callId) { + Log.d(this, "pullExternalCall(%s)", callId); + Connection connection = findConnectionForAction(callId, "pullExternalCall"); + if (connection != null) { + connection.onPullExternalCall(); + } + } + + /** + * Notifies a {@link Connection} of a call event. + * + * See {@link Call#sendCallEvent(String, Bundle)}. + * + * @param callId The ID of the call receiving the event. + * @param event The event. + * @param extras Extras associated with the event. + */ + private void sendCallEvent(String callId, String event, Bundle extras) { + Log.d(this, "sendCallEvent(%s, %s)", callId, event); + Connection connection = findConnectionForAction(callId, "sendCallEvent"); + if (connection != null) { + connection.onCallEvent(event, extras); + } + + } + private void onPostDialContinue(String callId, boolean proceed) { Log.d(this, "onPostDialContinue(%s)", callId); findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed); diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java index 30fc5ad1e4b6..e91128f1f7bc 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -418,12 +418,13 @@ final class ConnectionServiceAdapter implements DeathRecipient { * * @param callId The unique ID of the call. * @param event The event. + * @param extras Extras associated with the event. */ - void onConnectionEvent(String callId, String event) { + void onConnectionEvent(String callId, String event, Bundle extras) { Log.v(this, "onConnectionEvent: %s", event); for (IConnectionServiceAdapter adapter : mAdapters) { try { - adapter.onConnectionEvent(callId, event); + adapter.onConnectionEvent(callId, event, extras); } catch (RemoteException ignored) { } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java index 6a8c1cb281ba..4b15e541d0dc 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -245,7 +245,8 @@ final class ConnectionServiceAdapterServant { case MSG_ON_CONNECTION_EVENT: { SomeArgs args = (SomeArgs) msg.obj; try { - mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2); + mDelegate.onConnectionEvent((String) args.arg1, (String) args.arg2, + (Bundle) args.arg3); } finally { args.recycle(); } @@ -432,10 +433,11 @@ final class ConnectionServiceAdapterServant { } @Override - public final void onConnectionEvent(String connectionId, String event) { + public final void onConnectionEvent(String connectionId, String event, Bundle extras) { SomeArgs args = SomeArgs.obtain(); args.arg1 = connectionId; args.arg2 = event; + args.arg3 = extras; mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget(); } }; diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java index 2eef7eeb6bd8..cf73d4f1453e 100644 --- a/telecomm/java/android/telecom/DisconnectCause.java +++ b/telecomm/java/android/telecom/DisconnectCause.java @@ -64,6 +64,17 @@ public final class DisconnectCause implements Parcelable { */ public static final int CONNECTION_MANAGER_NOT_SUPPORTED = 10; + /** + * Disconnected because the user did not locally answer the incoming call, but it was answered + * on another device where the call was ringing. + */ + public static final int ANSWERED_ELSEWHERE = 11; + + /** + * Disconnected because the call was pulled from the current device to another device. + */ + public static final int CALL_PULLED = 12; + private int mDisconnectCode; private CharSequence mDisconnectLabel; private CharSequence mDisconnectDescription; diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java index 0cf7212ba55b..52ef4a705e05 100644 --- a/telecomm/java/android/telecom/InCallAdapter.java +++ b/telecomm/java/android/telecom/InCallAdapter.java @@ -16,6 +16,7 @@ package android.telecom; +import android.os.Bundle; import android.os.RemoteException; import com.android.internal.telecom.IInCallAdapter; @@ -251,6 +252,32 @@ public final class InCallAdapter { } /** + * Instructs Telecom to pull an external call to the local device. + * + * @param callId The callId to pull. + */ + public void pullExternalCall(String callId) { + try { + mAdapter.pullExternalCall(callId); + } catch (RemoteException ignored) { + } + } + + /** + * Intructs Telecom to send a call event. + * + * @param callId The callId to send the event for. + * @param event The event. + * @param extras Extras associated with the event. + */ + public void sendCallEvent(String callId, String event, Bundle extras) { + try { + mAdapter.sendCallEvent(callId, event, extras); + } catch (RemoteException ignored) { + } + } + + /** * Instructs Telecom to turn the proximity sensor on. */ public void turnProximitySensorOn() { diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java index 671399b6f842..df6715d41a3f 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -22,6 +22,7 @@ import android.app.Service; import android.content.Intent; import android.hardware.camera2.CameraManager; import android.net.Uri; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -74,6 +75,7 @@ public abstract class InCallService extends Service { private static final int MSG_BRING_TO_FOREGROUND = 6; private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7; private static final int MSG_SILENCE_RINGER = 8; + private static final int MSG_ON_CONNECTION_EVENT = 9; /** Default Handler used to consolidate binder method calls onto a single thread. */ private final Handler mHandler = new Handler(Looper.getMainLooper()) { @@ -118,6 +120,18 @@ public abstract class InCallService extends Service { case MSG_SILENCE_RINGER: mPhone.internalSilenceRinger(); break; + case MSG_ON_CONNECTION_EVENT: { + SomeArgs args = (SomeArgs) msg.obj; + try { + String callId = (String) args.arg1; + String event = (String) args.arg2; + Bundle extras = (Bundle) args.arg3; + mPhone.internalOnConnectionEvent(callId, event, extras); + } finally { + args.recycle(); + } + break; + } default: break; } @@ -174,6 +188,15 @@ public abstract class InCallService extends Service { public void silenceRinger() { mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget(); } + + @Override + public void onConnectionEvent(String callId, String event, Bundle extras) { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + args.arg2 = event; + args.arg3 = extras; + mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget(); + } } private Phone.Listener mPhoneListener = new Phone.Listener() { @@ -426,6 +449,19 @@ public abstract class InCallService extends Service { } /** + * Called when a {@link Call} has received a connection event issued by the + * {@link ConnectionService}. + * <p> + * See {@link Connection#sendConnectionEvent(String, Bundle)}. + * + * @param call The call the event is associated with. + * @param event The event. + * @param extras Any associated extras. + */ + public void onConnectionEvent(Call call, String event, Bundle extras) { + } + + /** * Used to issue commands to the {@link Connection.VideoProvider} associated with a * {@link Call}. */ diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java index d45938cb9b85..a4ef5601e551 100644 --- a/telecomm/java/android/telecom/Phone.java +++ b/telecomm/java/android/telecom/Phone.java @@ -17,6 +17,7 @@ package android.telecom; import android.annotation.SystemApi; +import android.os.Bundle; import android.util.ArrayMap; import java.util.Collections; @@ -190,6 +191,13 @@ public final class Phone { fireSilenceRinger(); } + final void internalOnConnectionEvent(String telecomId, String event, Bundle extras) { + Call call = mCallByTelecomCallId.get(telecomId); + if (call != null) { + call.internalOnConnectionEvent(event, extras); + } + } + /** * Called to destroy the phone and cleanup any lingering calls. */ diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 01858080d7d7..5b602eb49dca 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -212,12 +212,14 @@ public final class RemoteConnection { /** * Handles a connection event propagated to this {@link RemoteConnection}. + * <p> + * Connection events originate from {@link Connection#sendConnectionEvent(String, Bundle)}. * * @param connection The {@code RemoteConnection} invoking this method. * @param event The connection event. - * @hide + * @param extras Extras associated with the event. */ - public void onConnectionEvent(RemoteConnection connection, String event) {} + public void onConnectionEvent(RemoteConnection connection, String event, Bundle extras) {} } /** @@ -962,6 +964,20 @@ public final class RemoteConnection { } /** + * Instructs this {@link RemoteConnection} to pull itself to the local device. + * <p> + * See {@link Call#pullExternalCall()} for more information. + */ + public void pullExternalCall() { + try { + if (mConnected) { + mConnectionService.pullExternalCall(mConnectionId); + } + } catch (RemoteException ignored) { + } + } + + /** * Set the audio state of this {@code RemoteConnection}. * * @param state The audio state of this {@code RemoteConnection}. @@ -1301,14 +1317,14 @@ public final class RemoteConnection { } /** @hide */ - void onConnectionEvent(final String event) { + void onConnectionEvent(final String event, final Bundle extras) { for (CallbackRecord record : mCallbackRecords) { final RemoteConnection connection = this; final Callback callback = record.getCallback(); record.getHandler().post(new Runnable() { @Override public void run() { - callback.onConnectionEvent(connection, event); + callback.onConnectionEvent(connection, event, extras); } }); } diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index b85382feae60..fa7183acc350 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -332,9 +332,10 @@ final class RemoteConnectionService { } @Override - public void onConnectionEvent(String callId, String event) { + public void onConnectionEvent(String callId, String event, Bundle extras) { if (mConnectionById.containsKey(callId)) { - findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event); + findConnectionForAction(callId, "onConnectionEvent").onConnectionEvent(event, + extras); } } }; diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 8afb4556b97d..4fa8fe96a6a9 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -317,6 +317,18 @@ public class TelecomManager { "android.telecom.IN_CALL_SERVICE_RINGING"; /** + * A boolean meta-data value indicating whether an {@link InCallService} wants to be informed of + * calls which have the {@link Call.Details#PROPERTY_IS_EXTERNAL_CALL} property. An external + * call is one which a {@link ConnectionService} knows about, but is not connected to directly. + * Dialer implementations (see {@link #getDefaultDialerPackage()}) which would like to be + * informed of external calls should set this meta-data to {@code true} in the manifest + * registration of their {@link InCallService}. By default, the {@link InCallService} will NOT + * be informed of external calls. + */ + public static final String METADATA_INCLUDE_EXTERNAL_CALLS = + "android.telecom.INCLUDE_EXTERNAL_CALLS"; + + /** * The dual tone multi-frequency signaling character sent to indicate the dialing system should * pause for a predefined period. */ diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl index 8a54addcf06e..3ee0e9f94443 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl @@ -75,4 +75,8 @@ oneway interface IConnectionService { void swapConference(String conferenceCallId); void onPostDialContinue(String callId, boolean proceed); + + void pullExternalCall(String callId); + + void sendCallEvent(String callId, String event, in Bundle extras); } diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl index 569c24469368..dff1b1138741 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -87,5 +87,5 @@ oneway interface IConnectionServiceAdapter { void setExtras(String callId, in Bundle extras); - void onConnectionEvent(String callId, String event); + void onConnectionEvent(String callId, String event, in Bundle extras); } diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl index 863fff29d560..0678fe2c0aa4 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl @@ -16,6 +16,7 @@ package com.android.internal.telecom; +import android.os.Bundle; import android.telecom.PhoneAccountHandle; /** @@ -60,4 +61,8 @@ oneway interface IInCallAdapter { void turnOnProximitySensor(); void turnOffProximitySensor(boolean screenOnImmediately); + + void pullExternalCall(String callId); + + void sendCallEvent(String callId, String event, in Bundle extras); } diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl index 0088e0cf6b64..3e43fe22cdfb 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl @@ -17,6 +17,7 @@ package com.android.internal.telecom; import android.app.PendingIntent; +import android.os.Bundle; import android.telecom.CallAudioState; import android.telecom.ParcelableCall; @@ -47,4 +48,6 @@ oneway interface IInCallService { void onCanAddCallChanged(boolean canAddCall); void silenceRinger(); + + void onConnectionEvent(String callId, String event, in Bundle extras); } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index ea437d02ce2a..86518b57c430 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -444,6 +444,11 @@ public class CarrierConfigManager { public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string"; /** + * Flag specifying whether ICCID is showed in SIM Status screen, default to false. + */ + public static final String KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL = "show_iccid_in_sim_status_bool"; + + /** * Flag specifying whether an additional (client initiated) intent needs to be sent on System * update */ @@ -680,6 +685,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOLEAN,false); sDefaults.putBoolean(KEY_VVM_PREFETCH_BOOLEAN,true); sDefaults.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING, ""); + sDefaults.putBoolean(KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL, false); 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, ""); diff --git a/telephony/java/com/android/ims/ImsExternalCallState.aidl b/telephony/java/com/android/ims/ImsExternalCallState.aidl new file mode 100644 index 000000000000..c208702a8c34 --- /dev/null +++ b/telephony/java/com/android/ims/ImsExternalCallState.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016 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.ims; + +parcelable ImsExternalCallState; diff --git a/telephony/java/com/android/ims/ImsExternalCallState.java b/telephony/java/com/android/ims/ImsExternalCallState.java new file mode 100644 index 000000000000..edb6bfcf68c0 --- /dev/null +++ b/telephony/java/com/android/ims/ImsExternalCallState.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016 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.ims; + +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.Rlog; + +/* + * This file contains all the api's through which + * information received in Dialog Event Package can be + * queried + */ + +/** + * Parcelable object to handle VICE Dialog Information + * @hide + */ +public class ImsExternalCallState implements Parcelable { + + private static final String TAG = "ImsExternalCallState"; + + // Dialog States + public static final int CALL_STATE_CONFIRMED = 1; + public static final int CALL_STATE_TERMINATED = 2; + // Dialog Id + public int mCallId; + // Number + public Uri mAddress; + public boolean mIsPullable; + // CALL_STATE_CONFIRMED / CALL_STATE_TERMINATED + public int mCallState; + // ImsCallProfile#CALL_TYPE_* + public int mCallType; + public boolean mIsHeld; + + public ImsExternalCallState() { + } + + public ImsExternalCallState(Parcel in) { + mCallId = in.readInt(); + ClassLoader classLoader = ImsExternalCallState.class.getClassLoader(); + mAddress = in.readParcelable(classLoader); + mIsPullable = (in.readInt() != 0); + mCallState = in.readInt(); + mCallType = in.readInt(); + mIsHeld = (in.readInt() != 0); + Rlog.d(TAG, "ImsExternalCallState const = " + + "callid = " + getCallId() + + ", address = " + getAddress() + + ", mCallState = " + getCallState() + + ", calltype = " + getCallType() + + ", isheld = " + isCallHeld()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mCallId); + out.writeParcelable(mAddress, 0); + out.writeInt(mIsPullable ? 1 : 0); + out.writeInt(mCallState); + out.writeInt(mCallType); + out.writeInt(mIsHeld ? 1 : 0); + } + + public static final Parcelable.Creator<ImsExternalCallState> CREATOR = + new Parcelable.Creator<ImsExternalCallState>() { + @Override + public ImsExternalCallState createFromParcel(Parcel in) { + return new ImsExternalCallState(in); + } + + @Override + public ImsExternalCallState[] newArray(int size) { + return new ImsExternalCallState[size]; + } + }; + + public int getCallId() { + return mCallId; + } + + public Uri getAddress() { + return mAddress; + } + + public boolean isCallPullable() { + return mIsPullable; + } + + public int getCallState() { + return mCallState; + } + + public int getCallType() { + return mCallType; + } + + public boolean isCallHeld() { + return mIsHeld; + } + + @Override + public String toString() { + return "ImsExternalCallState { mCallId = " + mCallId + + ", mAddress = " + mAddress + + ", mIsPullable = " + mIsPullable + + ", mCallState = " + mCallState + + ", mCallType = " + mCallType + + ", mIsHeld = " + mIsHeld + "}"; + } +} diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java index 558c1dc1866c..f06d15456ac0 100644 --- a/telephony/java/com/android/ims/ImsReasonInfo.java +++ b/telephony/java/com/android/ims/ImsReasonInfo.java @@ -241,12 +241,12 @@ public class ImsReasonInfo implements Parcelable { public static final int CODE_ANSWERED_ELSEWHERE = 1014; /** - * Call pull request failure from the network. + * For MultiEndpoint - Call Pull request has failed */ public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015; /** - * Call ended due to being pulled onto another device. + * For MultiEndpoint - Call has been pulled from primary to secondary */ public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016; diff --git a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl new file mode 100644 index 000000000000..70a474ec41da --- /dev/null +++ b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 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.ims.internal; + +import com.android.ims.ImsExternalCallState; + +/** + * A listener type for receiving notifications about DEP through IMS + * + * {@hide} + */ +interface IImsExternalCallStateListener { + + /** + * Notifies client when Dialog Event Package update is received + * + * @param List<ImsExternalCallState> - External Call Dialog + * + * @return void. + */ + void notifyRefreshExternalCallState(in List<ImsExternalCallState> externalCallDialogs); + +} + diff --git a/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl b/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl new file mode 100644 index 000000000000..1bfb9b2b4d78 --- /dev/null +++ b/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016 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.ims.internal; + +import com.android.ims.internal.IImsExternalCallStateListener; + +/** + * Provides the ImsMultiEndpoint interface + * + * {@hide} + */ +interface IImsMultiEndpoint { + /** + * Sets the listener. + */ + void setListener(in IImsExternalCallStateListener listener); + + + /** + * Query api to get the latest Dialog Event Package information + * Should be invoked only after setListener is done + */ + void requestDialogEventPackageState(); +} diff --git a/telephony/java/com/android/ims/internal/IImsService.aidl b/telephony/java/com/android/ims/internal/IImsService.aidl index 30c48d7a839a..a9614a63d872 100644 --- a/telephony/java/com/android/ims/internal/IImsService.aidl +++ b/telephony/java/com/android/ims/internal/IImsService.aidl @@ -19,12 +19,13 @@ package com.android.ims.internal; import android.app.PendingIntent; import com.android.ims.ImsCallProfile; -import com.android.ims.internal.IImsRegistrationListener; import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsCallSessionListener; +import com.android.ims.internal.IImsConfig; import com.android.ims.internal.IImsEcbm; +import com.android.ims.internal.IImsMultiEndpoint; +import com.android.ims.internal.IImsRegistrationListener; import com.android.ims.internal.IImsUt; -import com.android.ims.internal.IImsConfig; import android.os.Message; @@ -75,4 +76,9 @@ interface IImsService { * Used to set current TTY Mode. */ void setUiTTYMode(int serviceId, int uiTtyMode, in Message onComplete); + + /** + * MultiEndpoint interface for DEP. + */ + IImsMultiEndpoint getMultiEndpointInterface(int serviceId); } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 7f90731d2f72..4f0e036e04ca 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -97,6 +97,12 @@ public interface RILConstants { int NETWORK_REJECT = 53; /* Request is rejected by network */ int OPERATION_NOT_ALLOWED = 54; /* Not allowed the request now */ int EMPTY_RECORD = 55; /* The request record is empty */ + int INVALID_SMS_FORMAT = 56; /* Invalid sms format */ + int ENCODING_ERR = 57; /* Message not encoded properly */ + int INVALID_SMSC_ADDRESS = 58; /* SMSC address specified is invalid */ + int NO_SUCH_ENTRY = 59; /* No such entry present to perform the request */ + int NETWORK_NOT_READY = 60; /* Network is not ready to perform the request */ + int NOT_PROVISIONED = 61; /* Device doesnot have this value provisioned */ // Below is list of OEM specific error codes which can by used by OEMs in case they don't want to // reveal particular replacement for Generic failure int OEM_ERROR_1 = 501; diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java index 645c3a17db14..ea3b5c97c4c9 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java +++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java @@ -217,4 +217,12 @@ public interface TelephonyProperties * or Earpiece, based on the default audio routing strategy. */ static final String PROPERTY_VIDEOCALL_AUDIO_OUTPUT = "persist.radio.call.audio.output"; + + /** + * For MultiEndpoint Feature + * If true: Dial intent is for call pull functionality + * if false: normal dial + */ + static final String EXTRA_IS_CALL_PULL = + "android.telephony.extra.IS_CALL_PULL"; } diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index e851c8d784f3..91e891f10f2f 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -758,6 +758,12 @@ public class MockPackageManager extends PackageManager { throw new UnsupportedOperationException(); } + /** @hide */ + @Override + public void flushPackageRestrictionsAsUser(int userId) { + throw new UnsupportedOperationException(); + } + @Override public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set, ComponentName activity) { diff --git a/tests/SoundTriggerTests/Android.mk b/tests/SoundTriggerTests/Android.mk index ac562b911cbe..e67134dd2806 100644 --- a/tests/SoundTriggerTests/Android.mk +++ b/tests/SoundTriggerTests/Android.mk @@ -27,6 +27,7 @@ else LOCAL_SRC_FILES := src/android/hardware/soundtrigger/SoundTriggerTest.java endif +LOCAL_STATIC_JAVA_LIBRARIES := mockito-target LOCAL_JAVA_LIBRARIES := android.test.runner LOCAL_PACKAGE_NAME := SoundTriggerTests diff --git a/tests/SoundTriggerTests/AndroidManifest.xml b/tests/SoundTriggerTests/AndroidManifest.xml index e8b9dd32d62f..f7454c752b7d 100644 --- a/tests/SoundTriggerTests/AndroidManifest.xml +++ b/tests/SoundTriggerTests/AndroidManifest.xml @@ -17,7 +17,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.hardware.soundtrigger"> <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" /> - + <uses-permission android:name="android.permission.INTERNET" /> + <application> <uses-library android:name="android.test.runner" /> </application> diff --git a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java index 7acb472339e0..ad02d2b77a99 100644 --- a/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java +++ b/tests/SoundTriggerTests/src/android/hardware/soundtrigger/stubhal/GenericSoundModelTest.java @@ -16,70 +16,180 @@ package android.hardware.soundtrigger; -import java.util.Random; -import java.util.UUID; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; import android.content.Context; +import android.hardware.soundtrigger.SoundTrigger.GenericRecognitionEvent; import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel; +import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent; +import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig; import android.media.soundtrigger.SoundTriggerManager; import android.os.ParcelUuid; import android.os.ServiceManager; import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.SmallTest; import com.android.internal.app.ISoundTriggerService; -import java.util.Arrays; +import java.io.DataOutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.util.ArrayList; import java.util.Random; import java.util.UUID; +import org.mockito.MockitoAnnotations; + public class GenericSoundModelTest extends AndroidTestCase { - private Random mRandom = new Random(); + static final int MSG_DETECTION_ERROR = -1; + static final int MSG_DETECTION_RESUME = 0; + static final int MSG_DETECTION_PAUSE = 1; + static final int MSG_KEYPHRASE_TRIGGER = 2; + static final int MSG_GENERIC_TRIGGER = 4; + + private Random random = new Random(); + private ArrayList<UUID> loadedModelUuids; + private ISoundTriggerService soundTriggerService; + private SoundTriggerManager soundTriggerManager; + + @Override + public void setUp() throws Exception { + super.setUp(); + MockitoAnnotations.initMocks(this); - @SmallTest - public void testUpdateGenericSoundModel() throws Exception { Context context = getContext(); - ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface( - ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE)); - SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService( - Context.SOUND_TRIGGER_SERVICE); + soundTriggerService = ISoundTriggerService.Stub.asInterface( + ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE)); + soundTriggerManager = (SoundTriggerManager) context.getSystemService( + Context.SOUND_TRIGGER_SERVICE); + + loadedModelUuids = new ArrayList<UUID>(); + } + + @Override + public void tearDown() throws Exception { + for (UUID modelUuid : loadedModelUuids) { + soundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid)); + } + super.tearDown(); + } + GenericSoundModel new_sound_model() { + // Create sound model byte[] data = new byte[1024]; - mRandom.nextBytes(data); + random.nextBytes(data); UUID modelUuid = UUID.randomUUID(); UUID mVendorUuid = UUID.randomUUID(); - GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data); + return new GenericSoundModel(modelUuid, mVendorUuid, data); + } - mSoundTriggerService.updateSoundModel(model); - GenericSoundModel returnedModel = - mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid)); + @SmallTest + public void testUpdateGenericSoundModel() throws Exception { + GenericSoundModel model = new_sound_model(); - assertEquals(model, returnedModel); + // Update sound model + soundTriggerService.updateSoundModel(model); + loadedModelUuids.add(model.uuid); - // Cleanup sound model - mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid)); + // Confirm it was updated + GenericSoundModel returnedModel = + soundTriggerService.getSoundModel(new ParcelUuid(model.uuid)); + assertEquals(model, returnedModel); } - @SmallTest public void testDeleteGenericSoundModel() throws Exception { - Context context = getContext(); - ISoundTriggerService mSoundTriggerService = ISoundTriggerService.Stub.asInterface( - ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE)); - SoundTriggerManager mSoundTriggerManager = (SoundTriggerManager) context.getSystemService( - Context.SOUND_TRIGGER_SERVICE); + GenericSoundModel model = new_sound_model(); - byte[] data = new byte[1024]; - mRandom.nextBytes(data); - UUID modelUuid = UUID.randomUUID(); - UUID mVendorUuid = UUID.randomUUID(); - GenericSoundModel model = new GenericSoundModel(modelUuid, mVendorUuid, data); + // Update sound model + soundTriggerService.updateSoundModel(model); + loadedModelUuids.add(model.uuid); - mSoundTriggerService.updateSoundModel(model); - mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid)); + // Delete sound model + soundTriggerService.deleteSoundModel(new ParcelUuid(model.uuid)); + loadedModelUuids.remove(model.uuid); + // Confirm it was deleted GenericSoundModel returnedModel = - mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid)); + soundTriggerService.getSoundModel(new ParcelUuid(model.uuid)); assertEquals(null, returnedModel); } + + @LargeTest + public void testStartStopGenericSoundModel() throws Exception { + GenericSoundModel model = new_sound_model(); + + boolean captureTriggerAudio = true; + boolean allowMultipleTriggers = true; + RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers, + null, null); + TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback()); + + // Update and start sound model recognition + soundTriggerService.updateSoundModel(model); + loadedModelUuids.add(model.uuid); + int r = soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback, + config); + assertEquals("Could Not Start Recognition with code: " + r, + android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r); + + // Stop recognition + r = soundTriggerService.stopRecognition(new ParcelUuid(model.uuid), spyCallback); + assertEquals("Could Not Stop Recognition with code: " + r, + android.hardware.soundtrigger.SoundTrigger.STATUS_OK, r); + } + + @LargeTest + public void testTriggerGenericSoundModel() throws Exception { + GenericSoundModel model = new_sound_model(); + + boolean captureTriggerAudio = true; + boolean allowMultipleTriggers = true; + RecognitionConfig config = new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers, + null, null); + TestRecognitionStatusCallback spyCallback = spy(new TestRecognitionStatusCallback()); + + // Update and start sound model + soundTriggerService.updateSoundModel(model); + loadedModelUuids.add(model.uuid); + soundTriggerService.startRecognition(new ParcelUuid(model.uuid), spyCallback, config); + + // Send trigger to stub HAL + Socket socket = new Socket(InetAddress.getLocalHost(), 14035); + DataOutputStream out = new DataOutputStream(socket.getOutputStream()); + out.writeBytes("trig " + model.uuid.toString() + "\r\n"); + out.flush(); + socket.close(); + + // Verify trigger was received + verify(spyCallback, timeout(100)).onGenericSoundTriggerDetected(any()); + } + + + public class TestRecognitionStatusCallback extends IRecognitionStatusCallback.Stub { + @Override + public void onGenericSoundTriggerDetected(GenericRecognitionEvent recognitionEvent) { + } + + @Override + public void onKeyphraseDetected(KeyphraseRecognitionEvent recognitionEvent) { + } + + @Override + public void onError(int status) { + } + + @Override + public void onRecognitionPaused() { + } + + @Override + public void onRecognitionResumed() { + } + } } diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml new file mode 100644 index 000000000000..d5d86d80269b --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_evenodd.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<vector android:height="24dp" android:viewportHeight="400.0" + android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillType="evenOdd" + android:fillColor="#f00" + android:pathData="M250,75L323,301 131,161 369,161 177,301z" + android:strokeColor="#000" android:strokeWidth="3"/> + <path android:fillType="evenOdd" + android:fillColor="#f00" + android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z" + android:strokeColor="#000" android:strokeWidth="3"/> + <path android:fillType="evenOdd" + android:fillColor="#f00" + android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z" + android:strokeColor="#000" android:strokeWidth="3"/> +</vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml new file mode 100644 index 000000000000..9754e4bed48b --- /dev/null +++ b/tests/VectorDrawableTest/res/drawable/vector_icon_filltype_nonzero.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2016 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. + */ +--> +<vector android:height="24dp" android:viewportHeight="400.0" + android:viewportWidth="1200.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillType="nonZero" + android:fillColor="#f00" + android:pathData="M250,75L323,301 131,161 369,161 177,301z" + android:strokeColor="#000" android:strokeWidth="3"/> + <path android:fillType="nonZero" + android:fillColor="#f00" + android:pathData="M600,81A107,107 0,0 1,600 295A107,107 0,0 1,600 81zM600,139A49,49 0,0 1,600 237A49,49 0,0 1,600 139z" + android:strokeColor="#000" android:strokeWidth="3"/> + <path android:fillType="nonZero" + android:fillColor="#f00" + android:pathData="M950,81A107,107 0,0 1,950 295A107,107 0,0 1,950 81zM950,139A49,49 0,0 0,950 237A49,49 0,0 0,950 139z" + android:strokeColor="#000" android:strokeWidth="3"/> +</vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java index 495d62010fb8..5856f49da343 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java @@ -35,6 +35,8 @@ import java.text.DecimalFormat; public class VectorDrawablePerformance extends Activity { private static final String LOGCAT = "VectorDrawable1"; protected int[] icon = { + R.drawable.vector_icon_filltype_nonzero, + R.drawable.vector_icon_filltype_evenodd, R.drawable.vector_icon_gradient_1, R.drawable.vector_icon_gradient_2, R.drawable.vector_icon_gradient_3, diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py index fb2213cdad57..fb172d4fca78 100755 --- a/tools/fonts/fontchain_lint.py +++ b/tools/fonts/fontchain_lint.py @@ -67,6 +67,20 @@ def assert_font_supports_any_of_chars(font, chars): sys.exit('None of characters in %s were found in %s' % (chars, font)) +def assert_font_supports_all_of_chars(font, chars): + best_cmap = get_best_cmap(font) + for char in chars: + assert char in best_cmap, ( + 'U+%04X was not found in %s' % (char, font)) + + +def assert_font_supports_none_of_chars(font, chars): + best_cmap = get_best_cmap(font) + for char in chars: + assert char not in best_cmap, ( + 'U+%04X was found in %s' % (char, font)) + + def check_hyphens(hyphens_dir): # Find all the scripts that need automatic hyphenation scripts = set() @@ -141,6 +155,70 @@ def parse_fonts_xml(fonts_xml_path): _script_to_font_map[script].add((font_file, index)) +def check_emoji_availability(): + emoji_fonts = [font[5] for font in _fallback_chain if 'Zsye' in font[1]] + emoji_chars = _emoji_properties['Emoji'] + for emoji_font in emoji_fonts: + assert_font_supports_all_of_chars(emoji_font, emoji_chars) + + +def check_emoji_defaults(): + default_emoji_chars = _emoji_properties['Emoji_Presentation'] + emoji_font_seen = False + for name, scripts, variant, weight, style, font in _fallback_chain: + if 'Zsye' in scripts: + emoji_font_seen = True + # No need to check the emoji font + continue + # For later fonts, we only check them if they have a script + # defined, since the defined script may get them to a higher + # score even if they appear after the emoji font. + if emoji_font_seen and not scripts: + continue + + if font[1] is None: + emoji_to_skip = set() + else: + # CJK font, skip checking the following characters for now. + # See b/26153752 + emoji_to_skip = ({ + 0x26BD, # SOCCER BALL + 0x26BE, # BASEBALL + 0x1F18E, # NEGATIVE SQUARED AB + 0x1F201, # SQUARED KATAKANA KOKO + 0x1F21A, # SQUARED CJK UNIFIED IDEOGRAPH-7121 + 0x1F22F, # SQUARED CJK UNIFIED IDEOGRAPH-6307 + } | set(xrange(0x1F191, 0x1F19A+1)) + | set(xrange(0x1F232, 0x1F236+1)) + | set(xrange(0x1F238, 0x1F23A+1)) + | set(xrange(0x1F250, 0x1F251+1))) + + assert_font_supports_none_of_chars(font, + sorted(default_emoji_chars - emoji_to_skip)) + + +def parse_ucd(ucd_path): + global _emoji_properties + _emoji_properties = collections.defaultdict(set) + with open(path.join(ucd_path, 'emoji-data.txt')) as emoji_data_txt: + for line in emoji_data_txt: + if '#' in line: + line = line[:line.index('#')] + line = line.strip() + if not line: + continue + char_range, prop = line.split(';') + char_range = char_range.strip() + prop = prop.strip() + if '..' in char_range: + char_start, char_end = char_range.split('..') + else: + char_start = char_end = char_range + char_start = int(char_start, 16) + char_end = int(char_end, 16) + _emoji_properties[prop].update(xrange(char_start, char_end+1)) + + def main(): target_out = sys.argv[1] global _fonts_dir @@ -152,6 +230,11 @@ def main(): hyphens_dir = path.join(target_out, 'usr', 'hyphen-data') check_hyphens(hyphens_dir) + ucd_path = sys.argv[2] + parse_ucd(ucd_path) + check_emoji_availability() + check_emoji_defaults() + if __name__ == '__main__': main() diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index e3bb3e318749..6d8ecd7c1b96 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -67,7 +67,7 @@ public final class Bitmap_Delegate { // ---- delegate manager ---- private static final DelegateManager<Bitmap_Delegate> sManager = - new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class); + new DelegateManager<>(Bitmap_Delegate.class); private static long sFinalizer = -1; // ---- delegate helper data ---- @@ -314,7 +314,7 @@ public final class Bitmap_Delegate { @LayoutlibDelegate /*package*/ static boolean nativeRecycle(long nativeBitmap) { - sManager.removeJavaReferenceFor(nativeBitmap); + // In our case reycle() is a no-op. We will let the finalizer to dispose the bitmap. return true; } diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 62f91f761683..7f413480a3e4 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -492,8 +492,7 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public void keyguardGoingAway(boolean disableWindowAnimations, - boolean keyguardGoingToNotificationShade) throws RemoteException { + public void keyguardGoingAway(int flags) throws RemoteException { } @Override diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java index 4039cdf7df6d..42c0ae0d8d8f 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java @@ -715,6 +715,10 @@ public class BridgePackageManager extends PackageManager { } @Override + public void flushPackageRestrictionsAsUser(int userId) { + } + + @Override public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, UserHandle userHandle) { return false; diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java index 13abaff8cdfe..87fc7fa367d2 100644 --- a/wifi/java/android/net/wifi/RttManager.java +++ b/wifi/java/android/net/wifi/RttManager.java @@ -1,5 +1,6 @@ package android.net.wifi; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.Context; import android.os.Bundle; @@ -14,6 +15,7 @@ import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; @@ -275,12 +277,13 @@ public class RttManager { /** Implement the Parcelable interface {@hide} */ public static final Creator<RttCapabilities> CREATOR = new Creator<RttCapabilities>() { - public RttCapabilities createFromParcel(Parcel in) { + @Override + public RttCapabilities createFromParcel(Parcel in) { RttCapabilities capabilities = new RttCapabilities(); - capabilities.oneSidedRttSupported = in.readInt() == 1 ? true : false; - capabilities.twoSided11McRttSupported = in.readInt() == 1 ? true : false; - capabilities.lciSupported = in.readInt() == 1 ? true : false; - capabilities.lcrSupported = in.readInt() == 1 ? true : false; + capabilities.oneSidedRttSupported = (in.readInt() == 1); + capabilities.twoSided11McRttSupported = (in.readInt() == 1); + capabilities.lciSupported = (in.readInt() == 1); + capabilities.lcrSupported = (in.readInt() == 1); capabilities.preambleSupported = in.readInt(); capabilities.bwSupported = in.readInt(); capabilities.responderSupported = (in.readInt() == 1); @@ -464,58 +467,57 @@ public class RttManager { /** pseudo-private class used to parcel arguments */ public static class ParcelableRttParams implements Parcelable { + @NonNull public RttParams mParams[]; - ParcelableRttParams(RttParams[] params) { - mParams = params; + /** + * @hide + */ + @VisibleForTesting + public ParcelableRttParams(RttParams[] params) { + mParams = (params == null ? new RttParams[0] : params); } /** Implement the Parcelable interface {@hide} */ + @Override public int describeContents() { return 0; } /** Implement the Parcelable interface {@hide} */ + @Override public void writeToParcel(Parcel dest, int flags) { - if (mParams != null) { - dest.writeInt(mParams.length); - - for (RttParams params : mParams) { - dest.writeInt(params.deviceType); - dest.writeInt(params.requestType); - dest.writeByte(params.secure ? (byte) 1 : 0); - dest.writeString(params.bssid); - dest.writeInt(params.channelWidth); - dest.writeInt(params.frequency); - dest.writeInt(params.centerFreq0); - dest.writeInt(params.centerFreq1); - dest.writeInt(params.numberBurst); - dest.writeInt(params.interval); - dest.writeInt(params.numSamplesPerBurst); - dest.writeInt(params.numRetriesPerMeasurementFrame); - dest.writeInt(params.numRetriesPerFTMR); - dest.writeInt(params.LCIRequest ? 1 : 0); - dest.writeInt(params.LCRRequest ? 1 : 0); - dest.writeInt(params.burstTimeout); - dest.writeInt(params.preamble); - dest.writeInt(params.bandwidth); - } - } else { - dest.writeInt(0); + dest.writeInt(mParams.length); + + for (RttParams params : mParams) { + dest.writeInt(params.deviceType); + dest.writeInt(params.requestType); + dest.writeByte(params.secure ? (byte) 1 : 0); + dest.writeString(params.bssid); + dest.writeInt(params.channelWidth); + dest.writeInt(params.frequency); + dest.writeInt(params.centerFreq0); + dest.writeInt(params.centerFreq1); + dest.writeInt(params.numberBurst); + dest.writeInt(params.interval); + dest.writeInt(params.numSamplesPerBurst); + dest.writeInt(params.numRetriesPerMeasurementFrame); + dest.writeInt(params.numRetriesPerFTMR); + dest.writeInt(params.LCIRequest ? 1 : 0); + dest.writeInt(params.LCRRequest ? 1 : 0); + dest.writeInt(params.burstTimeout); + dest.writeInt(params.preamble); + dest.writeInt(params.bandwidth); } } /** Implement the Parcelable interface {@hide} */ public static final Creator<ParcelableRttParams> CREATOR = new Creator<ParcelableRttParams>() { + @Override public ParcelableRttParams createFromParcel(Parcel in) { int num = in.readInt(); - - if (num == 0) { - return new ParcelableRttParams(null); - } - RttParams params[] = new RttParams[num]; for (int i = 0; i < num; i++) { params[i] = new RttParams(); @@ -532,8 +534,8 @@ public class RttManager { params[i].numSamplesPerBurst = in.readInt(); params[i].numRetriesPerMeasurementFrame = in.readInt(); params[i].numRetriesPerFTMR = in.readInt(); - params[i].LCIRequest = in.readInt() == 1 ? true : false; - params[i].LCRRequest = in.readInt() == 1 ? true : false; + params[i].LCIRequest = (in.readInt() == 1); + params[i].LCRRequest = (in.readInt() == 1); params[i].burstTimeout = in.readInt(); params[i].preamble = in.readInt(); params[i].bandwidth = in.readInt(); @@ -543,6 +545,7 @@ public class RttManager { return parcelableParams; } + @Override public ParcelableRttParams[] newArray(int size) { return new ParcelableRttParams[size]; } @@ -715,11 +718,13 @@ public class RttManager { } /** Implement the Parcelable interface {@hide} */ + @Override public int describeContents() { return 0; } /** Implement the Parcelable interface {@hide} */ + @Override public void writeToParcel(Parcel dest, int flags) { if (mResults != null) { dest.writeInt(mResults.length); @@ -764,6 +769,7 @@ public class RttManager { /** Implement the Parcelable interface {@hide} */ public static final Creator<ParcelableRttResults> CREATOR = new Creator<ParcelableRttResults>() { + @Override public ParcelableRttResults createFromParcel(Parcel in) { int num = in.readInt(); @@ -816,6 +822,7 @@ public class RttManager { return parcelableResults; } + @Override public ParcelableRttResults[] newArray(int size) { return new ParcelableRttResults[size]; } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index a5bfd3c094bc..823fd26c7904 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -21,7 +21,6 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.content.Context; import android.net.ConnectivityManager; -import android.net.ConnectivityManager.NetworkCallback; import android.net.DhcpInfo; import android.net.Network; import android.net.NetworkCapabilities; @@ -666,17 +665,15 @@ public class WifiManager { private final int mTargetSdkVersion; private static final int INVALID_KEY = 0; - private static int sListenerKey = 1; - private static final SparseArray sListenerMap = new SparseArray(); - private static final Object sListenerMapLock = new Object(); + private int mListenerKey = 1; + private final SparseArray mListenerMap = new SparseArray(); + private final Object mListenerMapLock = new Object(); - private static AsyncChannel sAsyncChannel; - private static CountDownLatch sConnected; - private static ConnectivityManager sCM; + private AsyncChannel mAsyncChannel; + private CountDownLatch mConnected; - private static final Object sThreadRefLock = new Object(); - private static int sThreadRefCount; - private static HandlerThread sHandlerThread; + /* TODO(b/27432949): Use a common connectivity thread for this. */ + private HandlerThread mHandlerThread; /** * Create a new WifiManager instance. @@ -1482,7 +1479,7 @@ public class WifiManager { */ public void getTxPacketCount(TxPacketCountListener listener) { validateChannel(); - sAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener)); + mAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener)); } /** @@ -1846,25 +1843,34 @@ public class WifiManager { public void onFailure(int reason); } - private static class ServiceHandler extends Handler { + // Ensure that multiple ServiceHandler threads do not interleave message dispatch. + private static final Object sServiceHandlerDispatchLock = new Object(); + + private class ServiceHandler extends Handler { ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message message) { + synchronized (sServiceHandlerDispatchLock) { + dispatchMessageToListeners(message); + } + } + + private void dispatchMessageToListeners(Message message) { Object listener = removeListener(message.arg2); switch (message.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); + mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); } else { Log.e(TAG, "Failed to set up channel connection"); // This will cause all further async API calls on the WifiManager // to fail and throw an exception - sAsyncChannel = null; + mAsyncChannel = null; } - sConnected.countDown(); + mConnected.countDown(); break; case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: // Ignore @@ -1873,7 +1879,7 @@ public class WifiManager { Log.e(TAG, "Channel connection lost"); // This will cause all further async API calls on the WifiManager // to fail and throw an exception - sAsyncChannel = null; + mAsyncChannel = null; getLooper().quit(); break; /* ActionListeners grouped together */ @@ -1899,8 +1905,8 @@ public class WifiManager { WpsResult result = (WpsResult) message.obj; ((WpsCallback) listener).onStarted(result.pin); //Listener needs to stay until completion or failure - synchronized(sListenerMapLock) { - sListenerMap.put(message.arg2, listener); + synchronized (mListenerMapLock) { + mListenerMap.put(message.arg2, listener); } } break; @@ -1945,54 +1951,50 @@ public class WifiManager { } } - private static int putListener(Object listener) { + private int putListener(Object listener) { if (listener == null) return INVALID_KEY; int key; - synchronized (sListenerMapLock) { + synchronized (mListenerMapLock) { do { - key = sListenerKey++; + key = mListenerKey++; } while (key == INVALID_KEY); - sListenerMap.put(key, listener); + mListenerMap.put(key, listener); } return key; } - private static Object removeListener(int key) { + private Object removeListener(int key) { if (key == INVALID_KEY) return null; - synchronized (sListenerMapLock) { - Object listener = sListenerMap.get(key); - sListenerMap.remove(key); + synchronized (mListenerMapLock) { + Object listener = mListenerMap.get(key); + mListenerMap.remove(key); return listener; } } private void init() { - synchronized (sThreadRefLock) { - if (++sThreadRefCount == 1) { - Messenger messenger = getWifiServiceMessenger(); - if (messenger == null) { - sAsyncChannel = null; - return; - } + Messenger messenger = getWifiServiceMessenger(); + if (messenger == null) { + mAsyncChannel = null; + return; + } - sHandlerThread = new HandlerThread("WifiManager"); - sAsyncChannel = new AsyncChannel(); - sConnected = new CountDownLatch(1); - - sHandlerThread.start(); - Handler handler = new ServiceHandler(sHandlerThread.getLooper()); - sAsyncChannel.connect(mContext, handler, messenger); - try { - sConnected.await(); - } catch (InterruptedException e) { - Log.e(TAG, "interrupted wait at init"); - } - } + mHandlerThread = new HandlerThread("WifiManager"); + mAsyncChannel = new AsyncChannel(); + mConnected = new CountDownLatch(1); + + mHandlerThread.start(); + Handler handler = new ServiceHandler(mHandlerThread.getLooper()); + mAsyncChannel.connect(mContext, handler, messenger); + try { + mConnected.await(); + } catch (InterruptedException e) { + Log.e(TAG, "interrupted wait at init"); } } private void validateChannel() { - if (sAsyncChannel == null) throw new IllegalStateException( + if (mAsyncChannel == null) throw new IllegalStateException( "No permission to access and change wifi or a bad initialization"); } @@ -2017,7 +2019,7 @@ public class WifiManager { validateChannel(); // Use INVALID_NETWORK_ID for arg1 when passing a config object // arg1 is used to pass network id when the network already exists - sAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, + mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, putListener(listener), config); } @@ -2037,7 +2039,7 @@ public class WifiManager { public void connect(int networkId, ActionListener listener) { if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative"); validateChannel(); - sAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener)); + mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener)); } /** @@ -2061,7 +2063,7 @@ public class WifiManager { public void save(WifiConfiguration config, ActionListener listener) { if (config == null) throw new IllegalArgumentException("config cannot be null"); validateChannel(); - sAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config); + mAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config); } /** @@ -2080,7 +2082,7 @@ public class WifiManager { public void forget(int netId, ActionListener listener) { if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); validateChannel(); - sAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener)); + mAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener)); } /** @@ -2095,7 +2097,7 @@ public class WifiManager { public void disable(int netId, ActionListener listener) { if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative"); validateChannel(); - sAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener)); + mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener)); } /** @@ -2124,7 +2126,7 @@ public class WifiManager { public void startWps(WpsInfo config, WpsCallback listener) { if (config == null) throw new IllegalArgumentException("config cannot be null"); validateChannel(); - sAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config); + mAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config); } /** @@ -2136,7 +2138,7 @@ public class WifiManager { */ public void cancelWps(WpsCallback listener) { validateChannel(); - sAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener)); + mAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener)); } /** @@ -2601,10 +2603,8 @@ public class WifiManager { protected void finalize() throws Throwable { try { - synchronized (sThreadRefLock) { - if (--sThreadRefCount == 0 && sAsyncChannel != null) { - sAsyncChannel.disconnect(); - } + if (mAsyncChannel != null) { + mAsyncChannel.disconnect(); } } finally { super.finalize(); |