Merge "Add Transition for App -> Recents on TV." into nyc-dev
diff --git a/Android.mk b/Android.mk
index 0bd6b7f..cf6d946 100644
--- a/Android.mk
+++ b/Android.mk
@@ -42,7 +42,7 @@
# 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 @@
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 \
diff --git a/api/current.txt b/api/current.txt
index 9e0af76..672eb4d9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -559,6 +559,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
@@ -6041,6 +6040,27 @@
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();
@@ -6245,6 +6265,8 @@
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();
@@ -6258,8 +6280,6 @@
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
@@ -6581,31 +6601,6 @@
}
-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 {
@@ -9454,6 +9449,7 @@
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);
@@ -10116,7 +10112,6 @@
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();
@@ -10128,6 +10123,7 @@
public abstract class ComplexColor {
ctor public ComplexColor();
+ method public int getChangingConfigurations();
method public abstract int getDefaultColor();
method public boolean isStateful();
}
@@ -11475,17 +11471,6 @@
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);
@@ -12352,10 +12337,6 @@
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);
@@ -13035,9 +13016,9 @@
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 {
@@ -23104,6 +23085,7 @@
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();
@@ -23121,6 +23103,7 @@
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);
@@ -23152,6 +23135,7 @@
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);
@@ -23213,6 +23197,7 @@
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);
@@ -30762,6 +30747,7 @@
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";
@@ -30784,6 +30770,7 @@
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
@@ -32427,7 +32414,6 @@
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";
@@ -36058,9 +36044,11 @@
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();
@@ -36074,6 +36062,7 @@
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
}
@@ -36084,6 +36073,7 @@
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);
@@ -36114,6 +36104,7 @@
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
@@ -36133,6 +36124,7 @@
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
}
@@ -36247,15 +36239,19 @@
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);
@@ -36279,9 +36275,12 @@
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
@@ -36295,6 +36294,7 @@
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";
@@ -36304,6 +36304,7 @@
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
}
@@ -36381,7 +36382,9 @@
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;
@@ -36417,6 +36420,7 @@
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);
@@ -36567,6 +36571,7 @@
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();
@@ -36583,6 +36588,7 @@
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);
@@ -36680,6 +36686,7 @@
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
@@ -36821,6 +36828,7 @@
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";
@@ -42585,6 +42593,7 @@
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);
@@ -43681,7 +43690,7 @@
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);
@@ -57344,6 +57353,7 @@
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();
@@ -57428,6 +57438,28 @@
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[]);
@@ -57615,6 +57647,7 @@
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();
@@ -58248,18 +58281,28 @@
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();
}
@@ -58267,6 +58310,8 @@
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();
@@ -58997,6 +59042,7 @@
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();
@@ -59048,6 +59094,7 @@
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;
}
@@ -59111,6 +59158,78 @@
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;
@@ -59119,20 +59238,130 @@
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 {
@@ -59162,6 +59391,7 @@
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 {
@@ -59172,6 +59402,7 @@
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 {
@@ -59203,6 +59434,9 @@
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();
@@ -59210,6 +59444,8 @@
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);
@@ -59218,6 +59454,7 @@
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();
@@ -59225,6 +59462,7 @@
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);
@@ -59252,6 +59490,7 @@
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);
@@ -59295,8 +59534,11 @@
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 {
@@ -59307,6 +59549,32 @@
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);
@@ -59397,6 +59665,8 @@
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();
@@ -59410,11 +59680,13 @@
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();
@@ -59452,6 +59724,7 @@
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();
@@ -59459,6 +59732,7 @@
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();
@@ -59477,9 +59751,11 @@
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();
}
@@ -59553,6 +59829,7 @@
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;
@@ -59573,6 +59850,7 @@
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;
}
@@ -59592,6 +59870,7 @@
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);
@@ -59639,6 +59918,7 @@
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;
}
@@ -59742,6 +60022,7 @@
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;
}
@@ -59871,112 +60152,136 @@
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);
}
@@ -59994,34 +60299,46 @@
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);
}
@@ -60036,6 +60353,59 @@
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 {
@@ -60243,6 +60613,34 @@
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 2f55373..8ac2d63 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -35,6 +35,25 @@
}
+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 708286c..77545c2 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -654,6 +654,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
@@ -6198,6 +6197,27 @@
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();
@@ -6511,6 +6531,8 @@
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();
@@ -6524,8 +6546,6 @@
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
@@ -6848,31 +6868,6 @@
}
-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 {
@@ -8409,6 +8404,7 @@
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
@@ -9788,6 +9784,7 @@
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);
@@ -9928,11 +9925,12 @@
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);
@@ -10511,7 +10509,6 @@
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();
@@ -10523,6 +10520,7 @@
public abstract class ComplexColor {
ctor public ComplexColor();
+ method public int getChangingConfigurations();
method public abstract int getDefaultColor();
method public boolean isStateful();
}
@@ -11870,17 +11868,6 @@
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);
@@ -12747,10 +12734,6 @@
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);
@@ -13430,9 +13413,9 @@
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 {
@@ -15291,37 +15274,32 @@
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();
@@ -33114,6 +33092,7 @@
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";
@@ -33136,6 +33115,7 @@
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
@@ -34911,7 +34891,6 @@
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";
@@ -38658,10 +38637,12 @@
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();
@@ -38676,6 +38657,7 @@
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
}
@@ -38686,6 +38668,7 @@
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);
@@ -38716,6 +38699,7 @@
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
@@ -38735,6 +38719,7 @@
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
}
@@ -38860,15 +38845,19 @@
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);
@@ -38892,9 +38881,12 @@
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
@@ -38908,6 +38900,7 @@
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";
@@ -38917,6 +38910,7 @@
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
}
@@ -38994,7 +38988,9 @@
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;
@@ -39031,6 +39027,7 @@
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();
@@ -39236,6 +39233,7 @@
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();
@@ -39253,6 +39251,7 @@
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);
@@ -39377,6 +39376,7 @@
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
@@ -39520,6 +39520,7 @@
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";
@@ -45348,6 +45349,7 @@
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);
@@ -46445,7 +46447,7 @@
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);
@@ -48699,12 +48701,13 @@
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
@@ -60444,6 +60447,7 @@
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();
@@ -60528,6 +60532,28 @@
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[]);
@@ -60715,6 +60741,7 @@
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();
@@ -61348,18 +61375,28 @@
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();
}
@@ -61367,6 +61404,8 @@
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();
@@ -62097,6 +62136,7 @@
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();
@@ -62148,6 +62188,7 @@
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;
}
@@ -62211,6 +62252,78 @@
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;
@@ -62219,20 +62332,130 @@
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 {
@@ -62262,6 +62485,7 @@
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 {
@@ -62272,6 +62496,7 @@
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 {
@@ -62303,6 +62528,9 @@
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();
@@ -62310,6 +62538,8 @@
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);
@@ -62318,6 +62548,7 @@
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();
@@ -62325,6 +62556,7 @@
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);
@@ -62352,6 +62584,7 @@
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);
@@ -62395,8 +62628,11 @@
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 {
@@ -62407,6 +62643,32 @@
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);
@@ -62497,6 +62759,8 @@
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();
@@ -62510,11 +62774,13 @@
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();
@@ -62552,6 +62818,7 @@
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();
@@ -62559,6 +62826,7 @@
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();
@@ -62577,9 +62845,11 @@
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();
}
@@ -62653,6 +62923,7 @@
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;
@@ -62673,6 +62944,7 @@
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;
}
@@ -62692,6 +62964,7 @@
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);
@@ -62739,6 +63012,7 @@
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;
}
@@ -62842,6 +63116,7 @@
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;
}
@@ -62971,112 +63246,136 @@
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);
}
@@ -63094,34 +63393,46 @@
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);
}
@@ -63136,6 +63447,59 @@
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 {
@@ -63343,6 +63707,34 @@
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 79f7297..caeecf5 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -33,6 +33,25 @@
}
+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 9aed5e9..55d6ecd 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -559,6 +559,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
@@ -6045,6 +6044,27 @@
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();
@@ -6249,6 +6269,8 @@
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();
@@ -6262,8 +6284,6 @@
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
@@ -6585,31 +6605,6 @@
}
-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 {
@@ -9463,6 +9458,7 @@
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);
@@ -10126,7 +10122,6 @@
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();
@@ -10138,6 +10133,7 @@
public abstract class ComplexColor {
ctor public ComplexColor();
+ method public int getChangingConfigurations();
method public abstract int getDefaultColor();
method public boolean isStateful();
}
@@ -11485,17 +11481,6 @@
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);
@@ -12362,10 +12347,6 @@
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);
@@ -13045,9 +13026,9 @@
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 {
@@ -23170,6 +23151,7 @@
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();
@@ -23187,6 +23169,7 @@
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);
@@ -23218,6 +23201,7 @@
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);
@@ -23279,6 +23263,7 @@
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);
@@ -30832,6 +30817,7 @@
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";
@@ -30854,6 +30840,7 @@
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
@@ -32497,7 +32484,6 @@
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";
@@ -36130,9 +36116,11 @@
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();
@@ -36146,6 +36134,7 @@
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
}
@@ -36156,6 +36145,7 @@
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);
@@ -36186,6 +36176,7 @@
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
@@ -36205,6 +36196,7 @@
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
}
@@ -36319,15 +36311,19 @@
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);
@@ -36351,9 +36347,12 @@
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
@@ -36367,6 +36366,7 @@
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";
@@ -36376,6 +36376,7 @@
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
}
@@ -36453,7 +36454,9 @@
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;
@@ -36489,6 +36492,7 @@
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);
@@ -36639,6 +36643,7 @@
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();
@@ -36655,6 +36660,7 @@
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);
@@ -36752,6 +36758,7 @@
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
@@ -36893,6 +36900,7 @@
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";
@@ -42659,6 +42667,7 @@
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);
@@ -43755,7 +43764,7 @@
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);
@@ -57418,6 +57427,7 @@
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();
@@ -57502,6 +57512,28 @@
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[]);
@@ -57689,6 +57721,7 @@
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();
@@ -58322,18 +58355,28 @@
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();
}
@@ -58341,6 +58384,8 @@
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();
@@ -59071,6 +59116,7 @@
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();
@@ -59122,6 +59168,7 @@
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;
}
@@ -59185,6 +59232,78 @@
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;
@@ -59193,20 +59312,130 @@
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 {
@@ -59236,6 +59465,7 @@
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 {
@@ -59246,6 +59476,7 @@
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 {
@@ -59277,6 +59508,9 @@
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();
@@ -59284,6 +59518,8 @@
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);
@@ -59292,6 +59528,7 @@
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();
@@ -59299,6 +59536,7 @@
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);
@@ -59326,6 +59564,7 @@
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);
@@ -59369,8 +59608,11 @@
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 {
@@ -59381,6 +59623,32 @@
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);
@@ -59471,6 +59739,8 @@
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();
@@ -59484,11 +59754,13 @@
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();
@@ -59526,6 +59798,7 @@
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();
@@ -59533,6 +59806,7 @@
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();
@@ -59551,9 +59825,11 @@
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();
}
@@ -59627,6 +59903,7 @@
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;
@@ -59647,6 +59924,7 @@
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;
}
@@ -59666,6 +59944,7 @@
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);
@@ -59713,6 +59992,7 @@
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;
}
@@ -59816,6 +60096,7 @@
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;
}
@@ -59945,112 +60226,136 @@
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);
}
@@ -60068,34 +60373,46 @@
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);
}
@@ -60110,6 +60427,59 @@
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 {
@@ -60317,6 +60687,34 @@
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 2f55373..8ac2d63 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -35,6 +35,25 @@
}
+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 8bcbf51..7590325 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -305,7 +305,7 @@
}
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/app/Activity.java b/core/java/android/app/Activity.java
index 6b67b95..a0a599e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1976,15 +1976,13 @@
* 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 @@
* 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 8b62ef9..811a05b 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2307,7 +2307,7 @@
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 @@
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 094950b..a6e7d67 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -710,6 +710,10 @@
/** @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 @@
/**
* 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/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index ca05091..5ef03d1 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1147,7 +1147,7 @@
}
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 @@
@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 @@
}
@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 @@
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 32ace14..4fccbc9 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1332,9 +1332,14 @@
}
}
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 cdbf598..8e87e26 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -475,8 +475,13 @@
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 b8fc323..c68fd65 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -281,7 +281,7 @@
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 @@
}
}
}
-
- 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();
- }
- }
-
- 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");
- }
- // 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);
-
- /*
- * 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 (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;
+ if (mBaseClassLoader != null) {
+ mClassLoader = mBaseClassLoader;
} else {
- classLoader = mClassLoader;
+ mClassLoader = ClassLoader.getSystemClassLoader();
}
- } else {
- if (mClassLoader == null) {
- if (mBaseClassLoader == null) {
- classLoader = ClassLoader.getSystemClassLoader();
- } else {
- classLoader = mBaseClassLoader;
- }
- } else {
- classLoader = mClassLoader;
+
+ 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();
}
}
- return classLoader;
+
+ 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);
+
+ /*
+ * 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 (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);
+ }
}
public ClassLoader getClassLoader() {
synchronized (this) {
if (mClassLoader == null) {
- mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/);
+ createOrUpdateClassLoaderLocked(null /*addedPaths*/);
}
return mClassLoader;
}
@@ -915,6 +913,8 @@
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 @@
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 88c8964..1e288de 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3173,16 +3173,9 @@
}
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;
}
@@ -4587,13 +4580,13 @@
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 +4689,13 @@
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 10aa7eb..0d4729d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -913,10 +913,6 @@
* (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 6c0b69c..9d7f724 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -51,6 +51,7 @@
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 @@
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/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index a34e8551e..dd70b5d 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -268,7 +268,7 @@
"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 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 @@
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 @@
* @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 @@
}
/**
- * 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 ec1e3e6..b7d9b80 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -25,16 +25,13 @@
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.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 @@
/**
* 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 @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 @@
*
* <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 @@
}
/**
- * 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 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 @@
}
/**
- * 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 @@
}
/**
- * 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.
+ * {@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>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 @@
}
/**
- * 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.
+ * {@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>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 @@
}
/**
- * 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.
+ * {@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>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 @@
}
/**
- * 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.
+ * {@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>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 @@
}
/**
- * 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.
+ * {@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>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 @@
}
/**
- * 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.
+ * {@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>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 @@
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 @@
}
/**
- * 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 @@
}
/**
- * 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 @@
*
* @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 @@
}
/**
- * Retrieve the number of times the user has failed at entering a
- * password since that last successful password entry.
+ * 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>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.
+ * @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 @@
}
/**
- * 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 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 @@
}
/**
- * 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 @@
}
/**
- * Make the device lock immediately, as if the lock screen timeout has
- * expired at the point of this call.
+ * 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>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.
+ * @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 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.
+ * 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.
*
- * <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 @@
}
/**
- * 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.
+ * 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 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.
* @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) {
@@ -2544,36 +2540,35 @@
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) {
@@ -2650,6 +2645,8 @@
*
* @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) {
@@ -2668,6 +2665,8 @@
* @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) {
@@ -2690,6 +2689,8 @@
* @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[]>();
@@ -2717,6 +2718,8 @@
*
* @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) {
@@ -2735,6 +2738,8 @@
* @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) {
@@ -2769,6 +2774,8 @@
* @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) {
@@ -2794,6 +2801,8 @@
* 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) {
@@ -2820,6 +2829,8 @@
* {@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 {
@@ -2849,15 +2860,16 @@
* 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 {
@@ -2871,12 +2883,13 @@
}
/**
- * 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) {
@@ -2891,18 +2904,18 @@
/**
* 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.
+ * 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.
*
- * <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.
- *
- * @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) {
@@ -2918,12 +2931,12 @@
/**
* 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) {
@@ -2937,18 +2950,20 @@
}
/**
- * 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) {
@@ -2984,14 +2999,16 @@
/**
* 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) {
@@ -3020,15 +3037,16 @@
* 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) {
@@ -3063,16 +3081,17 @@
}
/**
- * 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) {
@@ -3100,15 +3119,16 @@
/**
* 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(
@@ -3124,6 +3144,7 @@
/**
* @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) {
@@ -3141,39 +3162,41 @@
* 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) {
@@ -3500,13 +3523,13 @@
}
/**
- * 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) {
@@ -3616,13 +3639,14 @@
}
/**
- * 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) {
@@ -3682,20 +3706,21 @@
/**
* 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) {
@@ -3724,21 +3749,22 @@
/**
* 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) {
@@ -3758,7 +3784,8 @@
* @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) {
@@ -3776,8 +3803,8 @@
* 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) {
@@ -3790,15 +3817,15 @@
}
/**
- * 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) {
@@ -3896,19 +3923,20 @@
/**
* 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) {
@@ -3924,12 +3952,13 @@
/**
* 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) {
@@ -3955,7 +3984,8 @@
*
* @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) {
@@ -3974,7 +4004,8 @@
*
* @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) {
@@ -3988,9 +4019,12 @@
}
/**
- * 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) {
@@ -4005,34 +4039,34 @@
/**
* 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
*/
@@ -4048,23 +4082,29 @@
}
/**
- * 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) {
@@ -4110,14 +4150,15 @@
}
/**
- * 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) {
@@ -4132,11 +4173,12 @@
/**
* 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) {
@@ -4167,14 +4209,15 @@
}
/**
- * 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) {
@@ -4190,11 +4233,12 @@
/**
* 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) {
@@ -4254,18 +4298,17 @@
}
/**
- * 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) {
@@ -4278,16 +4321,16 @@
}
/**
- * 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) {
@@ -4322,14 +4365,15 @@
/**
* 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) {
@@ -4345,7 +4389,9 @@
* 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) {
@@ -4358,25 +4404,22 @@
}
/**
- * 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) {
@@ -4392,12 +4435,13 @@
/**
* 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) {
@@ -4458,27 +4502,23 @@
}
/**
- * 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) {
@@ -4494,12 +4534,13 @@
/**
* 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) {
@@ -4586,6 +4627,7 @@
*
* @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,
@@ -4671,27 +4713,27 @@
* 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,
@@ -4704,12 +4746,13 @@
}
/**
- * 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 {
@@ -4725,7 +4768,7 @@
* @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) {
@@ -4739,18 +4782,18 @@
/**
* 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) {
@@ -4767,13 +4810,13 @@
/**
* 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) {
@@ -4788,13 +4831,13 @@
/**
* 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) {
@@ -4811,11 +4854,11 @@
* {@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());
@@ -4835,14 +4878,15 @@
}
/**
- * 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) {
@@ -4862,6 +4906,7 @@
* @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) {
@@ -4880,6 +4925,7 @@
*
* @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) {
@@ -4892,13 +4938,14 @@
}
/**
- * 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) {
@@ -4914,21 +4961,22 @@
/**
* 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) {
@@ -4973,17 +5021,15 @@
/**
* 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)
@@ -5036,7 +5082,8 @@
/**
* 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>
@@ -5044,30 +5091,30 @@
* <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) {
@@ -5083,19 +5130,23 @@
* 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) {
@@ -5108,14 +5159,16 @@
}
/**
- * 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) {
@@ -5133,6 +5186,7 @@
*
* @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) {
@@ -5149,6 +5203,7 @@
*
* @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) {
@@ -5162,12 +5217,12 @@
}
/**
- * 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) {
@@ -5185,14 +5240,15 @@
* 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) {
@@ -5206,19 +5262,18 @@
}
/**
- * 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)
*/
@@ -5235,17 +5290,16 @@
/**
* 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)
*/
@@ -5267,9 +5321,9 @@
*
* @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) {
@@ -5290,6 +5344,7 @@
*
* @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 {
@@ -5304,10 +5359,10 @@
* {@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) {
@@ -5338,17 +5393,17 @@
/**
* 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 {
@@ -5360,14 +5415,13 @@
/**
* 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 {
@@ -5399,19 +5453,19 @@
/**
* 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) {
@@ -5437,29 +5491,28 @@
}
/**
- * 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
@@ -5480,13 +5533,15 @@
* @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)
*/
@@ -5503,9 +5558,6 @@
* 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.
*/
@@ -5552,10 +5604,11 @@
* 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 {
@@ -5566,7 +5619,12 @@
}
/**
- * 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 {
@@ -5577,24 +5635,21 @@
}
/**
- * 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) {
@@ -5611,8 +5666,9 @@
* 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) {
@@ -5626,18 +5682,18 @@
}
/**
- * 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) {
@@ -5654,8 +5710,9 @@
* 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) {
@@ -5712,10 +5769,11 @@
/**
* 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 {
@@ -5729,46 +5787,64 @@
}
/**
- * 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
@@ -5778,12 +5854,13 @@
* 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 {
@@ -5796,6 +5873,14 @@
}
/**
+ * 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.
*
@@ -5813,22 +5898,22 @@
/**
* 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();
@@ -5836,15 +5921,24 @@
}
/**
- * 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 {
@@ -5879,6 +5973,7 @@
*
* @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 {
@@ -5906,13 +6001,14 @@
/**
* 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 {
@@ -5923,11 +6019,12 @@
}
/**
- * 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 61b40d4..54a2f7a 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 @@
/**
* 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 c38496d..3ba5bd8 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -290,10 +290,10 @@
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
similarity index 98%
rename from core/java/android/auditing/SecurityLog.java
rename to core/java/android/app/admin/SecurityLog.java
index 13823a2..001a81d 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 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
similarity index 93%
rename from core/java/android/auditing/SecurityLogTags.logtags
rename to core/java/android/app/admin/SecurityLogTags.logtags
index ccc3799..39371c7 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 bbfec41..828ac38 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -73,9 +73,32 @@
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 @@
* 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 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 @@
* 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/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index eb4cb91..d762a17 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 @@
} 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 @@
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 0000000..736e55d
--- /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 cbce22c..eee66d1 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -131,6 +131,12 @@
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 0000000..b26ea29
--- /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 0ec58ea..58630b0 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -836,6 +836,17 @@
}
}
+ /** {@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/Context.java b/core/java/android/content/Context.java
index ccb0552..c4dfdcf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2681,6 +2681,7 @@
HARDWARE_PROPERTIES_SERVICE,
//@hide: SOUND_TRIGGER_SERVICE,
SHORTCUT_SERVICE,
+ //@hide: CONTEXTHUB_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
@@ -3585,6 +3586,18 @@
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/Intent.java b/core/java/android/content/Intent.java
index 182475f..09aad3b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -660,6 +660,8 @@
/**
* 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 @@
/**
* 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";
@@ -6034,13 +6037,20 @@
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.
*
@@ -8935,6 +8945,17 @@
* @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/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index b1d3f20..6b3d4f1 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -34,7 +34,7 @@
* {@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 @@
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 c684447..dabc652 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -291,6 +291,8 @@
*/
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 @@
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 @@
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 a6a732e..8724d5e 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.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 @@
* 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 @@
}
/**
+ * 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 @@
/**
* 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 @@
*
* @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 @@
* <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 @@
* 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 @@
* 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 @@
/**
* 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 @@
* @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 @@
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 0f5ec91..ed8143e 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -37,7 +37,6 @@
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.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 @@
* 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 @@
* 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 @@
/** {@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 @@
}
/** {@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 e1e8a07..c179596 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4387,10 +4387,8 @@
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 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 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 89f2fc4..13ebb82 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 @@
* 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 e41136c..b5c1f30 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -524,7 +524,7 @@
}
/** @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 918c763..4255582 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -36,8 +36,7 @@
*/
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 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/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 5bf2e3e..fb5bfd3 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -442,7 +442,7 @@
* @see android.content.pm.ActivityInfo
*/
public @Config int getChangingConfigurations() {
- return mChangingConfigurations;
+ return super.getChangingConfigurations() | mChangingConfigurations;
}
private int modulateColorAlpha(int baseColor, float alphaMod) {
diff --git a/core/java/android/content/res/ComplexColor.java b/core/java/android/content/res/ComplexColor.java
index d96ec62..b297764 100644
--- a/core/java/android/content/res/ComplexColor.java
+++ b/core/java/android/content/res/ComplexColor.java
@@ -25,6 +25,8 @@
* {@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 @@
* @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/GradientColor.java b/core/java/android/content/res/GradientColor.java
index 3291340..f29656a 100644
--- a/core/java/android/content/res/GradientColor.java
+++ b/core/java/android/content/res/GradientColor.java
@@ -542,6 +542,19 @@
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 90037f7..a364010 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -713,9 +713,11 @@
}
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 {
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index c4afbfb..b75e653 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -54,10 +54,9 @@
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 @@
/** {@hide} */
public SystemSensorManager(Context context, Looper mainLooper) {
+ synchronized(sLock) {
+ if (!sSensorModuleInitialized) {
+ sSensorModuleInitialized = true;
+ nativeClassInit();
+ }
+ }
+
mMainLooper = mainLooper;
mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
mContext = context;
mNativeInstance = nativeCreate(context.getOpPackageName());
- synchronized(mLock) {
- 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);
- }
+ // 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 @@
}
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 @@
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 @@
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 6cc7fec..dfa19b0 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -1196,7 +1196,7 @@
*
* <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 @@
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 @@
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 1a9221a..8de03da 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 e47c541..644e29f 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -23,7 +23,7 @@
/**
* @hide
- */
+ */
@SystemApi
public class ContextHubInfo {
private int mId;
@@ -58,6 +58,8 @@
* 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 @@
/**
* 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 @@
/**
* 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 @@
/**
* 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 @@
* set platform version
*
* @param platformVersion - platform version number
+ *
+ * @hide
*/
public void setPlatformVersion(int platformVersion) {
mPlatformVersion = platformVersion;
@@ -148,6 +158,8 @@
* set platform software version
*
* @param staticSwVersion - platform static s/w version number
+ *
+ * @hide
*/
public void setStaticSwVersion(int staticSwVersion) {
mStaticSwVersion = staticSwVersion;
@@ -166,6 +178,8 @@
* set the tool chain version number
*
* @param toolchainVersion - tool chain version number
+ *
+ * @hide
*/
public void setToolchainVersion(int toolchainVersion) {
mToolchainVersion = toolchainVersion;
@@ -184,6 +198,8 @@
* 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 @@
* 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 @@
* 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 @@
*
* @param peakPowerDrawMw - peak power draw of the hub in
* milliwatts.
+ *
+ * @hide
*/
public void setPeakPowerDrawMw(float peakPowerDrawMw) {
mPeakPowerDrawMw = peakPowerDrawMw;
@@ -281,6 +303,8 @@
* 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 @@
* @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 301b2e4..8deded2 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 @@
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 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 @@
/**
* 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 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 @@
/**
* 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 @@
/**
* 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 @@
*
* @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;
+ 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;
+ }
- 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());
- }
+ /**
+ * 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 message Message to be sent
+ *
+ * @see ContextHubMessage
+ *
+ * @return int 0 on success, -1 otherwise
+ */
+ public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
+ int retVal = -1;
+
+ try {
+ retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not fetch send message :" + e.toString());
}
return retVal;
}
/**
- * Send a message to a spcific nano app instance on a context
- * hub
+ * Set a callback to receive messages from the context hub
*
+ * @param callback Callback object
*
- * @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
- *
- * @see ContextHubMessage
+ * @see ContextHubCallback
*
* @return int 0 on success, -1 otherwise
*/
- public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) {
- 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());
- }
- }
-
- return retVal;
+ public int registerContextHubCallback(ContextHubCallback callback) {
+ return registerContextHubCallback(callback, null);
}
- 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
+ * @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;
+
+ IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE);
+ if (b != null) {
+ mContextHubService = IContextHubService.Stub.asInterface(b);
+
+ try {
+ getBinder().registerCallback(mClientCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not register callback:" + e);
+ }
+
+ } else {
+ Log.d(TAG, "failed to getService");
+ }
}
- private ServiceConnection mServiceConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mContextHubService = IContextHubService.Stub.asInterface(service);
- mContextHubConnected = true;
-
- // Register our Callback
- try {
- mContextHubService.registerCallBack(mClientCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not register callback with context hub service :" + e.toString());
- }
- Log.d(TAG, "contexthub manager connected to " + name.toString());
+ private IContextHubService getBinder() throws RemoteException {
+ if (mContextHubService == null) {
+ throw new RemoteException("Service not connected.");
}
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mContextHubService = null;
- mContextHubConnected = false;
- Log.d(TAG, "contexthub manager disconnected from " + name.toString());
- }
- };
-
+ return mContextHubService;
+ }
}
diff --git a/core/java/android/hardware/location/ContextHubMessage.aidl b/core/java/android/hardware/location/ContextHubMessage.aidl
index 915f1ec..56704e7 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 a2a13c6..274babe 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 @@
/**
* @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 HashMap<Integer, ContextHubInfo> mHubHash;
+ private final Context mContext;
+
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);
- private ContextHubService(Context context) {
- initialize();
- Log.d(TAG, "Created from " + context.toString());
- }
-
- public static ContextHubService getInstance(Context context) {
- synchronized (sSingletonInstanceLock) {
- if (sSingletonInstance == null) {
- sSingletonInstance = new ContextHubService(context);
+ try {
+ mCallback.onMessageReceipt(0, 0, msg);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception " + e + " when calling remote callback");
+ return -1;
}
- return sSingletonInstance;
+ } else {
+ Log.d(TAG, "Message Callback is NULL");
+ }
+
+ return 0;
+ }
+
+ @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 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 int loadNanoApp(int contextHubHandle, NanoApp app) throws RemoteException {
+ checkPermissions();
+ contextHubHandle -= 1;
+
+ if (!(contextHubHandle >= 0 && contextHubHandle < mContextHubInfo.length)) {
+ return -1; // negative handle are invalid, means failed
+ }
+
+ // 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
+
+ return nativeSendMessage(msgHeader, app.getAppBinary());
+ }
+
+ @Override
+ public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+ checkPermissions();
+ NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
+ if (info == null) {
+ return -1; //means failed
+ }
+
+ // Call Native interface here
+ int[] msgHeader = new int[8];
+ msgHeader[0] = info.getContexthubId();
+ msgHeader[1] = ContextHubManager.MSG_UNLOAD_NANO_APP;
+ msgHeader[2] = info.getHandle();
+
+ return nativeSendMessage(msgHeader, null);
+ }
+
+ @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;
}
}
@Override
- public void onCreate() {
- super.onCreate();
+ public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
+ checkPermissions();
+ 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;
}
@Override
- public IBinder onBind(Intent intent) {
- return null;
+ 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());
}
- private final IContextHubService.Stub mBinder = new IContextHubService.Stub() {
-
- private IContextHubCallback callback;
-
- @Override
- public int registerCallBack(IContextHubCallback callback) throws RemoteException{
- this.callback = callback;
- return 0;
- }
-
- @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 ContextHubInfo getContextHubInfo(int contexthubHandle) throws RemoteException {
- return mHubHash.get(contexthubHandle);
- }
-
- @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());
-
- // if successful, add an entry to mNanoAppHash
-
- if(handle > 0) {
- return 0;
- } else {
-
- return -1;
- }
- }
- }
-
- @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);
- }
- }
-
- @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;
- }
- }
-
- @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;
- }
-
- @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();
-
- 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 45b1ef4..141fcf6 100644
--- a/core/java/android/hardware/location/IContextHubCallback.aidl
+++ b/core/java/android/hardware/location/IContextHubCallback.aidl
@@ -18,7 +18,9 @@
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 b2db0b2..ff8c1d0 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.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 e8c7615..d100de2 100644
--- a/core/java/android/hardware/location/MemoryRegion.java
+++ b/core/java/android/hardware/location/MemoryRegion.java
@@ -23,7 +23,6 @@
/**
* @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 d32c44a..9df9a08 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 36d181f..b447b62 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 cc6d475..5f10201 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 ac341e4..369f9e4 100644
--- a/core/java/android/hardware/location/NanoAppFilter.java
+++ b/core/java/android/hardware/location/NanoAppFilter.java
@@ -110,8 +110,9 @@
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 c8c40d7..2db5566 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 2826882..6b79a8a 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -2269,8 +2269,9 @@
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/os/BadParcelableException.java b/core/java/android/os/BadParcelableException.java
index a1c5bb2..7e0b1a5 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 5c71373..6e50155 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -26,7 +26,9 @@
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 @@
// 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 @@
*/
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 @@
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 @@
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 @@
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 74699fd..1097cad 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -27,11 +27,17 @@
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 @@
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 @@
*/
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 Bundle(ClassLoader loader) {
super(loader);
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -90,6 +96,7 @@
*/
public Bundle(int capacity) {
super(capacity);
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -100,9 +107,7 @@
*/
public Bundle(Bundle b) {
super(b);
-
- mHasFds = b.mHasFds;
- mFdsKnown = b.mFdsKnown;
+ mFlags = b.mFlags;
}
/**
@@ -113,6 +118,7 @@
*/
public Bundle(PersistableBundle b) {
super(b);
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -145,14 +151,37 @@
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 @@
@Override
public void clear() {
super.clear();
-
- mHasFds = false;
- mFdsKnown = true;
+ mFlags = FLAG_HAS_FDS_KNOWN | FLAG_ALLOW_FDS;
}
/**
@@ -182,16 +209,20 @@
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 @@
}
}
- 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 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 void putParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
unparcel();
mMap.put(key, value);
- mFdsKnown = false;
+ mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/**
@@ -399,14 +432,14 @@
@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 @@
@Nullable SparseArray<? extends Parcelable> value) {
unparcel();
mMap.put(key, value);
- mFdsKnown = false;
+ mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/**
@@ -1074,7 +1107,7 @@
*/
@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 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 @@
}
return "Bundle[" + mMap.toString() + "]";
}
-
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1b79497..dd73e53 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -605,6 +605,30 @@
*/
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 @@
}
}
- 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 5872f74..b947c97 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -18,7 +18,9 @@
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 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 PersistableBundle() {
super();
+ mFlags = FLAG_DEFUSABLE;
}
/**
@@ -67,6 +72,7 @@
*/
public PersistableBundle(int capacity) {
super(capacity);
+ mFlags = FLAG_DEFUSABLE;
}
/**
@@ -77,6 +83,7 @@
*/
public PersistableBundle(PersistableBundle b) {
super(b);
+ mFlags = b.mFlags;
}
@@ -101,6 +108,7 @@
*/
private PersistableBundle(ArrayMap<String, Object> map) {
super();
+ mFlags = FLAG_DEFUSABLE;
// First stuff everything in.
putAll(map);
@@ -123,6 +131,7 @@
/* package */ PersistableBundle(Parcel parcelledData, int length) {
super(parcelledData, length);
+ mFlags = FLAG_DEFUSABLE;
}
/**
@@ -278,5 +287,4 @@
}
return "PersistableBundle[" + mMap.toString() + "]";
}
-
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index ddcd635..b25b33d 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -434,25 +434,35 @@
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);
- }
-
- BLOCK_MAP_FILE.delete();
- }
-
- // If the package is on the /data partition, use the block map file as
- // the package name instead.
+ // 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();
+ }
+
+ // 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 7223dfb..e2675b1 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -972,7 +972,8 @@
/**
* 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 e7c4a07..e2ae133 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -179,6 +179,7 @@
* <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 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 @@
/** 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 e7a9b7d..4ad7969 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -379,8 +379,18 @@
* @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 d4ff766..5fc2899 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -217,21 +217,6 @@
"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 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 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 @@
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 @@
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 d4fea53..ed7534d 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 @@
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 fc075de..1eaa7cf 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -19,7 +19,7 @@
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 @@
/**
* 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 @@
/** 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 @@
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 bfe5c3f..a1bc2d1 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -247,23 +247,22 @@
*/
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 @@
}
}
- 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 @@
}
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 93a156b..e9153dd 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -1013,7 +1013,7 @@
* @return This instance.
*/
public MeasureBuilder setIntegerPart(long integerPart) {
- return setNumber(String.valueOf(integerPart));
+ return setIntegerPart(String.valueOf(integerPart));
}
/**
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index fb6a9d5..22d5ed8 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.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 @@
}
/**
+ * Returns the display's HDR capabilities.
+ * @hide
+ */
+ public HdrCapabilities getHdrCapabilities() {
+ return new HdrCapabilities();
+ }
+
+ /**
* Gets the supported color transforms of this device.
* @hide
*/
@@ -1112,6 +1123,117 @@
}
/**
+ * 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 f912e51..d8b7421 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -193,8 +193,7 @@
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 57ab6d4..a7bf73a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -84,7 +84,6 @@
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 @@
* {@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 @@
}
/**
+ * 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 @@
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 @@
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 @@
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 @@
/*
* 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 @@
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 @@
}
if (mForegroundInfo.mDrawable != null) {
+ if (isAttachedToWindow()) {
+ mForegroundInfo.mDrawable.setVisible(false, false);
+ }
mForegroundInfo.mDrawable.setCallback(null);
unscheduleDrawable(mForegroundInfo.mDrawable);
}
@@ -18194,6 +18253,9 @@
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 56ee478..aa11e3f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1291,6 +1291,22 @@
}
@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 69c30ba..b770bd5 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -216,6 +216,9 @@
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 f7405e2..a2295ce 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1472,6 +1472,7 @@
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 9f05990..63f3744 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -566,8 +566,8 @@
* @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 a1cbc1d..887cc3a 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -170,7 +170,7 @@
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 @@
},
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 34e81fc..c1392fe 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -91,6 +91,11 @@
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;
diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java
index df33698..35d3bf9 100644
--- a/core/java/android/view/textservice/SpellCheckerSubtype.java
+++ b/core/java/android/view/textservice/SpellCheckerSubtype.java
@@ -50,7 +50,10 @@
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/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 3d72260..0751ab0 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -106,6 +106,9 @@
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 @@
* 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 @@
if (!sPackageInfo.packageName.equals(packageName))
return LIBLOAD_WRONG_PACKAGE_NAME;
- return loadNativeLibrary();
+ return loadNativeLibrary(clazzLoader);
}
static WebViewFactoryProvider getProvider() {
@@ -333,15 +337,16 @@
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 @@
}
// 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 @@
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 @@
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/widget/Editor.java b/core/java/android/widget/Editor.java
index 3b6ba3a..4bcb406 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -18,6 +18,7 @@
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 @@
boolean mInBatchEditControllers;
boolean mShowSoftInputOnFocus = true;
private boolean mPreserveSelection;
+ private boolean mRestartActionModeOnNextRefresh;
boolean mTemporaryDetach;
boolean mIsBeingLongClicked;
@@ -380,9 +382,8 @@
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 @@
}
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 @@
}
final InputMethodManager imm = InputMethodManager.peekInstance();
if (mTextView.hasSelection() && !extractedTextModeWillBeStarted()) {
- startSelectionActionMode();
+ refreshTextActionMode();
}
} else {
if (mBlink != null) {
@@ -1846,6 +1851,7 @@
void refreshTextActionMode() {
if (extractedTextModeWillBeStarted()) {
+ mRestartActionModeOnNextRefresh = false;
return;
}
final boolean hasSelection = mTextView.hasSelection();
@@ -1854,12 +1860,19 @@
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 @@
mTextActionMode.invalidateContentRect();
}
}
+ mRestartActionModeOnNextRefresh = false;
}
/**
@@ -1904,11 +1918,12 @@
*
* @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 @@
}
private void stopTextActionModeWithPreservingSelection() {
+ if (mTextActionMode != null) {
+ mRestartActionModeOnNextRefresh = true;
+ }
mPreserveSelection = true;
stopTextActionMode();
mPreserveSelection = false;
@@ -2460,7 +2478,7 @@
}
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 @@
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 @@
}
// 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 @@
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,19 +3059,12 @@
}
}
- private static class SuggestionInfo {
+ private static final class SuggestionInfo {
// Range of actual suggestion within mText
int mSuggestionStart, mSuggestionEnd;
// The SuggestionSpan that this TextView represents
- @Nullable
- SuggestionSpan mSuggestionSpan;
-
- // The SuggestionSpan start position
- int mSuggestionSpanStart;
-
- // The SuggestionSpan end position
- int mSuggestionSpanEnd;
+ final SuggestionSpanInfo mSuggestionSpanInfo = new SuggestionSpanInfo();
// The index of this suggestion inside suggestionSpan
int mSuggestionIndex;
@@ -3049,9 +3072,32 @@
final SpannableStringBuilder mText = new SpannableStringBuilder();
void clear() {
- mSuggestionSpan = null;
+ 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 mSpanStart;
+
+ // The SuggestionSpan end position
+ int mSpanEnd;
+
+ void clear() {
+ mSuggestionSpan = null;
+ }
}
private class SuggestionHelper {
@@ -3109,48 +3155,51 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
@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 @@
if (mSelectionModifierCursorController != null) {
mSelectionModifierCursorController.hide();
}
-
- mTextActionMode = null;
}
@Override
@@ -5083,27 +5146,12 @@
// 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;
-
- // Also update the selection with the right offsets in this case.
- Selection.setSelection((Spannable) mTextView.getText(),
- startOffset, endOffset);
- }
- if (startOffset != endOffset) {
- startSelectionActionMode();
- }
-
// No longer the first dragging motion, reset.
resetDragAcceleratorState();
+
+ if (mTextView.hasSelection()) {
+ startSelectionActionMode();
+ }
break;
}
}
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 1321221..6d7313d 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1644,7 +1644,7 @@
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 3400873..04d344f 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -913,6 +913,7 @@
if (mDrawable != null) {
mDrawable.setCallback(null);
unscheduleDrawable(mDrawable);
+ mDrawable.setVisible(false, false);
}
mDrawable = d;
@@ -923,7 +924,8 @@
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 @@
}
}
- @RemotableViewMethod
@Override
- public void setVisibility(int visibility) {
- super.setVisibility(visibility);
+ public void onVisibilityAggregated(boolean isVisible) {
+ super.onVisibilityAggregated(isVisible);
if (mDrawable != null) {
- mDrawable.setVisible(visibility == VISIBLE, false);
- }
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- 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 ce94870..e9fa26c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -246,6 +246,8 @@
boolean mMirrorForRtl = false;
+ private boolean mAggregatedIsVisible;
+
private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>();
private AccessibilityEventSender mAccessibilityEventSender;
@@ -615,14 +617,13 @@
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 @@
}
@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 e971f86..8a1a8c5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6552,7 +6552,7 @@
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 @@
}
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 29190f9..f6fbaab 100644
--- a/core/java/com/android/internal/app/UnlaunchableAppActivity.java
+++ b/core/java/com/android/internal/app/UnlaunchableAppActivity.java
@@ -42,15 +42,13 @@
/**
* 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 @@
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 @@
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 90ee05e..f3ae688 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -854,7 +854,8 @@
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 @@
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 @@
// 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 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
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 c484121..8de9c09 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1953,7 +1953,7 @@
*/
@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 df48d6d..fbd8fb5 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2073,11 +2073,7 @@
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 623b603..c6db0ed 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -36,7 +36,7 @@
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 @@
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 798a6de..7ff38fd5 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -95,6 +95,7 @@
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 @@
* 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);
@@ -1252,7 +1253,7 @@
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),
@@ -1357,6 +1358,7 @@
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 fb9b1e5..4001283 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -73,6 +73,9 @@
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 7441acc..78975a4f 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 @@
{"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 0000000..da47c4c
--- /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 7314fbc..e17de17 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -78,11 +78,11 @@
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 @@
{"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 0000000..8724729
--- /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 3e4e352..1bc4285 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -200,7 +200,7 @@
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 @@
}
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 1eb0111..7496124 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -109,7 +109,8 @@
jfieldID mRule;
jfieldID mFormat;
jfieldID mRouteFlags;
- jfieldID mRegistrationId;
+ jfieldID mDeviceType;
+ jfieldID mDeviceAddress;
jfieldID mMixType;
jfieldID mCallbackFlags;
} gAudioMixFields;
@@ -388,7 +389,7 @@
}
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 @@
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 @@
{
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 @@
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 302cf63..024c21d 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -235,7 +235,7 @@
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 a9003c1..a7ac5b8 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 @@
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 @@
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 @@
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 b7701d6..14252dc 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -144,7 +144,7 @@
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 @@
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 @@
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/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index 6f3c4d42..c96e280 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 de4ccae..dfdb6b0 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 88e9367..50f5f76 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 84bc768..fcde691 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 3953264..3bc0ec3 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -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 5c73faf..be40fa8 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 b2633a9..40e9572 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 2042c4c..92bd3e7 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 f352620..ca7a80a 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 5482896..a737412 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 390dfd0..5b6a213 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 583a6b7..06861e7 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 b67402a..30188b5 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 8450189..1091495 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 ac7ad91..58d45ba 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 ac7ad91..58d45ba 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 ac7ad91..58d45ba 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 4623d77..225116f 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 65f5f24..5ce1711 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -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 c35d222..3ce50d9 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 bb83a9e..6c41c2c 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 eeab6d3..aba5e08 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 d45e0bd..e52d870 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 6fa6f49..acfd0a6 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 02ad9e6..d3bb5d0 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 cb0ac76..6a2b7f3 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 6270867..7595a88 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 82e1d83..3c33b38 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 cd23a1a..862ee60 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 ffa8d21..d6114fa 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 909a5c9..0b2fe57 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 14b7526..fca667a 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 e3278f3..dc41214 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 6f1c1ec..c43470b 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 c79befa..246140b 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/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-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 5c97295..1cd079b 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 15167f7..8ff6a09 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 6d31dd1..a0e987d 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>
@@ -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 e3e46b0..e586c78 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 7a41d4b..74aa801 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 b236d39..3c09cfb 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 3a30b55..d10a50f 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1138,7 +1138,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>
@@ -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 5ad1786..46cc85a 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 5496ada..0efdfca 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 59ffdc3..f5c5921 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 d0a7b20..1fbf363 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 829e06a..2fa6786 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 9414f4e..9956dbf 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 67351ea..40f7807 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 5c342f0..2154bda 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 e66cf66..4a934f0 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 6c2358b..79a5a86 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 40d13f0..db7cd01 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 b48fc33..c7c95e19 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 7ff2071..cbb2628 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 b68b45a..5eb6b56 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 cd0de0e..21f6665 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 dde0131..011ad4e 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 cd0de0e..21f6665 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 1c6e024..fe5139e 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 f134357..40c8551 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 9a6d3af..4f0c971 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 f4794a6..4630434 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 3e0cfaf..bf60752 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 bc8bd2b..8b78c76 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 d14c166..c68ec88 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 3eb4ae3..46b1bf6 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 04994d5..fa3d151 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 2cb08c9..57bde42 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 4fd8aad..d2381fc0 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 ae19150..58d3d91 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 fabecc3..1eedd01 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 981567d..d785cf4 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 af5652b..d4f2891 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 344797f..aba18b5 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 a58f5c2..47e6e88 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 f95a37d..88a417b 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -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 283198f..b67008e 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 8dfbaed..d9e5a14 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 c52d843..64de938 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 8ff0fed..756c52d 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 fe2c8a6..6ff550b 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 50c7bfb..a52c4e5 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5876,6 +5876,12 @@
</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/public.xml b/core/res/res/values/public.xml
index 2b0ef42..4e8740a 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 17afd92..5d083d7 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 a65a813..e636bc0 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -993,7 +993,7 @@
</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 @@
</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 32a01318..f01cce3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2508,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 5970a22..a361eda 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -223,6 +223,7 @@
<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 cf7978c..c02a01a 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/widget/SuggestionsPopupWindowTest.java b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
index 3d8fe69..a37abf1 100644
--- a/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
+++ b/core/tests/coretests/src/android/widget/SuggestionsPopupWindowTest.java
@@ -32,6 +32,8 @@
/**
* 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 844eadb..4a4727f 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -47,6 +47,8 @@
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 @@
.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/data/fonts/Android.mk b/data/fonts/Android.mk
index dc85046..fd28f64 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -105,4 +105,4 @@
.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 48ee6fa..683c157 100644
--- a/graphics/java/android/graphics/AvoidXfermode.java
+++ b/graphics/java/android/graphics/AvoidXfermode.java
@@ -19,6 +19,8 @@
/**
* 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 @@
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 d312454..3973f2f 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 @@
* @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 @@
* @see #isEmpty()
*/
public void setEmpty() {
- mPath = null;
- mRect = null;
+ mMode = MODE_EMPTY;
+ mPath.rewind();
+ mRect.setEmpty();
mRadius = RADIUS_UNDEFINED;
}
@@ -77,7 +98,7 @@
* @see #setEmpty()
*/
public boolean isEmpty() {
- return mRect == null && mPath == null;
+ return mMode == MODE_EMPTY;
}
@@ -90,7 +111,7 @@
* @see {@link android.view.View#setClipToOutline(boolean)}
*/
public boolean canClip() {
- return !isEmpty() && mRect != null;
+ return mMode != MODE_CONVEX_PATH;
}
/**
@@ -122,19 +143,9 @@
* @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 @@
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 @@
* 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 @@
}
/**
- * 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 @@
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 @@
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 @@
* 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 0080e65..27884e0 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 0cde0b9..93ef3f0 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -30,6 +30,11 @@
* 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 437ebaa..ae9ebc7 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -157,7 +157,7 @@
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
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 8417a40..d9c3a02 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -89,7 +89,7 @@
* @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;
@@ -759,7 +759,7 @@
* @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);
}
/**
@@ -874,7 +874,7 @@
/**
* @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) {
@@ -885,7 +885,7 @@
/**
* @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) {
@@ -1503,8 +1503,8 @@
// 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.
@@ -1602,8 +1602,8 @@
// 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.
@@ -1763,8 +1763,8 @@
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;
@@ -1833,10 +1833,10 @@
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) {
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index ae98c22..bd069ff 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -1281,8 +1281,10 @@
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> () {
{
@@ -1399,6 +1401,7 @@
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.
@@ -1474,10 +1477,11 @@
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
@@ -1645,7 +1649,7 @@
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 f6e3b50..ca07738 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -255,6 +255,7 @@
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 da5ecca..bb3ea3f 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -40,6 +40,16 @@
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 330dc29..eac9359 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -92,6 +92,8 @@
*/
bool init();
+ bool isInitialized() { return mInitialized; }
+
/**
* Flush the cache.
*
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index afe9807..f886dda 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -41,6 +41,10 @@
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 479796d..1654eb8 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -106,6 +106,8 @@
// 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 fd5856a..50b21a4 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -646,7 +646,9 @@
}
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/Layer.cpp b/libs/hwui/Layer.cpp
index 114347d..cdbbbab 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -197,7 +197,12 @@
}
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 c5af279..e6a95ff 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -349,8 +349,9 @@
}
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 f0c79d7..11eb825 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -356,11 +356,15 @@
}
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 2e3856f..d35f764 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -158,7 +158,8 @@
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 @@
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 @@
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 @@
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 @@
// 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 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 36a8aeb..4d2fed0 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -96,7 +96,7 @@
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 @@
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 @@
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 @@
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 @@
StrokeLineCap,
StrokeLineJoin,
StrokeMiterLimit,
+ FillType,
Count,
};
// Applies trimming to the specified path.
@@ -233,7 +235,7 @@
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 ffb0649..8689f98 100644
--- a/libs/hwui/debug/nullgles.cpp
+++ b/libs/hwui/debug/nullgles.cpp
@@ -133,6 +133,15 @@
}
}
+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 5f984b5..bb1a044 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -164,6 +164,9 @@
// 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 a496b49..c539d63 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -484,6 +484,8 @@
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 @@
#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 cb61e51..6706c30 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 @@
}
}
+ // 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 @@
void freePrefetechedLayers();
+ void waitOnFences();
+
EGLint mLastFrameWidth = 0;
EGLint mLastFrameHeight = 0;
@@ -213,6 +221,16 @@
// 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 09d4869..0572ee55 100755
--- a/libs/hwui/tests/scripts/prep_volantis.sh
+++ b/libs/hwui/tests/scripts/prep_volantis.sh
@@ -49,6 +49,6 @@
# 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 0000000..59bd75e
--- /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 f147fd4..31555f2 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -316,6 +316,61 @@
<< "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 949c541..454011f 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 0c6eb57..37a485e 100644
--- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
+++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp
@@ -103,9 +103,11 @@
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 @@
// 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 c3165bb..5e613fd 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -114,6 +114,23 @@
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 6cb23e5..0a7acb0 100644
--- a/libs/hwui/thread/Barrier.h
+++ b/libs/hwui/thread/Barrier.h
@@ -33,11 +33,6 @@
mCondition.signal(mType);
}
- void close() {
- Mutex::Autolock l(mLock);
- mOpened = false;
- }
-
void wait() const {
Mutex::Autolock l(mLock);
while (!mOpened) {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 69d4487..d179171 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -21,6 +21,7 @@
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 @@
* 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 @@
* 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.
@@ -1069,6 +1076,9 @@
* <p>
* This method has no effect if the device implements a fixed volume policy
* as indicated by {@link #isVolumeFixed()}.
+ * <p>From N onward, stream mute changes that would toggle Do Not Disturb are not allowed unless
+ * the app has been granted Do Not Disturb Access.
+ * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
* <p>
* This method was deprecated in API level 22. Prior to API level 22 this
* method had significantly different behavior and should be used carefully.
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 0f82cfc..ca306cc 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -228,7 +228,7 @@
/**
* Audio session ID
*/
- private int mSessionId = AudioSystem.AUDIO_SESSION_ALLOCATE;
+ private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
/**
* AudioAttributes
*/
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index c5d1120..e1dab09 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -295,7 +295,7 @@
/**
* 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 @@
int bufferSizeInBytes, int mode)
throws IllegalArgumentException {
this(streamType, sampleRateInHz, channelConfig, audioFormat,
- bufferSizeInBytes, mode, AudioSystem.AUDIO_SESSION_ALLOCATE);
+ bufferSizeInBytes, mode, AudioManager.AUDIO_SESSION_ID_GENERATE);
}
/**
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index ce12e76..1fc236a 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -824,7 +824,13 @@
}
// 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 @@
}
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
}
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 @@
// 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 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 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 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 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 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 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 @@
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 db0c5bb..2650ee0 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -1070,16 +1070,15 @@
* 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 @@
@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 @@
@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 @@
*/
@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 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 @@
@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/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 56d3c99..adeb834 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -36,30 +36,28 @@
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 @@
}
void setRegistration(String regId) {
- mRegistrationId = regId;
+ mDeviceAddress = regId;
}
/** @hide */
public String getRegistration() {
- return mRegistrationId;
+ return mDeviceAddress;
}
/** @hide */
@@ -185,7 +183,8 @@
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 @@
/**
* @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 @@
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 @@
}
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 @@
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 3af3ae7..cafa5a8 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -84,7 +84,7 @@
// 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 0b0306c..89e4577 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -19,6 +19,7 @@
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 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
public void setParentalControlsEnabled(boolean enabled) {
try {
mService.setParentalControlsEnabled(enabled, mUserId);
@@ -1292,6 +1294,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
public void addBlockedRating(@NonNull TvContentRating rating) {
Preconditions.checkNotNull(rating);
try {
@@ -1310,6 +1313,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS)
public void removeBlockedRating(@NonNull TvContentRating rating) {
Preconditions.checkNotNull(rating);
try {
@@ -1444,6 +1448,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
public List<TvInputHardwareInfo> getHardwareList() {
try {
return mService.getHardwareList();
@@ -1462,6 +1467,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
public Hardware acquireTvInputHardware(int deviceId, final HardwareCallback callback,
TvInputInfo info) {
try {
@@ -1488,6 +1494,7 @@
* @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 bc20c17..88be686 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -904,9 +904,7 @@
* 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 @@
* 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 d48ea21e..da1002d 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -200,16 +200,14 @@
}
/**
- * 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 9623076..6ca6193c 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -293,7 +293,7 @@
/**
* 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 @@
}
/**
- * 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 e9d62de..2fb1a3b 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -906,14 +906,16 @@
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 527e6c2..62685c9 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -307,6 +307,11 @@
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 @@
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 @@
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 fa69135..10efe18 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -351,7 +351,7 @@
priority,
effectCallback,
&lpJniStorage->mCallbackData,
- sessionId,
+ (audio_session_t) sessionId,
0);
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
@@ -819,7 +819,7 @@
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 3d3adba..f1a8c6f 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -388,7 +388,7 @@
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 76c701a..5cfe300 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -105,6 +105,14 @@
/*****************************************************************************/
+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/app-perf-tests/Android.mk b/packages/DocumentsUI/app-perf-tests/Android.mk
new file mode 100644
index 0000000..3f12906
--- /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 0000000..1c3ed80
--- /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 0000000..d6e8a96
--- /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 0000000..21fc52e
--- /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 0000000..bfb0271
--- /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 6fff804..17e2c31 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 c61db57..0cb68de 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 dcfef2a..4a30257 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 e1505f8..b432680 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 b884a19..3e36503 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 94c34bd..a1ac5c9 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 2159044..7b88194 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 f366ce8..9daa80a 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 5af86b1..b7d887e 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 4e8b440..d58615d 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 ee5ba49..99338f6 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 a42e955..373b0582 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 e6839de..539a7c6 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 8b46660..1693bdb 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 8b46660..1693bdb 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 8b46660..1693bdb 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 8fd8381..8ad0439 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 81fc59abb..c3a4648 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 7cf134e..76f1ef7 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 23e4079..ea77657 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 6aa5626..4c2a342 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 8be6d61..a586f7c 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 0a33570..cb3a123 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 478ea46..0cbc141 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 c933faa..1f8ecad 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 e9fda19..7fc21b6 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 489bb98..87dfb5f 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 51b8673..f86877e6 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 b7e74e0..14662ad 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 4dbae9d..ecd7669 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 73ed8bc..b27674e 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 75831ed..f351cb8 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 cfd5611..3eb14c0 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 7d4cb9e9..3b0aef8 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 9618d36..23b7ab6 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 ac8d267..fc36bdb 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 759506b..101392d 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 d83c1d3..2ee35fe 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 57ddd0b..b74d6a20 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 907802d..3c2da97 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 699e76a..865e717 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 468853b..4f4a375 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 a6297be..fa653fc 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 1a9b77c0..8fd73e4 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 5bbf8c5..12455da 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 264d196..0c0420d 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 02c818b..2af8556 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 6fae578..6256a99 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 6f7c525..df896a2 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 9fb7f84..14193b2 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 0e48f0f..7d37078 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 cc70c91..5a06cd2 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 ebddf54..0e022af 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 a8c65e7..4cfe638 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 e888fd7..b10d8a2 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 213e76a..26ec421 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 2c74e67..490c4d7 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 213e76a..26ec421 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 e57d1ab..ef34f3a 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 9c0f031..b94b2a5 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 a34aa88..a0d764e 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 1133815..06b7a10 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 f2c691d..ee7bdc9 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 80ae000..352da58 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 be96db6..0ba3da1 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 7fd4be0..081c331 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 2730ce9..fc4d555 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 881e05a..30bdc9d 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 0043ddc..c11840a 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 8b24210..aba869c 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 9849b85..a76a306 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 8df52d2..f5e6258 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 d5a1fcd..9c4b054 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 846555a..2d4804c 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 0e1ac5a..0a09921 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 c3c16f4..9aca29f 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 7f479ff..75dcfbc 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 f22e27e..b834a11 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 a5ede47..d6e270a 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 b99ab8c..35864a7 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 e2d1870..e7406e68 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 21bdfd9..a548d89 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 1a8ce18..fe61094 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.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 @@
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 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 @@
}
}
+ /**
+ * 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 @@
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/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index c7c61c3..8c4859f 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 @@
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 afd308c..deef1c2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -411,11 +411,15 @@
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 @@
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 dc529ce..2b6f396 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.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.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.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 @@
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 @@
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 @@
// 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 @@
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 @@
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 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 @@
}
@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 @@
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 @@
.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/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 26900a7..c32bbff 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -86,11 +86,10 @@
*/
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 @@
/**
* 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 @@
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 bfc8d71..63a834f 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.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 @@
private String mQuery = null;
private Selection mSelection = null;
private boolean mSearchMode = false;
+ private @Nullable ActionMode mActionMode;
@Override
public View onCreateView(
@@ -406,9 +406,9 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
}.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 @@
// 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 @@
}
// 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 5edda38..450341f 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 @@
/**
* 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 0ee7623..ea1deb4 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 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 @@
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 @@
@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 @@
@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 90b2341..ce5bcb1 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 @@
}
@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 c8641a8..c4f6f11 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 @@
}
@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 @@
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 3a1be11..ace53e0 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 @@
}
@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 ab4f5c4..c5ee592 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 @@
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 @@
/**
* 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 @@
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 @@
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 @@
* 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 @@
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 @@
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 149ecdd..ca3b2e2 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.view.ViewGroup;
import com.android.documentsui.State;
-
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -103,7 +102,7 @@
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 @@
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 b0cc09a..b80486d 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 Selection createFromParcel(Parcel in, ClassLoader loader) {
return new Selection(
in.readString(),
- (ArrayList<String>) in.readArrayList(loader));
+ in.readArrayList(loader));
}
@Override
@@ -931,7 +931,6 @@
Rect getAbsoluteRectForChildViewAt(int index);
int getAdapterPositionAt(int index);
int getColumnCount();
- int getRowCount();
int getChildCount();
int getVisibleChildCount();
/**
@@ -1008,13 +1007,6 @@
}
@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 @@
}
mCurrentPosition = input.getOrigin();
+ mModel.resizeSelection(input.getOrigin());
scrollViewIfNecessary();
resizeBandSelectRectangle();
}
@@ -1549,11 +1542,7 @@
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 @@
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 d5327f91..31ce837 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 @@
summary = null;
size = -1;
icon = 0;
-
derivedUri = null;
}
@@ -210,6 +209,7 @@
+ ", isContainer=" + isContainer()
+ ", isDirectory=" + isDirectory()
+ ", isArchive=" + isArchive()
+ + ", isPartial=" + isPartial()
+ ", isVirtualDocument=" + isVirtualDocument()
+ ", isDeleteSupported=" + isDeleteSupported()
+ ", isCreateSupported=" + isCreateSupported()
@@ -249,6 +249,10 @@
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/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
index 59dc232..e4afc3d 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 @@
// 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 @@
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 353d4bd..0c0e0b7 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 com.android.documentsui.dirlist.MultiSelectManager.GridModel;
import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
@SmallTest
@@ -42,6 +43,17 @@
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 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 @@
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 @@
@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 @@
}
@Override
- public int getRowCount() {
- return mNumRows;
- }
-
- @Override
public void showBand(Rect rect) {
throw new UnsupportedOperationException();
}
@@ -328,5 +442,19 @@
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 8e624a0..56e54a6 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 @@
}
@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
similarity index 83%
rename from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
rename to packages/MtpDocumentsProvider/src/com/android/mtp/BusyDeviceException.java
index 55f55b0..83488cd 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/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index d4d4591..68c1992 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.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.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;
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 @@
// 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 @@
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.");
}
- 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]);
+ 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 MtpObjectInfo infoWithHandle =
new MtpObjectInfo.Builder(info).setObjectHandle(objectHandle).build();
final String documentId = mDatabase.putNewDocument(
@@ -342,9 +388,12 @@
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 @@
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 @@
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 0202343..6fb2a78 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.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 @@
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 2f66c5c..2e9133b 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.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
final class RootScanner {
/**
@@ -95,15 +96,19 @@
* 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 @@
}
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/exceptions/BusyDeviceException.java b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
similarity index 75%
copy from packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
copy to packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.java
index 55f55b0..db7d777 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/exceptions/BusyDeviceException.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/SendObjectInfoFailure.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.
+ * Exception thrown when sendObjectInfo failed.
*/
-public class BusyDeviceException extends IOException {
+class SendObjectInfoFailure extends IOException {
+ SendObjectInfoFailure() {
+ super("Failed to MtpDevice#sendObjectInfo.");
+ }
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index d6ad0f3..9c1880a 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.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 @@
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 cdddd81..a08d9ee 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 @@
@Override
protected void tearDown() throws Exception {
assertTrue(mPipeManager.close());
+ mDatabase.close();
}
public void testReadDocument_basic() throws Exception {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index 606f4eb7..645e182 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.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 @@
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 a408c08..92374cb 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 7ae97e2..386d697 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 eb76e1f..2c8eda0 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 9903397..d62f472 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 f570d09..eb050de 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 72652c9..7640ffd 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 b863773..a1063b9 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 542c3ce..7a87fda 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 e2c4495..0249282 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 f713ceb..86f269d 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 d1d7b23..720aeba 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 fbd1207..ec8407b 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 dce2cf7..7db5853 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 4821a71..2834031 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 4821a71..2834031 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 4821a71..2834031 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 2d0ce02..5f7a447 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 8dcf6ab..0314f2e 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 62dd7ab..6420ccc 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 cb6f0b4..30bab3c 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 e7cbd1e..f1437d7 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 bb3ad97..9717a78 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 1f12f18..80181f0 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 3dc2a6a..b8ff857 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 3715919..2cde752 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 c77aeb6..9c25a0f 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 e8a47cb..2e1b337 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 320ebc1..f9dd6b7 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 4ea4528..94fa1bd 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 046ea48..e9232f5 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 02c747a..3971398 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 17a2f08..7f9e768 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 9c75939..147ad4d 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 429ce61..4fce9b8 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 6c42110..b2b3612 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 6dba53b..8c34c63 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 36843fd..47d3458 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 9985a1e..3f2c6c3 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 8ca9807..009b9f7 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 31e0378..4bfdbfd 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 fd2d905..d06aec5 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 605f476..c5121a5 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 253eeb3..dd1ccc8 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 3323cd9..009ccf6 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 41c8600..0c2ddf4 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 80cf43e..3b4acd2 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 5e7ea15..4473f7f 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 7a3d76d..d8075aa 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 3f29687..44ed1f6 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 71862a3..bf2ea80 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 2ad14dc..94993d4 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 6c8dc59..8d25315 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 7f9df25..c60e9df 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 10d57f4..3771536 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 3e89094..cd4cc83 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 c772ded..64a97b9 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 2b3dcc7..b648589 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 c772ded..64a97b9 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 0322f55..b0c5064 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 7548ace..4aa4c10 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 f3d6dc3..b5053dd 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 712c348..852bd9e 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 2f23144..830399f 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 853dd2f..10b9134 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 094a405..51b2b10 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 e12d394..c19f7f4 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 d5a9d1b..091a447 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 5c7732f..105b980 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 a74fc82..91ee5fa 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 53caea5..b5ec3d9 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 0c1f167..d3bcc5f 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 230da22..a8f2620 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 01cedc6..d094ef7 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 878ff0c..27046dc 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 d81a041..031f8f7 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 2b4bddd..f3fb96a 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 48f03b7..348a319 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 38656e5..6adabc9 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 af83365..f4aade0 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 16841d3..268cdb2 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 e4c2cbc..1aee490 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 47023c1..d0aba22 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -146,12 +146,13 @@
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 fa2226d..74c1ebd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -151,10 +151,17 @@
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 7a1c741..ce69c5a 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 @@
}
@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 987b5ea..743912a 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 @@
@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 b6b8d6b..bb3084f 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-es/strings.xml b/packages/Shell/res/values-es/strings.xml
index 68abf83..730ae73 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-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml
index e462cee..d4610977b 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-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index d7d62e2..5c4b8d3 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-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml
index 9c2e4e7..90028ca 100644
--- a/packages/Shell/res/values-kk-rKZ/strings.xml
+++ b/packages/Shell/res/values-kk-rKZ/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-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml
index e4039fe..16a9549 100644
--- a/packages/Shell/res/values-ky-rKG/strings.xml
+++ b/packages/Shell/res/values-ky-rKG/strings.xml
@@ -19,7 +19,7 @@
<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>
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index e758745..46bc1a9 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -24,8 +24,8 @@
<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>
- <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ketik untuk berkongsi laporan pepijat anda tanpa tangkapan skrin atau tunggu sehingga 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 sehingga tangkapan skrin selesai"</string>
+ <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-ne-rNP/strings.xml b/packages/Shell/res/values-ne-rNP/strings.xml
index 9fb1bcb..906d824 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-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index fa17326..7a78c43 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-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml
index c1a1948..dd7f41b 100644
--- a/packages/Shell/res/values-uz-rUZ/strings.xml
+++ b/packages/Shell/res/values-uz-rUZ/strings.xml
@@ -24,8 +24,8 @@
<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>
- <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Xatoliklar hisobotini darhol yuborish uchun bosing yoki skrinshot saqlanguncha kuting"</string>
- <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Xatoliklar hisobotini darhol yuborish uchun bosing yoki skrinshot saqlanguncha kuting"</string>
+ <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/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 10c5416..7fae0ee 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -454,21 +454,15 @@
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 @@
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 @@
*/
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 @@
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 @@
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 9afa900..cbd17bf 100644
--- a/packages/Shell/src/com/android/shell/BugreportReceiver.java
+++ b/packages/Shell/src/com/android/shell/BugreportReceiver.java
@@ -51,6 +51,7 @@
@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 47e3b3b..17f6f6b 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 @@
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 @@
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 0000000..5506de1
--- /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 df46271..c062b6d 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 b2c0331..53d9cc5 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/tv_pip_onboarding.xml b/packages/SystemUI/res/layout/tv_pip_onboarding.xml
index f031bb4..b0814cf 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 40c6fa1..1ba423b 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 7d85ef6..090b8e6 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -221,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 adc1306..f595479 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_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index 544ae07..95e480c 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/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-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 100bc63..4a4e004 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -225,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 99c413cf..a54e0ab 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_tv.xml b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
index 6751bc9..b3ac6d4 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Göstərin"</string>
<string name="pip_pause" msgid="8412075640017218862">"Fasilə verin"</string>
<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="2627737116380318292">"PIP idarə etmək üçün Əsas səhifə\n düyməsini basıb 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 1198950..fff464d 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -74,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 39a858c..d78f8d3 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_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index 38c10ab..c5230a4 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/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\nнатиснете и задръжте HOME"</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_tv.xml b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
index 7a95815..6bb19f5 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 3befd44..0b72a06 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -74,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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
index 1719318..dd4a518 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings_tv.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings_tv.xml
@@ -27,6 +27,6 @@
<!-- 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="2627737116380318292">"Za kontrolu PIP \n držite dugme POČETAK"</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 42596fe..6ddec67 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 1aed2b4..3634b99 100644
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -23,7 +23,7 @@
<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>
- <string name="pip_hold_home" msgid="340086535668778109">"Prem "<b>"INICI"</b>" per contr. PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Mantén premut botó INICI\n per controlar PIP"</string>
+ <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 3867673..e23f53f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -75,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -224,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 2480c37..b65b08e 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Přehrát"</string>
<string name="pip_pause" msgid="8412075640017218862">"Pozastavit"</string>
<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="2627737116380318292">"Funkci PIP lze ovládat\npodržením tlačítka PLOCHA"</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 0356a18..ba8898e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 10a1ecd..b51c5df 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 7e7b2ac..345dbed 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 aa1a9b2..b96669b 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 943c67d..78cbb20 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -221,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 c96f852..e72d579 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_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index 6f33655..5711c352 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_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index 6f33655..5711c352 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_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index 6f33655..5711c352 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 e60fd2e..4769e20 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 1df219d..99913e6 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Reproducir"</string>
<string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Mantén presionado "<b>"INICIO"</b>" para controlar PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Mantén presionado botón\nINICIO 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 e387019..e89125e 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 fcc839e..200410c 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 7e68757..cad44d9b 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 ae6cb30..972083b 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 6a358d4..1dc6d68 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 80feff6..a312ea4 100644
--- a/packages/SystemUI/res/values-eu-rES/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Erreproduzitu"</string>
<string name="pip_pause" msgid="8412075640017218862">"Pausatu"</string>
<string name="pip_hold_home" msgid="340086535668778109"><b>"HASIERA"</b>" PIP kontrolatzeko"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Eduki sakatuta HASIERA\nPIPa 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 2477a12..dfe1d54 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
index 5130b50..cf37db1 100644
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ b/packages/SystemUI/res/values-fa/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 دکمه صفحه\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-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 6199536..e5d513f 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 a42c231..94c7806 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Toista"</string>
<string name="pip_pause" msgid="8412075640017218862">"Keskeytä"</string>
<string name="pip_hold_home" msgid="340086535668778109">"PIP: paina pitkään "<b>"aloituspain"</b>"."</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Hallinnoi PIP:tä: paina\naloitusnäyttöpainiketta pitkään."</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 6ed42ed..223274f5 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 29e94c6..48bbb26 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -24,6 +24,7 @@
<string name="pip_play" msgid="674145557658227044">"Lecture"</string>
<string name="pip_pause" msgid="8412075640017218862">"Interrompre"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Maint. enf. "<b>"ACC."</b>" pr gér. mode IDI"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Maint. enf. \nACCUEIL 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 c08958d..474a240 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 8504a8e..27c62fb 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Lire"</string>
<string name="pip_pause" msgid="8412075640017218862">"Suspendre"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Appui long "<b>"ACCUEIL"</b>" pour contrôler PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Appui long bouton ACCUEIL\npour 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 7cb3cb1..a675c21 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 6aab613..b0343e1 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_tv.xml b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
index 56f0298..3f2f68a 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 7618c02..43331fd 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 c4bb26b..cf259dd 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_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
index 2a72055..424c68b 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_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
index ff4d37c..5271a4a 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 bf9f80d..6338d8e 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 0ddb715..280d733 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
+++ b/packages/SystemUI/res/values-hy-rAM/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-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index f631513..c12fa9c 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 6b4f191..57756e0 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 b44aaf0..9c3db2f 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 6fc814a..b4f473a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 08f2b67..dc79802 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 2eda0e4..2ace8e8 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -75,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 74297e4..77deaf6 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_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index be6693b..e045fd6 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/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-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 41da191..14f9406 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 97944c3..e525eba 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
+++ b/packages/SystemUI/res/values-ka-rGE/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-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index bc56c8e..07c95c8 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -221,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 f67157c..e7e7bfd 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/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>"HOME"</b>" түй. ұс. тұр."</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP бас. үшін HOME\n түй. бас., ұс. тұр."</string>
+ <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_tv.xml b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
index cc0a8b0..2d40468 100644
--- a/packages/SystemUI/res/values-km-rKH/strings_tv.xml
+++ b/packages/SystemUI/res/values-km-rKH/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">"សង្កត់ប៊ូតុង "<b>"ដើម"</b>" ដើម្បីគ្រប់គ្រង PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"ចុច និងសង្កត់ប៊ូតុង ដើម\nដើម្បីគ្រប់គ្រង 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 62a1235..11d239c 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 09d7b07..5ed7705 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 fca1dba..30d4216 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 ea12d5e..2846e55 100644
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ b/packages/SystemUI/res/values-ko/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"><b>"HOME"</b>"을 눌러 PIP 제어"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"HOME\n버튼을 길게 눌러 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 8894820..653dded 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 e95bc89..2da47ea 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
+++ b/packages/SystemUI/res/values-ky-rKG/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"><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_tv.xml b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
index f6bc833..e4116f8 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
+++ b/packages/SystemUI/res/values-lo-rLA/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">"ກົດ "<b>"HOME"</b>" ຄ້າງໄວ້ເພື່ອຄວບຄຸມ PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"ກົດປຸ່ມ HOME\nຄ້າງໄວ້ເພື່ອຄວບຄຸມ 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 4299efa..3c7af5c 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -75,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 140b55d..8c60970 100644
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Leisti"</string>
<string name="pip_pause" msgid="8412075640017218862">"Pristabdyti"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Kad vald. PIP, pal. pasp. m. "<b>"PAGRINDINIS"</b></string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Kad vald. PIP, pal.\npasp. m. PAGRINDINIS"</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 ad00ad0..bafad80 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -74,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 d7ca370..397376a 100644
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Atskaņot"</string>
<string name="pip_pause" msgid="8412075640017218862">"Apturēt"</string>
<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="2627737116380318292">"Nospiediet un turiet pogu SĀKUMS,\n 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 4116b6f..4902006 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 5f88cb5..acb04be 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
+++ b/packages/SystemUI/res/values-mk-rMK/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">"Задржете "<b>"ДОМА"</b>" за кон. PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Притиснете и задржете го копчето\nДОМА за контролирање 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 f861a00..9bbc3ad 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 0094bb6..3d6250d 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-ml-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-mn-rMN/strings_tv.xml b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
index 78b7cc8..334a9f1 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn-rMN/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-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index a3cb736..a37365c 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 fd76c53..2f56b0a 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 75fdf62..e2175e5 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 5fc98b9..83dee5a 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
@@ -24,6 +24,7 @@
<string name="pip_play" msgid="674145557658227044">"Main"</string>
<string name="pip_pause" msgid="8412075640017218862">"Jeda"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Thn "<b>"SKRN UTMA"</b>" utk kwl PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Tkn & thn butang SKRIN UTAMA\nutk mengawal 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 d7597a5..d6362f3 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -221,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 8491e37..616acda 100644
--- a/packages/SystemUI/res/values-my-rMM/strings_tv.xml
+++ b/packages/SystemUI/res/values-my-rMM/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-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 5b0c6eb..a2b09c5 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 8574d66..921744e 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_tv.xml b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
index 68c86ca..adfb443 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_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index c116f81..8ccf464 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_tv.xml b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
index 1bf28af..fafcd62 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 8a1fff6..5a4a320 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -75,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 b804146..d0371b0 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 1cf0ed9..089fa75 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 21d36e0..36ba02d 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
<string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Mantenha "<b>"INÍCIO"</b>" pressionado para controlar o PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Mantenha o botão INÍCIO\npressionado 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 520abc4..1660670 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -221,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 8b1b032..b588c7b 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 1cf0ed9..089fa75 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 21d36e0..36ba02d 100644
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Reproduzir"</string>
<string name="pip_pause" msgid="8412075640017218862">"Pausar"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Mantenha "<b>"INÍCIO"</b>" pressionado para controlar o PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Mantenha o botão INÍCIO\npressionado 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 113f2bc..b7e0834 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -74,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 e30b2f9..0af2b39 100644
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Redați"</string>
<string name="pip_pause" msgid="8412075640017218862">"Întrerupeți"</string>
<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="2627737116380318292">"Apăsați lung ACASĂ\npentru 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 c131284..f73ebf4 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -75,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 f25b460..30f55cb 100644
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ b/packages/SystemUI/res/values-ru/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></string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Управляйте кадром в кадре,\nудерживая кнопку \"ГЛАВНАЯ\""</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_tv.xml b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
index b2c6485..70884b0 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 26d6d2f..edae154 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -75,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
index 46f88f9..98a67f8 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_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
index e1d1604..20de9c5 100644
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Predvajanje"</string>
<string name="pip_pause" msgid="8412075640017218862">"Zaustavitev"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Pridr. "<b>"HOME"</b>" za up. n. PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Pridržite gumb HOME\nza upravljanje načina 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 b3e6ea8..f657fb4 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 28bfbb5..481662f 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
@@ -24,6 +24,6 @@
<string name="pip_play" msgid="674145557658227044">"Luaj"</string>
<string name="pip_pause" msgid="8412075640017218862">"Pauzë"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Mbaj shtypur "<b>"HOME"</b>" për të kontrolluar PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Shtyp dhe mbaj shtypur butonin HOME\npë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 9c26ebd..52d52e0 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -74,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 4b03b68..eed8f51 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 0fb5731..1c72fa9 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 dc65877..2b2c5c2 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 a716281..5fe6375 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 9b3799a..337c136 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 59fe9dd..570aeae 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 d4d661a..b92af22 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 c7f9b42..f0e5c60 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 4c18743..7ce24cb 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_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
index f1c24ec..abc1a87c 100644
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ b/packages/SystemUI/res/values-th/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">"กด "<b>"HOME"</b>" ค้างไว้เพื่อควบคุม PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"กดปุ่ม HOME ค้างไว้\nเพื่อควบคุม 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_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
index 85a4f5b..e6aad60 100644
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -24,6 +24,7 @@
<string name="pip_play" msgid="674145557658227044">"I-play"</string>
<string name="pip_pause" msgid="8412075640017218862">"I-pause"</string>
<string name="pip_hold_home" msgid="340086535668778109">"I-hold ang "<b>"HOME"</b>" para makontrol ang PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"I-hold ang button na HOME\nupang 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 12be4c3..039a63f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 ea136b1..c6da011 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -24,6 +24,7 @@
<string name="pip_play" msgid="674145557658227044">"Oynat"</string>
<string name="pip_pause" msgid="8412075640017218862">"Duraklat"</string>
<string name="pip_hold_home" msgid="340086535668778109">"PIP\'yi kontrol etmek için "<b>"ANA EKRAN"</b>"\'ı basılı tutun"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"PIP\'yi kontrol etmek için\nANA EKRAN düğmesini 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 e7721f1..e2ca5c5 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -75,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 22bcf52..dcb7a52 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 dd76828..866350c 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 4929f81..4216e9e 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
+++ b/packages/SystemUI/res/values-ur-rPK/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-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 21400b3..fb9a9e2 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 d6ffb67..d9db7d2 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/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">"PIP’ni yopish"</string>
+ <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>
- <string name="pip_hold_home" msgid="340086535668778109"><b>"BOSHIGA"</b>" tugmasini bosib turib, PIP’ni boshqaring"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"BOSHIGA tugmasini bosib turib,\nPIP’ni boshqaring"</string>
+ <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 8f947af..7427bda 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -221,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 48ba444..727dcb8 100644
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -24,6 +24,7 @@
<string name="pip_play" msgid="674145557658227044">"Phát"</string>
<string name="pip_pause" msgid="8412075640017218862">"Tạm dừng"</string>
<string name="pip_hold_home" msgid="340086535668778109">"Giữ "<b>"HOME"</b>" để đ.khiển PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"Nhấn và giữ nút HOME\nđể điều 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_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
index 860df35..87b62a0 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -19,11 +19,12 @@
<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">"关闭 PIP"</string>
+ <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>
- <string name="pip_hold_home" msgid="340086535668778109">"按住"<b>"主屏幕"</b>"即可控制 PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"按住主屏幕\n按钮即可控制 PIP"</string>
+ <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 c7b2fff..602089e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -221,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-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index 8e5a2df..e419aa1 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/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">"按住"<b>"主按鈕"</b>"即可控制 PIP"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"按住主按鈕\n即可控制 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 636f2fb..189f404d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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 60edac2..94a83b9 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rTW/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">"按住「主畫面」"<b></b>"按鈕即可控制子母畫面"</string>
- <string name="pip_onboarding_description" msgid="2627737116380318292">"按住「主畫面」按鈕\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-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 8d2a51b..60c4479 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -73,8 +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>
- <!-- no translation found for screenshot_failed_to_save_unknown_text (7887826345701753830) -->
- <skip />
+ <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>
@@ -222,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 b901f90..b010556 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 d65ab04..eeed0cf 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/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8af413c..5295ccb 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 b35038d..0e1fe8f 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 2660926..b0c1e95 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/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index ddc03a3..a130cf9 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 358674c..aa3f6e5 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -535,31 +535,43 @@
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 937f7d3..0d822cb 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 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 312d3c5..02b860c 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 @@
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 @@
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 @@
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 88b6caa..815c679 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -89,6 +89,7 @@
public void setHost(QSTileHost qsh) {
qsh.addCallback(this);
+ updateAnimators();
}
@Override
@@ -133,6 +134,7 @@
TouchAnimator.Builder translationYBuilder = 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];
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index d0e034b..ab90179 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 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 @@
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 72a59d7..aeca840 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 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 d9b3b3f..57db3a6 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.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 @@
@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 @@
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 473956f..f33ef65 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.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 @@
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 @@
}
@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 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 6feda81..40bf6d3 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 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 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 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 @@
* @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/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 5e1af12..ee4d95e 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 @@
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 @@
// 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 @@
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 d433b6c0..748d8ed 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 @@
*/
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 @@
/** 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/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 8342de5..9235673 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 @@
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 @@
}
});
}
- 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 @@
if (stack.getTaskCount() > 0) {
hideEmptyView();
} else {
- showEmptyView();
+ showEmptyView(R.string.recents_empty_message);
}
}
@@ -327,11 +327,12 @@
/**
* 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 @@
// 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 @@
// 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 6c410c3..93b5b6c 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.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 @@
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 @@
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 ad46abd..9be3542 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 @@
/** 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 @@
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 143f160..8f1517d 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.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.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 @@
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 @@
"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 @@
private UserManager mUserManager;
private int mDensity;
+ private KeyguardManager mKeyguardManager;
+ private LockPatternUtils mLockPatternUtils;
+
// UI-specific methods
/**
@@ -499,6 +508,20 @@
);
}
+ } 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 @@
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 @@
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 @@
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);
@@ -1680,7 +1708,6 @@
ActivityManagerNative.getDefault().resumeAppSwitches();
} catch (RemoteException e) {
}
-
try {
intent.send();
} catch (PendingIntent.CanceledException e) {
@@ -1773,8 +1800,22 @@
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) {
@@ -1809,6 +1850,23 @@
}, 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) {
@@ -1856,15 +1914,16 @@
/**
* 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/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index e53f044..99896f8 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.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.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 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 @@
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 @@
mShowMenu = false;
mGestureHelper = new NavigationBarGestureHelper(context);
+ mDensity = context.getResources().getConfiguration().densityDpi;
getIcons(context);
mBarTransitions = new NavigationBarTransitions(this);
@@ -599,6 +598,10 @@
// 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 906bd0f..bf58611 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 @@
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 @@
// 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/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 2ba1562..117e2b3 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 @@
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 77ece93..ada7450 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 @@
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 @@
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 @@
pw.println(mCurrentState);
}
+ public boolean isShowingWallpaper() {
+ return !mCurrentState.backdropShowing;
+ }
+
private static class State {
boolean keyguardShowing;
boolean keyguardOccluded;
@@ -338,6 +351,7 @@
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 f03d9e9..c6b1cdf 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 @@
@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 @@
}
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 d9b78a2..59ec6112 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2691,6 +2691,16 @@
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 d36a1d7..d929519 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -1996,6 +1996,22 @@
// 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 4e667c6..e0f5934 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -2071,6 +2071,8 @@
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/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 3659a40..a4f85db 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 @@
private final UserManager mUserManager;
private final AppOpsManager mAppOpsManager;
private final KeyguardManager mKeyguardManager;
+ private final DevicePolicyManagerInternal mDevicePolicyManagerInternal;
private final SecurityPolicy mSecurityPolicy;
@@ -232,6 +233,7 @@
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 @@
}
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 @@
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 @@
}
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 aaa2211..99c5dd6 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -7,7 +7,8 @@
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 bfe9e8e..a94c8b8 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -121,6 +121,8 @@
* - 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 @@
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 @@
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 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 @@
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 @@
@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 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 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 @@
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 @@
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 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 @@
@Override
public int permissionToOpCode(String permission) {
+ if (permission == null) {
+ return AppOpsManager.OP_NONE;
+ }
return AppOpsManager.permissionToOpCode(permission);
}
@@ -1163,15 +1202,6 @@
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 @@
}
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 @@
}
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 @@
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 @@
@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 @@
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 @@
exceptions.clear();
}
- exceptions.addAll(Arrays.asList(exceptionPackages));
+ for (String p : exceptionPackages) {
+ exceptions.add(p);
+ }
+ } else {
+ opExceptions.remove(code);
}
}
@@ -2219,14 +2256,23 @@
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 @@
}
}
+ 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/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 3c13577..b7fca1a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1784,6 +1784,38 @@
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 @@
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));
- }
+ dumpNetworkDiagnostics(pw);
+ return;
+ }
- for (NetworkDiagnostics netDiag : netDiags) {
- pw.println();
- netDiag.waitForMeasurements();
- netDiag.dump(pw);
- }
-
+ if (argsContain(args, "apf")) {
+ dumpApf(pw);
return;
}
@@ -1878,6 +1900,9 @@
pw.println();
mKeepaliveTracker.dump(pw);
+ pw.println();
+ dumpApf(pw);
+
if (mInetLog != null && mInetLog.size() > 0) {
pw.println();
pw.println("Inet condition reports:");
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 0000000..1b85632
--- /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 9b8f2d2..00a49bd 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -456,6 +456,7 @@
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 329f716..07c10b0 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.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 @@
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 @@
private final Handler mFgHandler;
private final Handler mDaemonHandler;
+ private INetd mNetdService;
+
private IBatteryStats mBatteryStats;
private final Thread mThread;
@@ -306,7 +309,7 @@
}
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 @@
* 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 306e933..3eb20a0 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -28,6 +28,7 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
}
- 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 @@
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 11888ff..4198af9 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -67,7 +67,8 @@
"/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/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index f99d035..6361db5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6497,15 +6497,13 @@
}
@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();
@@ -6915,6 +6913,14 @@
}
}
+ // 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;
@@ -11198,7 +11204,6 @@
}
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 09542cb..26eaa8a 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 @@
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 e4b4c2d..13d90e3 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.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.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 @@
(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 83ad2a7..fa62c98 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 @@
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 d2aa966..39fbeb5 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_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 d919737..5320221 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.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.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.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 @@
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 @@
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 @@
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 @@
// array initialized by updateStreamVolumeAlias()
updateStreamVolumeAlias(false /*updateVolumes*/, TAG);
readPersistedSettings();
+ readUserRestrictions();
mSettingsObserver = new SettingsObserver();
createStreamStates();
@@ -751,6 +750,8 @@
}
}
+ mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+
sendMsg(mAudioHandler,
MSG_CONFIGURE_SAFE_MEDIA_VOLUME_FORCED,
SENDMSG_REPLACE,
@@ -1109,35 +1110,6 @@
System.MUTE_STREAMS_AFFECTED, AudioSystem.DEFAULT_MUTE_STREAMS_AFFECTED,
UserHandle.USER_CURRENT);
- 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(
- currentUser, UserManager.DISALLOW_ADJUST_VOLUME);
- if (mUseFixedVolume) {
- masterMute = false;
- AudioSystem.setMasterVolume(1.0f);
- }
- if (DEBUG_VOL) {
- Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
- }
- setSystemAudioMute(masterMute);
- 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);
- 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
@@ -1154,6 +1126,31 @@
mVolumeController.loadSettings(cr);
}
+ private void readUserRestrictions() {
+ final int currentUser = getCurrentUserId();
+
+ // Check the current user restriction.
+ boolean masterMute = mUserManagerInternal.getUserRestriction(
+ currentUser, UserManager.DISALLOW_ADJUST_VOLUME);
+ if (mUseFixedVolume) {
+ masterMute = false;
+ AudioSystem.setMasterVolume(1.0f);
+ }
+ if (DEBUG_VOL) {
+ Log.d(TAG, String.format("Master mute %s, user=%d", masterMute, currentUser));
+ }
+ setSystemAudioMute(masterMute);
+ AudioSystem.setMasterMute(masterMute);
+ broadcastMasterMuteStatus(masterMute);
+
+ 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);
+ }
+
private int rescaleIndex(int index, int srcStream, int dstStream) {
return (index * mStreamStates[dstStream].getMaxIndex() + mStreamStates[srcStream].getMaxIndex() / 2) / mStreamStates[srcStream].getMaxIndex();
}
@@ -1293,7 +1290,7 @@
// Check if the ringer mode handles this adjustment. If it does we don't
// need to adjust the volume further.
final int result = checkForRingerModeChange(aliasIndex, direction, step,
- streamState.mIsMuted);
+ streamState.mIsMuted, caller);
adjustVolume = (result & FLAG_ADJUST_VOLUME) != 0;
// If suppressing a volume adjustment in silent mode, display the UI hint
if ((result & AudioManager.FLAG_SHOW_SILENT_HINT) != 0) {
@@ -1309,7 +1306,6 @@
&& (mRingerModeMutedStreams & (1 << AudioSystem.STREAM_MUSIC)) != 0) {
adjustVolume = false;
}
-
int oldIndex = mStreamStates[streamType].getIndex(device);
if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
@@ -1453,10 +1449,7 @@
}
};
- 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 @@
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 @@
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 @@
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 @@
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 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 @@
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();
@@ -3328,7 +3361,8 @@
* adjusting volume. If so, this will set the proper ringer mode and volume
* indices on the stream states.
*/
- private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted) {
+ private int checkForRingerModeChange(int oldIndex, int direction, int step, boolean isMuted,
+ String caller) {
final boolean isTv = mPlatformType == AudioSystem.PLATFORM_TELEVISION;
int result = FLAG_ADJUST_VOLUME;
int ringerMode = getRingerModeInternal();
@@ -3417,6 +3451,11 @@
break;
}
+ if (isAndroidNPlus(caller) && wouldToggleZenMode(ringerMode)
+ && !mNm.isNotificationPolicyAccessGrantedForPackage(caller)) {
+ throw new SecurityException("Not allowed to change Do Not Disturb state");
+ }
+
setRingerMode(ringerMode, TAG + ".checkForRingerModeChange", false /*external*/);
mPrevVolDirection = direction;
@@ -4492,16 +4531,6 @@
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 +4653,11 @@
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 25c84e1..8195319 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.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 @@
}
private static final String TAG = "ApfFilter";
+ private static final boolean VDBG = true;
private final ConnectivityService mConnectivityService;
private final NetworkAgentInfo mNai;
@@ -152,9 +158,14 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
}
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 @@
// 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 @@
// 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 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 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/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index e1d208e..e5342ce 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.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 @@
* 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 @@
* 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 @@
private final NotificationManager mNotificationMgr;
private final IBatteryStats mBatteryStats;
private JobScheduler mJobScheduler;
+ private JobSchedulerInternal mJobSchedulerInternal;
private SyncJobService mSyncJobService;
private SyncStorageEngine mSyncStorageEngine;
@@ -235,14 +227,13 @@
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 @@
}
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 @@
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 @@
continue;
}
if (opx.key.equals(opy.key)) {
- removeSyncOperationFromCache(opy.jobId);
mJobScheduler.cancel(opy.jobId);
}
}
@@ -473,18 +453,16 @@
}
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 @@
}
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 @@
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 @@
* 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 @@
* 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 @@
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 @@
if (isLoggable) {
Slog.v(TAG, "Cancelling duplicate sync " + op);
}
- removeSyncOperationFromCache(op.jobId);
getJobScheduler().cancel(op.jobId);
}
}
@@ -1294,7 +1269,6 @@
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 @@
* 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 @@
* @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 @@
// 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 @@
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 @@
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 @@
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 @@
if (op.isPeriodic) {
scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
} else {
- removeSyncOperationFromCache(op.jobId);
scheduleSyncOperationH(op, delay);
}
}
@@ -2489,7 +2455,6 @@
if (op.isPeriodic) {
scheduleSyncOperationH(op.createOneTimeSyncOperation(), delay);
} else {
- removeSyncOperationFromCache(op.jobId);
scheduleSyncOperationH(op, delay);
}
}
@@ -2515,7 +2480,7 @@
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 @@
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 @@
}
}
- 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 @@
+ " 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 @@
*/
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 @@
mSyncJobService.callJobFinished(syncOperation.jobId, false);
runSyncFinishedOrCanceledH(null, asc);
}
- removeSyncOperationFromCache(op.jobId);
getJobScheduler().cancel(op.jobId);
}
}
@@ -2720,7 +2680,7 @@
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 @@
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/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 8c12060..603402e 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 @@
// 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 39c6732..a36e671 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 @@
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 @@
@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 @@
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 459c47f..fed7e4b 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 @@
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 0000000..75170ec
--- /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 d2b77aa..cee46195 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.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 @@
@Override
public void onStart() {
+ publishLocalService(JobSchedulerInternal.class, new LocalService());
publishBinderService(Context.JOB_SCHEDULER_SERVICE, mJobSchedulerStub);
}
@@ -1178,6 +1180,28 @@
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 9837a56..55f37b8 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 @@
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 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 bd06645..6ef425a 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 @@
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 7638494..d9eb45c 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 @@
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 620800c..36fa9ec 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 @@
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 @@
+ "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/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java
index b13fec1..5bc9b1c 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.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 @@
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 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 @@
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);
- }
- }
- } 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");
+ 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;
}
- result = tracker.checkEvent(event, now);
+ 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);
+ }
+ if (result.recheckAt != 0
+ && (reevaluateAt == 0 || result.recheckAt < reevaluateAt)) {
+ reevaluateAt = result.recheckAt;
+ }
+ if (!result.inEvent) {
+ conditionsToNotify.add(createCondition(conditionId, Condition.STATE_FALSE));
+ continue;
+ }
+ conditionsToNotify.add(createCondition(conditionId, Condition.STATE_TRUE));
}
- if (result.recheckAt != 0 && (reevaluateAt == 0 || result.recheckAt < reevaluateAt)) {
- reevaluateAt = result.recheckAt;
- }
- if (!result.inEvent) {
- notifyCondition(conditionId, Condition.STATE_FALSE, "!inEventNow");
- continue;
- }
- notifyCondition(conditionId, Condition.STATE_TRUE, "inEventNow");
+ rescheduleAlarm(now, reevaluateAt);
}
- rescheduleAlarm(now, reevaluateAt);
+ for (Condition condition : conditionsToNotify) {
+ if (condition != null) {
+ notifyCondition(condition);
+ }
+ }
if (DEBUG) Slog.d(TAG, "evaluateSubscriptions took " + (System.currentTimeMillis() - now));
}
@@ -266,12 +284,6 @@
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 6cf3940..6d9fed4 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 @@
rebuildRestoredPackages();
}
// make sure we're still bound to any of our services who may have just upgraded
- rebindServices();
+ rebindServices(false);
}
}
@@ -249,13 +249,13 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
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 516602e..e8a6528 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.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.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 @@
private IActivityManager mAm;
AudioManager mAudioManager;
AudioManagerInternal mAudioManagerInternal;
- StatusBarManagerInternal mStatusBar;
+ @Nullable StatusBarManagerInternal mStatusBar;
Vibrator mVibrator;
private VrManagerInternal mVrManagerInternal;
@@ -274,9 +277,6 @@
// 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 @@
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 @@
private void loadPolicyFile() {
if (DBG) Slog.d(TAG, "loadPolicyFile");
synchronized(mPolicyFile) {
- mBlockedPackages.clear();
FileInputStream infile = null;
try {
@@ -795,7 +774,9 @@
} 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 @@
private final Runnable mBuzzBeepBlinked = new Runnable() {
@Override
public void run() {
- mStatusBar.buzzBeepBlinked();
+ if (mStatusBar != null) {
+ mStatusBar.buzzBeepBlinked();
+ }
}
};
@@ -935,7 +918,7 @@
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 @@
// 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 @@
}
/**
- * 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 @@
checkCallerIsSystem();
setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
+ mRankingHelper.setEnabled(pkg, uid, enabled);
+ savePolicyFile();
}
/**
@@ -1811,6 +1807,16 @@
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 @@
}
@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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 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 538f951..b853417 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 @@
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 void emit() {
- if (mPrevious == null) {
- mPrevious = new AggregatedStats(null, key);
- }
+ 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);
- 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);
+ 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 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 @@
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 fd96a78..4a41705 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.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.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 @@
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 @@
}
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 b7cd318..5b0ceca 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.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 @@
@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 @@
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 @@
startWatchingPackageBroadcasts();
}
mListeners.unregister(listener);
- mListeners.register(listener, Binder.getCallingUserHandle());
+ mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()),
+ callingPackage));
}
}
@@ -296,17 +319,21 @@
}
}
- 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 @@
@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 @@
@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 @@
@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 @@
@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 @@
}
}
-
- 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);
+ /** 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);
+ }
+ return false;
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":"
+ + 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;
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ } 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
@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 9a1ecd7..c7578f0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16456,14 +16456,29 @@
@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) {
@@ -16478,6 +16493,32 @@
}
@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;
@@ -16621,6 +16662,22 @@
}
}
+ @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)
@@ -19252,6 +19309,12 @@
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 d77168c..319fc37 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 @@
return runSuspend(true);
case "unsuspend":
return runSuspend(false);
+ case "set-home-activity":
+ return runSetHomeActivity();
default:
return handleDefaultCommands(cmd);
}
@@ -963,6 +965,39 @@
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 @@
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 0b0f7ab..197b2fa 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.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.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.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.function.Predicate;
/**
@@ -156,6 +158,9 @@
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 @@
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 @@
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 @@
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 @@
}
// TODO Actually make it async.
- private void scheduleSaveUser(@UserIdInt int userId) {
+ void scheduleSaveUser(@UserIdInt int userId) {
synchronized (mLock) {
saveUserLocked(userId);
}
@@ -676,6 +690,10 @@
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 @@
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 @@
/** 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 @@
/** 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 @@
return;
}
- final long token = Binder.clearCallingIdentity();
+ final long token = injectClearCallingIdentity();
try {
// Clear icon info on the shortcut.
shortcut.setIconResourceId(0);
@@ -874,7 +895,7 @@
shortcut.clearIcon();
}
} finally {
- Binder.restoreCallingIdentity(token);
+ injectRestoreCallingIdentity(token);
}
}
@@ -975,6 +996,10 @@
}
}
+ void postToHandler(Runnable r) {
+ mHandler.post(r);
+ }
+
/**
* Throw if {@code numShortcuts} is bigger than {@link #mMaxDynamicShortcuts}.
*/
@@ -994,17 +1019,16 @@
}
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 @@
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 @@
// 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 @@
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 @@
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 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 @@
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 @@
}
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 @@
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 @@
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 @@
}
}
}
+
+ @Override
+ public boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
+ return ShortcutService.this.hasShortcutHostPermission(callingPackage, userId);
+ }
}
// === Dump ===
@@ -1512,37 +1623,74 @@
(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);
+ 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;
}
- if (ret == 0) {
- pw.println("Success");
- }
- return ret;
+ pw.println("Success");
+ return 0;
}
@Override
@@ -1562,56 +1710,85 @@
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 @@
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 @@
return ActivityManager.isLowRamDeviceStatic();
}
+ PackageManagerInternal injectPackageManagerInternal() {
+ return mPackageManagerInternal;
+ }
+
File getUserBitmapFilePath(@UserIdInt int userId) {
return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
}
@@ -1687,6 +1890,9 @@
}
}
+/**
+ * Per-user information.
+ */
class UserShortcuts {
private static final String TAG = ShortcutService.TAG;
@@ -1695,6 +1901,10 @@
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 @@
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);
- packageShortcuts.saveToXml(out);
+ final int lsize = mLaunchers.size();
+ for (int i = 0; i < lsize; i++) {
+ mLaunchers.valueAt(i).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,12 +1968,186 @@
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(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);
}
@@ -1743,13 +2155,31 @@
}
public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
- pw.print(" ");
- pw.print("User: ");
- pw.print(mUserId);
pw.println();
- for (int i = 0; i < mPackages.size(); i++) {
- mPackages.valueAt(i).dump(s, pw, prefix + " ");
+ 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();
+ }
}
}
}
@@ -1791,7 +2221,6 @@
mPackageName = packageName;
}
- @GuardedBy("mLock")
@Nullable
public ShortcutInfo findShortcutById(String id) {
return mShortcuts.get(id);
@@ -1818,28 +2247,34 @@
*
* 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 @@
}
}
- @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 @@
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 @@
}
}
- @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 @@
* 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 @@
return true;
}
- @GuardedBy("mLock")
public void resetRateLimitingForCommandLine() {
mApiCallCount = 0;
mLastResetTime = 0;
@@ -1959,18 +2410,51 @@
/**
* 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 8206bda..5fd196b 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 @@
@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 @@
*
* @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/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ffdd89a..3cf9590 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 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 55b3c7b..3a5dec9 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 @@
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 @@
if (animation != null) {
toAppAnimator.animation = animation;
- animation = null;
toAppAnimator.animating = animating;
toAppAnimator.animLayerAdjustment = animLayerAdjustment;
+ setNullAnimation();
animLayerAdjustment = 0;
toAppAnimator.updateLayers();
updateLayers();
@@ -311,7 +315,7 @@
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 9795c93..4ec297e 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 @@
}
}
- 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 e42658e..b702180 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 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.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 @@
// 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 @@
}
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 @@
}
mInputDispatchFrozen = false;
+ mInputFreezeReason = null;
updateInputDispatchModeLw();
}
}
@@ -509,4 +519,10 @@
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 2e424d0..e44b0f3 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 @@
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 4698e4e..f243761 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_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 @@
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 @@
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 @@
winAnimator.mAnimationIsEntrance = false;
winAnimator.mAnimationStartTime = -1;
winAnimator.mKeyguardGoingAwayAnimation = true;
+ winAnimator.mKeyguardGoingAwayWithWallpaper
+ = keyguardGoingAwayWithWallpaper;
}
} else {
if (DEBUG_KEYGUARD) Slog.d(TAG,
@@ -392,10 +403,13 @@
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 @@
// 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 @@
// 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 1ae4394..607a3e9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2826,10 +2826,12 @@
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
@@ -4086,7 +4088,7 @@
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;
@@ -4196,7 +4198,7 @@
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);
}
@@ -4253,17 +4255,12 @@
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;
@@ -4279,6 +4276,9 @@
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
@@ -4288,6 +4288,11 @@
// 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(
@@ -4298,7 +4303,6 @@
if (visible) {
wtoken.mEnteringAnimation = true;
} else {
- wtoken.setWindowsExiting(true);
mClosingApps.add(wtoken);
wtoken.mEnteringAnimation = false;
}
@@ -5174,18 +5178,16 @@
}
@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();
}
}
@@ -9908,6 +9910,9 @@
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 aff668b..1695615 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -645,15 +645,23 @@
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 @@
}
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);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index bf8a62e..41eafe7 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 @@
boolean mEnteringAnimation;
boolean mKeyguardGoingAwayAnimation;
+ boolean mKeyguardGoingAwayWithWallpaper;
/** The pixel format of the underlying SurfaceControl */
int mSurfaceFormat;
@@ -250,6 +251,7 @@
mAnimation.cancel();
mAnimation = null;
mKeyguardGoingAwayAnimation = false;
+ mKeyguardGoingAwayWithWallpaper = false;
}
}
@@ -381,6 +383,7 @@
mAnimating = false;
mKeyguardGoingAwayAnimation = false;
+ mKeyguardGoingAwayWithWallpaper = false;
mLocalAnimating = false;
if (mAnimation != null) {
mAnimation.cancel();
@@ -708,8 +711,6 @@
// 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 @@
}
// 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 fb07512..11f3771 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 @@
mSurfaceY = top;
try {
+ if (SHOW_TRANSACTIONS) logSurface(
+ "POS (setPositionAndLayer) @ (" + left + "," + top + ")", null);
mSurfaceControl.setPosition(left, top);
mSurfaceControl.setLayerStack(layerStack);
@@ -205,6 +207,9 @@
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 8ada2f1..5ad771f 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 @@
if (!appAnimator.usingTransferredAnimation) {
appAnimator.clearThumbnail();
- appAnimator.animation = null;
+ appAnimator.setNullAnimation();
}
wtoken.inPendingTransaction = false;
@@ -1231,7 +1231,7 @@
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 @@
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/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b48c185..6ddc6c8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -26,8 +26,6 @@
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;
@@ -50,10 +48,10 @@
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;
@@ -115,6 +113,7 @@
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;
@@ -141,6 +140,7 @@
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;
@@ -306,6 +306,7 @@
final IPackageManager mIPackageManager;
final UserManager mUserManager;
final UserManagerInternal mUserManagerInternal;
+ final TelephonyManager mTelephonyManager;
private final LockPatternUtils mLockPatternUtils;
/**
@@ -482,9 +483,9 @@
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) {
@@ -1354,6 +1355,10 @@
return LocalServices.getService(PowerManagerInternal.class);
}
+ TelephonyManager getTelephonyManager() {
+ return TelephonyManager.from(mContext);
+ }
+
IWindowManager getIWindowManager() {
return IWindowManager.Stub
.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -1542,6 +1547,7 @@
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();
@@ -1664,12 +1670,14 @@
} 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");
}
}
}
@@ -5603,7 +5611,7 @@
mOwners.clearDeviceOwner();
mOwners.writeDeviceOwner();
updateDeviceOwnerLocked();
- disableDeviceLoggingIfNotCompliant();
+ disableSecurityLoggingIfNotCompliant();
// Reactivate backup service.
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -7893,6 +7901,29 @@
}
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;
+ }
}
/**
@@ -8309,6 +8340,10 @@
}
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);
@@ -8562,15 +8597,15 @@
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);
@@ -8588,7 +8623,7 @@
}
@Override
- public boolean getDeviceLoggingEnabled(ComponentName admin) {
+ public boolean isSecurityLoggingEnabled(ComponentName admin) {
Preconditions.checkNotNull(admin);
synchronized (this) {
getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -8597,7 +8632,7 @@
}
@Override
- public ParceledListSlice<SecurityEvent> retrievePreviousDeviceLogs(ComponentName admin) {
+ public ParceledListSlice<SecurityEvent> retrievePreRebootSecurityLogs(ComponentName admin) {
Preconditions.checkNotNull(admin);
ensureDeviceOwnerManagingSingleUser(admin);
@@ -8612,7 +8647,7 @@
}
@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 cacc671..79702a8 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 e7daaa1..5975405 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -28,6 +28,7 @@
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.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.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.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 @@
// 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 @@
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 @@
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
- if (!disableNonCoreServices) {
+ if (!disableNonCoreServices && !disableTextServices) {
mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
}
@@ -912,7 +926,7 @@
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 @@
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 @@
mSystemServiceManager.startService(GestureLauncherService.class);
}
mSystemServiceManager.startService(SensorNotificationService.class);
+ mSystemServiceManager.startService(ContextHubSystemService.class);
}
traceBeginAndSlog("StartDiskStatsService");
@@ -1030,18 +1047,20 @@
}
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 @@
}
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 @@
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 69f12eb..34f2e2e 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 @@
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 aaec1e9..35777ce 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -29,6 +29,7 @@
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;
@@ -322,5 +323,10 @@
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 e897e3d..6c2bdda 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.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 @@
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 @@
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 b05309a..8e2ef70 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -40,6 +40,7 @@
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;
@@ -262,6 +263,7 @@
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;
@@ -295,6 +297,7 @@
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/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index f2c42db..5c51139 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.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 libcore.io.IoUtils;
import org.junit.Assert;
+import org.mockito.ArgumentCaptor;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -90,7 +104,7 @@
*
*/
@SmallTest
-public class ShortcutManagerTest extends AndroidTestCase {
+public class ShortcutManagerTest extends InstrumentationTestCase {
private static final String TAG = "ShortcutManagerTest";
/**
@@ -116,7 +130,14 @@
@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 @@
/** 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 @@
}
@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 @@
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 @@
}
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 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 @@
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 @@
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 @@
mClientContext = new ClientContext();
mMockPackageManager = mock(PackageManager.class);
+ mMockPackageManagerInternal = mock(PackageManagerInternal.class);
mMockUserManager = mock(UserManager.class);
// Prepare injection values.
@@ -311,7 +402,7 @@
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 @@
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 @@
+ "/" + 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 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 @@
dumpsysOnLogcat();
mInjectedCurrentTimeLillis++; // Need to advance the clock for reset to work.
- mService.resetThrottlingInner();
+ mService.resetThrottlingInner(UserHandle.USER_SYSTEM);
dumpsysOnLogcat();
@@ -1148,16 +1247,16 @@
}
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 @@
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 @@
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 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
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_3,
+ Arrays.asList("s3"), getCallingUser()); // Note ID doesn't exist
+ });
// 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(), "s2");
+ mManager.deleteDynamicShortcut("s2");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s2");
+ });
- setCaller(CALLING_PACKAGE_2);
- assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
- mManager.deleteDynamicShortcut("s3");
- assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ mManager.deleteDynamicShortcut("s3");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3", "s4");
+ });
- setCaller(CALLING_PACKAGE_3);
- assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
- mManager.deleteDynamicShortcut("s2");
- assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ mManager.deleteDynamicShortcut("s2");
+ assertShortcutIds(mManager.getPinnedShortcuts() /* none */);
+ });
// Get pinned shortcuts from launcher
- setCaller(LAUNCHER_1);
+ 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");
- // 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_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 */);
+ });
+ }
- 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();
+
+ // 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.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+ mManager.deleteDynamicShortcut("s3");
+ assertShortcutIds(mManager.getPinnedShortcuts(), "s3");
+ });
+
+ dumpsysOnLogcat();
+
+ 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
+ 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");
+ });
+
+ dumpsysOnLogcat();
+
+ 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(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 @@
// 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 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 @@
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 @@
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 @@
assertEquals(2, mManager.getRemainingCallCount());
});
+ mService.getShortcutsForTest().get(UserHandle.USER_SYSTEM).setLauncherComponent(
+ mService, new ComponentName("pkg1", "class"));
+
// Restore.
initService();
@@ -1918,6 +2394,9 @@
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 @@
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 @@
// TODO Check all other fields
}
+
+ // TODO Detailed test for hasShortcutPermissionInner().
+
+ // TODO Add tests for the command line functions too.
}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 10808da..afb7d93 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -95,6 +95,19 @@
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 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 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 @@
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 @@
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 @@
* 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 @@
}
/**
+ * 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 @@
}
}
+ /** {@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 @@
}
/**
+ * 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 4547c6a..51a6588 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -93,6 +93,15 @@
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 @@
/**
* 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 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 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 @@
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 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 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 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 @@
}
/**
- * 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 5b62e03..d18b317 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -103,6 +103,8 @@
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 @@
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 @@
}
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 @@
}
@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 @@
}
}
+ /**
+ * 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 30fc5ad..e91128f 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -418,12 +418,13 @@
*
* @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 6a8c1cb..4b15e54 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -245,7 +245,8 @@
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 @@
}
@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 2eef7ee..cf73d4f 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -64,6 +64,17 @@
*/
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 0cf7212b..52ef4a7 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 @@
}
/**
+ * 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 671399b..df6715d 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -22,6 +22,7 @@
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 @@
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 @@
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 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 @@
}
/**
+ * 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 d45938c..a4ef560 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 @@
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 0185808..5b602eb 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -212,12 +212,14 @@
/**
* 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 @@
}
/**
+ * 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 @@
}
/** @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 b85382f..fa7183a 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -332,9 +332,10 @@
}
@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 8afb455..4fa8fe9 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -317,6 +317,18 @@
"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 8a54add..3ee0e9f 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -75,4 +75,8 @@
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 569c244..dff1b11 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -87,5 +87,5 @@
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 863fff2..0678fe2 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 @@
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 0088e0c..3e43fe2 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 @@
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 ea437d0..86518b5 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -444,6 +444,11 @@
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 @@
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/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index e851c8d..91e891f 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -758,6 +758,12 @@
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 ac562b9..e67134d 100644
--- a/tests/SoundTriggerTests/Android.mk
+++ b/tests/SoundTriggerTests/Android.mk
@@ -27,6 +27,7 @@
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 e8b9dd3..f7454c7 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 7acb472..ad02d2b 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);
+
+ Context context = getContext();
+ 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];
+ random.nextBytes(data);
+ UUID modelUuid = UUID.randomUUID();
+ UUID mVendorUuid = UUID.randomUUID();
+ return new GenericSoundModel(modelUuid, mVendorUuid, data);
+ }
@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);
+ 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);
+ // Confirm it was updated
GenericSoundModel returnedModel =
- mSoundTriggerService.getSoundModel(new ParcelUuid(modelUuid));
-
+ soundTriggerService.getSoundModel(new ParcelUuid(model.uuid));
assertEquals(model, returnedModel);
-
- // Cleanup sound model
- mSoundTriggerService.deleteSoundModel(new ParcelUuid(modelUuid));
}
-
@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 0000000..d5d86d8
--- /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 0000000..9754e4b
--- /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 495d620..5856f49 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 @@
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 fb2213c..fb172d4 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -67,6 +67,20 @@
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 @@
_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 @@
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/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 62f91f7..7f41348 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -492,8 +492,7 @@
}
@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 4039cdf..42c0ae0 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 @@
}
@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 13abaff..87fc7fa 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.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 @@
/** 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 @@
/** 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);
+ 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);
+ 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 @@
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 @@
return parcelableParams;
}
+ @Override
public ParcelableRttParams[] newArray(int size) {
return new ParcelableRttParams[size];
}
@@ -715,11 +718,13 @@
}
/** 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 @@
/** 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 @@
return parcelableResults;
}
+ @Override
public ParcelableRttResults[] newArray(int size) {
return new ParcelableRttResults[size];
}