Merge "Partially fix the keyguard scrim" into lmp-dev
diff --git a/Android.mk b/Android.mk
index 23c4753..9cda341 100644
--- a/Android.mk
+++ b/Android.mk
@@ -118,9 +118,7 @@
core/java/android/content/IIntentReceiver.aidl \
core/java/android/content/IIntentSender.aidl \
core/java/android/content/IOnPrimaryClipChangedListener.aidl \
- core/java/android/content/IPermissionResponseCallback.aidl \
core/java/android/content/IRestrictionsManager.aidl \
- core/java/android/content/IRestrictionsProvider.aidl \
core/java/android/content/ISyncAdapter.aidl \
core/java/android/content/ISyncContext.aidl \
core/java/android/content/ISyncServiceAdapter.aidl \
@@ -320,9 +318,12 @@
media/java/android/media/IRemoteVolumeObserver.aidl \
media/java/android/media/IRingtonePlayer.aidl \
media/java/android/media/IVolumeController.aidl \
- media/java/android/media/routeprovider/IRouteConnection.aidl \
- media/java/android/media/routeprovider/IRouteProvider.aidl \
- media/java/android/media/routeprovider/IRouteProviderCallback.aidl \
+ media/java/android/media/routing/IMediaRouteService.aidl \
+ media/java/android/media/routing/IMediaRouteClientCallback.aidl \
+ media/java/android/media/routing/IMediaRouter.aidl \
+ media/java/android/media/routing/IMediaRouterDelegate.aidl \
+ media/java/android/media/routing/IMediaRouterRoutingCallback.aidl \
+ media/java/android/media/routing/IMediaRouterStateCallback.aidl \
media/java/android/media/session/IActiveSessionsListener.aidl \
media/java/android/media/session/ISessionController.aidl \
media/java/android/media/session/ISessionControllerCallback.aidl \
@@ -333,12 +334,11 @@
media/java/android/media/tv/ITvInputHardware.aidl \
media/java/android/media/tv/ITvInputHardwareCallback.aidl \
media/java/android/media/tv/ITvInputManager.aidl \
+ media/java/android/media/tv/ITvInputManagerCallback.aidl \
media/java/android/media/tv/ITvInputService.aidl \
media/java/android/media/tv/ITvInputServiceCallback.aidl \
media/java/android/media/tv/ITvInputSession.aidl \
media/java/android/media/tv/ITvInputSessionCallback.aidl \
- telecomm/java/com/android/internal/telecomm/ICallServiceLookupResponse.aidl \
- telecomm/java/com/android/internal/telecomm/ICallServiceProvider.aidl \
telecomm/java/com/android/internal/telecomm/ICallVideoProvider.aidl \
telecomm/java/com/android/internal/telecomm/ICallVideoClient.aidl \
telecomm/java/com/android/internal/telecomm/IConnectionService.aidl \
@@ -359,10 +359,6 @@
telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
telephony/java/com/android/internal/telephony/ITelephony.aidl \
- telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl \
- telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl \
- telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl \
- telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl \
telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
telephony/java/com/android/internal/telephony/ISms.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
@@ -372,6 +368,7 @@
wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
wifi/java/android/net/wifi/IWifiScanner.aidl \
+ wifi/java/android/net/wifi/IRttManager.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
packages/services/Proxy/com/android/net/IProxyCallback.aidl \
packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
@@ -527,6 +524,7 @@
frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \
frameworks/base/media/java/android/media/MediaMetadata.aidl \
frameworks/base/media/java/android/media/Rating.aidl \
+ frameworks/base/media/java/android/media/routing/MediaRouteSelector.aidl \
frameworks/base/media/java/android/media/session/MediaSession.aidl \
frameworks/base/media/java/android/media/session/PlaybackState.aidl \
frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
diff --git a/api/current.txt b/api/current.txt
index c319ce8..abf7ea2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23,6 +23,7 @@
field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
+ field public static final java.lang.String BIND_MEDIA_ROUTE_SERVICE = "android.permission.BIND_MEDIA_ROUTE_SERVICE";
field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
@@ -298,6 +299,9 @@
field public static final int alphabeticShortcut = 16843235; // 0x10101e3
field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
+ field public static final int amPmSelectedBackgroundColor = 16843947; // 0x10104ab
+ field public static final int amPmTextColor = 16843945; // 0x10104a9
+ field public static final int amPmUnselectedBackgroundColor = 16843946; // 0x10104aa
field public static final int angle = 16843168; // 0x10101a0
field public static final int animateFirstView = 16843477; // 0x10102d5
field public static final int animateLayoutChanges = 16843506; // 0x10102f2
@@ -358,6 +362,7 @@
field public static final int buttonTint = 16843889; // 0x1010471
field public static final int buttonTintMode = 16843890; // 0x1010472
field public static final int cacheColorHint = 16843009; // 0x1010101
+ field public static final int calendarTextColor = 16843934; // 0x101049e
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
@@ -446,6 +451,14 @@
field public static final int dashWidth = 16843174; // 0x10101a6
field public static final int data = 16842798; // 0x101002e
field public static final int datePickerStyle = 16843612; // 0x101035c
+ field public static final int dateSelectorBackgroundColor = 16843928; // 0x1010498
+ field public static final int dateSelectorDayOfMonthTextAppearance = 16843930; // 0x101049a
+ field public static final int dateSelectorDayOfWeekBackgroundColor = 16843926; // 0x1010496
+ field public static final int dateSelectorDayOfWeekTextAppearance = 16843927; // 0x1010497
+ field public static final int dateSelectorMonthTextAppearance = 16843929; // 0x1010499
+ field public static final int dateSelectorYearListItemTextAppearance = 16843932; // 0x101049c
+ field public static final int dateSelectorYearListSelectedCircleColor = 16843933; // 0x101049d
+ field public static final int dateSelectorYearTextAppearance = 16843931; // 0x101049b
field public static final int dateTextAppearance = 16843593; // 0x1010349
field public static final int debuggable = 16842767; // 0x101000f
field public static final int defaultValue = 16843245; // 0x10101ed
@@ -616,8 +629,12 @@
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
field public static final int hardwareAccelerated = 16843475; // 0x10102d3
field public static final int hasCode = 16842764; // 0x101000c
+ field public static final int headerAmPmTextAppearance = 16843939; // 0x10104a3
field public static final int headerBackground = 16843055; // 0x101012f
+ field public static final int headerBackgroundColor = 16843941; // 0x10104a5
field public static final int headerDividersEnabled = 16843310; // 0x101022e
+ field public static final int headerSelectedTextColor = 16843940; // 0x10104a4
+ field public static final int headerTimeTextAppearance = 16843938; // 0x10104a2
field public static final int height = 16843093; // 0x1010155
field public static final int hideOnContentScroll = 16843845; // 0x1010445
field public static final int hint = 16843088; // 0x1010150
@@ -741,6 +758,8 @@
field public static final int largeScreens = 16843398; // 0x1010286
field public static final int largestWidthLimitDp = 16843622; // 0x1010366
field public static final int launchMode = 16842781; // 0x101001d
+ field public static final int launchTaskBehindBackgroundAnimation = 16843923; // 0x1010493
+ field public static final int launchTaskBehindSourceAnimation = 16843924; // 0x1010494
field public static final int layerType = 16843604; // 0x1010354
field public static final int layout = 16842994; // 0x10100f2
field public static final int layoutAnimation = 16842988; // 0x10100ec
@@ -870,6 +889,9 @@
field public static final int notificationTimeout = 16843651; // 0x1010383
field public static final int numColumns = 16843032; // 0x1010118
field public static final int numStars = 16843076; // 0x1010144
+ field public static final int numbersBackgroundColor = 16843943; // 0x10104a7
+ field public static final int numbersSelectorColor = 16843944; // 0x10104a8
+ field public static final int numbersTextColor = 16843942; // 0x10104a6
field public static final deprecated int numeric = 16843109; // 0x1010165
field public static final int numericShortcut = 16843236; // 0x10101e4
field public static final int onClick = 16843375; // 0x101026f
@@ -974,6 +996,7 @@
field public static final int ratingBarStyleIndicator = 16843280; // 0x1010210
field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
field public static final int readPermission = 16842759; // 0x1010007
+ field public static final int recognitionService = 16843935; // 0x101049f
field public static final int relinquishTaskIdentity = 16843896; // 0x1010478
field public static final int repeatCount = 16843199; // 0x10101bf
field public static final int repeatMode = 16843200; // 0x10101c0
@@ -995,6 +1018,7 @@
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int restrictedAccountType = 16843733; // 0x10103d5
+ field public static final int restrictionType = 16843925; // 0x1010495
field public static final int reversible = 16843853; // 0x101044d
field public static final int right = 16843183; // 0x10101af
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
@@ -1038,6 +1062,7 @@
field public static final int searchIcon = 16843909; // 0x1010485
field public static final int searchKeyphrase = 16843873; // 0x1010461
field public static final int searchKeyphraseId = 16843872; // 0x1010460
+ field public static final int searchKeyphraseRecognitionFlags = 16843948; // 0x10104ac
field public static final int searchKeyphraseSupportedLocales = 16843874; // 0x1010462
field public static final int searchMode = 16843221; // 0x10101d5
field public static final int searchSettingsDescription = 16843402; // 0x101028a
@@ -1262,6 +1287,8 @@
field public static final int tileMode = 16843265; // 0x1010201
field public static final int tileModeX = 16843897; // 0x1010479
field public static final int tileModeY = 16843898; // 0x101047a
+ field public static final int timePickerDialogTheme = 16843937; // 0x10104a1
+ field public static final int timePickerStyle = 16843936; // 0x10104a0
field public static final int timeZone = 16843724; // 0x10103cc
field public static final int tint = 16843041; // 0x1010121
field public static final int tintMode = 16843797; // 0x1010415
@@ -1367,6 +1394,7 @@
field public static final int windowContentTransitions = 16843794; // 0x1010412
field public static final int windowDisablePreview = 16843298; // 0x1010222
field public static final int windowDrawsSystemBarBackgrounds = 16843858; // 0x1010452
+ field public static final int windowElevation = 16843922; // 0x1010492
field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
field public static final int windowEnterAnimation = 16842932; // 0x10100b4
field public static final int windowEnterTransition = 16843833; // 0x1010439
@@ -3308,6 +3336,7 @@
method public android.view.LayoutInflater getLayoutInflater();
method public android.app.LoaderManager getLoaderManager();
method public java.lang.String getLocalClassName();
+ method public final android.media.session.MediaController getMediaController();
method public android.view.MenuInflater getMenuInflater();
method public final android.app.Activity getParent();
method public android.content.Intent getParentActivityIntent();
@@ -3431,6 +3460,7 @@
method public void setFinishOnTouchOutside(boolean);
method public void setImmersive(boolean);
method public void setIntent(android.content.Intent);
+ method public final void setMediaController(android.media.session.MediaController);
method public boolean setMediaPlaying(boolean);
method public final void setProgress(int);
method public final void setProgressBarIndeterminate(boolean);
@@ -3509,6 +3539,7 @@
method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
method public deprecated java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
+ method public boolean isInLockTaskMode();
method public boolean isLowRamDevice();
method public static boolean isRunningInTestHarness();
method public static boolean isUserAMonkey();
@@ -3583,6 +3614,7 @@
field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
+ field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82
field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
@@ -3659,6 +3691,7 @@
public class ActivityOptions {
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
+ method public static android.app.ActivityOptions makeLaunchTaskBehindAnimation();
method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.view.View, java.lang.String);
method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.app.Activity, android.util.Pair<android.view.View, java.lang.String>...);
@@ -5287,6 +5320,8 @@
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
method public android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
method public android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
+ method public void enableSystemApp(android.content.ComponentName, java.lang.String);
+ method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
method public java.lang.String[] getAccountTypesWithManagementDisabled();
method public java.util.List<android.content.ComponentName> getActiveAdmins();
method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
@@ -6570,11 +6605,10 @@
package android.content {
- public abstract class AbstractRestrictionsProvider extends android.app.Service {
+ public abstract class AbstractRestrictionsProvider extends android.content.BroadcastReceiver {
ctor public AbstractRestrictionsProvider();
- method public abstract android.os.Bundle getPermissionResponse(java.lang.String, java.lang.String);
- method public final android.os.IBinder onBind(android.content.Intent);
- method public abstract void requestPermission(java.lang.String, java.lang.String, android.os.Bundle);
+ method public void onReceive(android.content.Context, android.content.Intent);
+ method public abstract void requestPermission(android.content.Context, java.lang.String, java.lang.String, android.os.Bundle);
}
public abstract class AbstractThreadedSyncAdapter {
@@ -7045,6 +7079,7 @@
method public abstract android.content.res.AssetManager getAssets();
method public abstract java.io.File getCacheDir();
method public abstract java.lang.ClassLoader getClassLoader();
+ method public abstract java.io.File getCodeCacheDir();
method public abstract android.content.ContentResolver getContentResolver();
method public abstract java.io.File getDatabasePath(java.lang.String);
method public abstract java.io.File getDir(java.lang.String, int);
@@ -7057,6 +7092,7 @@
method public abstract java.io.File getFileStreamPath(java.lang.String);
method public abstract java.io.File getFilesDir();
method public abstract android.os.Looper getMainLooper();
+ method public abstract java.io.File getNoBackupFilesDir();
method public abstract java.io.File getObbDir();
method public abstract java.io.File[] getObbDirs();
method public abstract java.lang.String getPackageCodePath();
@@ -7170,6 +7206,7 @@
field public static final java.lang.String SEARCH_SERVICE = "search";
field public static final java.lang.String SENSOR_SERVICE = "sensor";
field public static final java.lang.String STORAGE_SERVICE = "storage";
+ field public static final java.lang.String TELECOMM_SERVICE = "telecomm";
field public static final java.lang.String TELEPHONY_SERVICE = "phone";
field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
field public static final java.lang.String TV_INPUT_SERVICE = "tv_input";
@@ -7215,6 +7252,7 @@
method public android.content.Context getBaseContext();
method public java.io.File getCacheDir();
method public java.lang.ClassLoader getClassLoader();
+ method public java.io.File getCodeCacheDir();
method public android.content.ContentResolver getContentResolver();
method public java.io.File getDatabasePath(java.lang.String);
method public java.io.File getDir(java.lang.String, int);
@@ -7226,6 +7264,7 @@
method public java.io.File getFileStreamPath(java.lang.String);
method public java.io.File getFilesDir();
method public android.os.Looper getMainLooper();
+ method public java.io.File getNoBackupFilesDir();
method public java.io.File getObbDir();
method public java.io.File[] getObbDirs();
method public java.lang.String getPackageCodePath();
@@ -7689,7 +7728,6 @@
field public static final int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 8388608; // 0x800000
field public static final int FLAG_ACTIVITY_FORWARD_RESULT = 33554432; // 0x2000000
field public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 1048576; // 0x100000
- field public static final int FLAG_ACTIVITY_LAUNCH_BEHIND = 4096; // 0x1000
field public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 134217728; // 0x8000000
field public static final int FLAG_ACTIVITY_NEW_DOCUMENT = 524288; // 0x80000
field public static final int FLAG_ACTIVITY_NEW_TASK = 268435456; // 0x10000000
@@ -7917,6 +7955,7 @@
}
public class RestrictionEntry implements android.os.Parcelable {
+ ctor public RestrictionEntry(int, java.lang.String);
ctor public RestrictionEntry(java.lang.String, java.lang.String);
ctor public RestrictionEntry(java.lang.String, boolean);
ctor public RestrictionEntry(java.lang.String, java.lang.String[]);
@@ -7951,31 +7990,34 @@
field public static final int TYPE_INTEGER = 5; // 0x5
field public static final int TYPE_MULTI_SELECT = 4; // 0x4
field public static final int TYPE_NULL = 0; // 0x0
+ field public static final int TYPE_STRING = 6; // 0x6
}
public class RestrictionsManager {
method public android.os.Bundle getApplicationRestrictions();
method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(java.lang.String);
- method public void getPermissionResponse(java.lang.String, android.content.RestrictionsManager.PermissionResponseCallback);
method public boolean hasRestrictionsProvider();
method public void notifyPermissionResponse(java.lang.String, android.os.Bundle);
method public void requestPermission(java.lang.String, android.os.Bundle);
field public static final java.lang.String ACTION_PERMISSION_RESPONSE_RECEIVED = "android.intent.action.PERMISSION_RESPONSE_RECEIVED";
- field public static final java.lang.String EXTRA_PACKAGE_NAME = "package_name";
- field public static final java.lang.String EXTRA_RESPONSE_BUNDLE = "response";
+ field public static final java.lang.String ACTION_REQUEST_PERMISSION = "android.content.action.REQUEST_PERMISSION";
+ field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
+ field public static final java.lang.String EXTRA_REQUEST_BUNDLE = "android.content.extra.REQUEST_BUNDLE";
+ field public static final java.lang.String EXTRA_REQUEST_TYPE = "android.content.extra.REQUEST_TYPE";
+ field public static final java.lang.String EXTRA_RESPONSE_BUNDLE = "android.content.extra.RESPONSE_BUNDLE";
+ field public static final java.lang.String META_DATA_APP_RESTRICTIONS = "android.content.APP_RESTRICTIONS";
field public static final java.lang.String REQUEST_KEY_APPROVE_LABEL = "android.request.approve_label";
field public static final java.lang.String REQUEST_KEY_DATA = "android.request.data";
field public static final java.lang.String REQUEST_KEY_DENY_LABEL = "android.request.deny_label";
- field public static final java.lang.String REQUEST_KEY_DEVICE_NAME = "android.request.device";
field public static final java.lang.String REQUEST_KEY_ICON = "android.request.icon";
field public static final java.lang.String REQUEST_KEY_ID = "android.request.id";
field public static final java.lang.String REQUEST_KEY_MESSAGE = "android.request.mesg";
- field public static final java.lang.String REQUEST_KEY_REQUESTOR_NAME = "android.request.requestor";
+ field public static final java.lang.String REQUEST_KEY_NEW_REQUEST = "android.request.new_request";
field public static final java.lang.String REQUEST_KEY_TITLE = "android.request.title";
+ field public static final java.lang.String REQUEST_TYPE_APPROVAL = "android.request.type.approval";
field public static final java.lang.String REQUEST_TYPE_LOCAL_APPROVAL = "android.request.type.local_approval";
- field public static final java.lang.String REQUEST_TYPE_QUESTION = "android.request.type.question";
field public static final java.lang.String RESPONSE_KEY_ERROR_CODE = "android.response.errorcode";
- field public static final java.lang.String RESPONSE_KEY_ERROR_MESSAGE = "android.response.errormsg";
+ field public static final java.lang.String RESPONSE_KEY_MESSAGE = "android.response.msg";
field public static final java.lang.String RESPONSE_KEY_RESPONSE_TIMESTAMP = "android.response.timestamp";
field public static final java.lang.String RESPONSE_KEY_RESULT = "android.response.result";
field public static final int RESULT_APPROVED = 1; // 0x1
@@ -7988,11 +8030,6 @@
field public static final int RESULT_UNKNOWN_REQUEST = 4; // 0x4
}
- public static abstract class RestrictionsManager.PermissionResponseCallback {
- ctor public RestrictionsManager.PermissionResponseCallback();
- method public abstract void onResponse(android.os.Bundle);
- }
-
public class SearchRecentSuggestionsProvider extends android.content.ContentProvider {
ctor public SearchRecentSuggestionsProvider();
method public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
@@ -8351,6 +8388,36 @@
field public int reqGlEsVersion;
}
+ public class InstallSessionInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.graphics.Bitmap getIcon();
+ method public java.lang.String getInstallerPackageName();
+ method public java.lang.String getPackageName();
+ method public int getProgress();
+ method public int getSessionId();
+ method public java.lang.CharSequence getTitle();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public class InstallSessionParams implements android.os.Parcelable {
+ ctor public InstallSessionParams();
+ method public int describeContents();
+ method public void setDeltaSize(long);
+ method public void setIcon(android.graphics.Bitmap);
+ method public void setInstallLocation(int);
+ method public void setModeFullInstall();
+ method public void setModeInheritExisting();
+ method public void setOriginatingUri(android.net.Uri);
+ method public void setPackageName(java.lang.String);
+ method public void setProgressMax(int);
+ method public void setReferrerUri(android.net.Uri);
+ method public void setSignatures(android.content.pm.Signature[]);
+ method public void setTitle(java.lang.CharSequence);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
public class InstrumentationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
ctor public InstrumentationInfo();
ctor public InstrumentationInfo(android.content.pm.InstrumentationInfo);
@@ -8366,6 +8433,9 @@
field public java.lang.String targetPackage;
}
+ public class KeySet {
+ }
+
public class LabeledIntent extends android.content.Intent {
ctor public LabeledIntent(android.content.Intent, java.lang.String, int, int);
ctor public LabeledIntent(android.content.Intent, java.lang.String, java.lang.CharSequence, int);
@@ -8415,6 +8485,9 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final int INSTALL_LOCATION_AUTO = 0; // 0x0
+ field public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1; // 0x1
+ field public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2; // 0x2
field public static final int REQUESTED_PERMISSION_GRANTED = 2; // 0x2
field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
field public android.content.pm.ActivityInfo[] activities;
@@ -8422,6 +8495,7 @@
field public android.content.pm.ConfigurationInfo[] configPreferences;
field public long firstInstallTime;
field public int[] gids;
+ field public int installLocation;
field public android.content.pm.InstrumentationInfo[] instrumentation;
field public long lastUpdateTime;
field public java.lang.String packageName;
@@ -8435,10 +8509,52 @@
field public java.lang.String sharedUserId;
field public int sharedUserLabel;
field public android.content.pm.Signature[] signatures;
+ field public java.lang.String[] splitNames;
field public int versionCode;
field public java.lang.String versionName;
}
+ public class PackageInstaller {
+ method public int createSession(android.content.pm.InstallSessionParams) throws java.io.IOException;
+ method public java.util.List<android.content.pm.InstallSessionInfo> getActiveSessions();
+ method public android.content.pm.PackageInstaller.Session openSession(int);
+ method public void registerSessionObserver(android.content.pm.PackageInstaller.SessionObserver);
+ method public void uninstall(java.lang.String, android.content.pm.PackageInstaller.UninstallResultCallback);
+ method public void unregisterSessionObserver(android.content.pm.PackageInstaller.SessionObserver);
+ }
+
+ public static abstract class PackageInstaller.CommitResultCallback {
+ ctor public PackageInstaller.CommitResultCallback();
+ method public abstract void onFailure(java.lang.String);
+ method public void onFailureConflict(java.lang.String, java.lang.String);
+ method public void onFailureIncompatible(java.lang.String);
+ method public void onFailureInvalid(java.lang.String);
+ method public void onFailureStorage(java.lang.String);
+ method public abstract void onSuccess();
+ }
+
+ public static class PackageInstaller.Session implements java.io.Closeable {
+ method public void close();
+ method public void commit(android.content.pm.PackageInstaller.CommitResultCallback);
+ method public void destroy();
+ method public void fsync(java.io.OutputStream) throws java.io.IOException;
+ method public java.io.OutputStream openWrite(java.lang.String, long, long) throws java.io.IOException;
+ method public void setProgress(int);
+ }
+
+ public static abstract class PackageInstaller.SessionObserver {
+ ctor public PackageInstaller.SessionObserver();
+ method public abstract void onCreated(android.content.pm.InstallSessionInfo);
+ method public abstract void onFinalized(int, boolean);
+ method public abstract void onProgress(int, int);
+ }
+
+ public static abstract class PackageInstaller.UninstallResultCallback {
+ ctor public PackageInstaller.UninstallResultCallback();
+ method public abstract void onFailure(java.lang.String);
+ method public abstract void onSuccess();
+ }
+
public class PackageItemInfo {
ctor public PackageItemInfo();
ctor public PackageItemInfo(android.content.pm.PackageItemInfo);
@@ -8501,8 +8617,10 @@
method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+ method public abstract android.content.pm.PackageInstaller getInstaller();
method public abstract java.lang.String getInstallerPackageName(java.lang.String);
method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract android.content.pm.KeySet getKeySetByAlias(java.lang.String, java.lang.String);
method public abstract android.content.Intent getLaunchIntentForPackage(java.lang.String);
method public abstract android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
method public abstract java.lang.String getNameForUid(int);
@@ -8521,12 +8639,15 @@
method public abstract android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract android.content.pm.KeySet getSigningKeySet(java.lang.String);
method public abstract android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
method public abstract java.lang.String[] getSystemSharedLibraryNames();
method public abstract java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public abstract boolean hasSystemFeature(java.lang.String);
method public abstract boolean isSafeMode();
+ method public abstract boolean isSignedBy(java.lang.String, android.content.pm.KeySet);
+ method public abstract boolean isSignedByExactly(java.lang.String, android.content.pm.KeySet);
method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
method public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(java.lang.String, int, int);
method public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
@@ -8583,12 +8704,14 @@
field public static final java.lang.String FEATURE_SCREEN_LANDSCAPE = "android.hardware.screen.landscape";
field public static final java.lang.String FEATURE_SCREEN_PORTRAIT = "android.hardware.screen.portrait";
field public static final java.lang.String FEATURE_SENSOR_ACCELEROMETER = "android.hardware.sensor.accelerometer";
+ field public static final java.lang.String FEATURE_SENSOR_AMBIENT_TEMPERATURE = "android.hardware.sensor.ambient_temperature";
field public static final java.lang.String FEATURE_SENSOR_BAROMETER = "android.hardware.sensor.barometer";
field public static final java.lang.String FEATURE_SENSOR_COMPASS = "android.hardware.sensor.compass";
field public static final java.lang.String FEATURE_SENSOR_GYROSCOPE = "android.hardware.sensor.gyroscope";
field public static final java.lang.String FEATURE_SENSOR_HEART_RATE = "android.hardware.sensor.heartrate";
field public static final java.lang.String FEATURE_SENSOR_LIGHT = "android.hardware.sensor.light";
field public static final java.lang.String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity";
+ field public static final java.lang.String FEATURE_SENSOR_RELATIVE_HUMIDITY = "android.hardware.sensor.relative_humidity";
field public static final java.lang.String FEATURE_SENSOR_STEP_COUNTER = "android.hardware.sensor.stepcounter";
field public static final java.lang.String FEATURE_SENSOR_STEP_DETECTOR = "android.hardware.sensor.stepdetector";
field public static final java.lang.String FEATURE_SIP = "android.software.sip";
@@ -8808,7 +8931,7 @@
ctor public AssetFileDescriptor.AutoCloseOutputStream(android.content.res.AssetFileDescriptor) throws java.io.IOException;
}
- public final class AssetManager {
+ public final class AssetManager implements java.lang.AutoCloseable {
method public void close();
method public final java.lang.String[] getLocales();
method public final java.lang.String[] list(java.lang.String) throws java.io.IOException;
@@ -11857,7 +11980,7 @@
package android.hardware {
- public class Camera {
+ public deprecated class Camera {
method public final void addCallbackBuffer(byte[]);
method public final void autoFocus(android.hardware.Camera.AutoFocusCallback);
method public final void cancelAutoFocus();
@@ -11896,21 +12019,21 @@
field public static final int CAMERA_ERROR_UNKNOWN = 1; // 0x1
}
- public static class Camera.Area {
+ public static deprecated class Camera.Area {
ctor public Camera.Area(android.graphics.Rect, int);
field public android.graphics.Rect rect;
field public int weight;
}
- public static abstract interface Camera.AutoFocusCallback {
+ public static abstract deprecated interface Camera.AutoFocusCallback {
method public abstract void onAutoFocus(boolean, android.hardware.Camera);
}
- public static abstract interface Camera.AutoFocusMoveCallback {
+ public static abstract deprecated interface Camera.AutoFocusMoveCallback {
method public abstract void onAutoFocusMoving(boolean, android.hardware.Camera);
}
- public static class Camera.CameraInfo {
+ public static deprecated class Camera.CameraInfo {
ctor public Camera.CameraInfo();
field public static final int CAMERA_FACING_BACK = 0; // 0x0
field public static final int CAMERA_FACING_FRONT = 1; // 0x1
@@ -11919,11 +12042,11 @@
field public int orientation;
}
- public static abstract interface Camera.ErrorCallback {
+ public static abstract deprecated interface Camera.ErrorCallback {
method public abstract void onError(int, android.hardware.Camera);
}
- public static class Camera.Face {
+ public static deprecated class Camera.Face {
ctor public Camera.Face();
field public int id;
field public android.graphics.Point leftEye;
@@ -11933,15 +12056,15 @@
field public int score;
}
- public static abstract interface Camera.FaceDetectionListener {
+ public static abstract deprecated interface Camera.FaceDetectionListener {
method public abstract void onFaceDetection(android.hardware.Camera.Face[], android.hardware.Camera);
}
- public static abstract interface Camera.OnZoomChangeListener {
+ public static abstract deprecated interface Camera.OnZoomChangeListener {
method public abstract void onZoomChange(int, boolean, android.hardware.Camera);
}
- public class Camera.Parameters {
+ public deprecated class Camera.Parameters {
method public java.lang.String flatten();
method public java.lang.String get(java.lang.String);
method public java.lang.String getAntibanding();
@@ -12091,19 +12214,19 @@
field public static final java.lang.String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent";
}
- public static abstract interface Camera.PictureCallback {
+ public static abstract deprecated interface Camera.PictureCallback {
method public abstract void onPictureTaken(byte[], android.hardware.Camera);
}
- public static abstract interface Camera.PreviewCallback {
+ public static abstract deprecated interface Camera.PreviewCallback {
method public abstract void onPreviewFrame(byte[], android.hardware.Camera);
}
- public static abstract interface Camera.ShutterCallback {
+ public static abstract deprecated interface Camera.ShutterCallback {
method public abstract void onShutter();
}
- public class Camera.Size {
+ public deprecated class Camera.Size {
ctor public Camera.Size(int, int);
field public int height;
field public int width;
@@ -14324,6 +14447,7 @@
method public final void release();
method public final void releaseOutputBuffer(int, boolean);
method public final void releaseOutputBuffer(int, long);
+ method public final void reset();
method public void setCallback(android.media.MediaCodec.Callback);
method public final void setParameters(android.os.Bundle);
method public final void setVideoScalingMode(int);
@@ -14846,7 +14970,9 @@
method public void attachAuxEffect(int);
method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri);
method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder);
+ method public static android.media.MediaPlayer create(android.content.Context, android.net.Uri, android.view.SurfaceHolder, android.media.AudioAttributes, int);
method public static android.media.MediaPlayer create(android.content.Context, int);
+ method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
method public void deselectTrack(int) throws java.lang.IllegalStateException;
method public int getAudioSessionId();
method public int getCurrentPosition();
@@ -14864,6 +14990,7 @@
method public void reset();
method public void seekTo(int) throws java.lang.IllegalStateException;
method public void selectTrack(int) throws java.lang.IllegalStateException;
+ method public void setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setAudioStreamType(int);
method public void setAuxEffectSendLevel(float);
@@ -14970,7 +15097,7 @@
method public void setAudioEncodingBitRate(int);
method public void setAudioSamplingRate(int);
method public void setAudioSource(int) throws java.lang.IllegalStateException;
- method public void setCamera(android.hardware.Camera);
+ method public deprecated void setCamera(android.hardware.Camera);
method public void setCaptureRate(double);
method public void setLocation(float, float);
method public void setMaxDuration(int) throws java.lang.IllegalArgumentException;
@@ -15004,6 +15131,7 @@
field public static final int AMR_WB = 2; // 0x2
field public static final int DEFAULT = 0; // 0x0
field public static final int HE_AAC = 4; // 0x4
+ field public static final int VORBIS = 6; // 0x6
}
public final class MediaRecorder.AudioSource {
@@ -15034,6 +15162,7 @@
field public static final int MPEG_4 = 2; // 0x2
field public static final deprecated int RAW_AMR = 3; // 0x3
field public static final int THREE_GPP = 1; // 0x1
+ field public static final int WEBM = 9; // 0x9
}
public final class MediaRecorder.VideoEncoder {
@@ -15041,6 +15170,7 @@
field public static final int H263 = 1; // 0x1
field public static final int H264 = 2; // 0x2
field public static final int MPEG_4_SP = 3; // 0x3
+ field public static final int VP8 = 4; // 0x4
}
public final class MediaRecorder.VideoSource {
@@ -15508,7 +15638,7 @@
method public final int getMaxVolume();
method public final int getVolumeControl();
method public final void notifyVolumeChanged();
- method public void onAdjustVolumeBy(int);
+ method public void onAdjustVolume(int);
method public abstract int onGetCurrentVolume();
method public void onSetVolumeTo(int);
field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2
@@ -15871,14 +16001,251 @@
}
+package android.media.routing {
+
+ public final class MediaRouteSelector implements android.os.Parcelable {
+ method public boolean containsProtocol(java.lang.Class<?>);
+ method public boolean containsProtocol(java.lang.String);
+ method public int describeContents();
+ method public android.os.Bundle getExtras();
+ method public int getOptionalFeatures();
+ method public java.util.List<java.lang.String> getOptionalProtocols();
+ method public int getRequiredFeatures();
+ method public java.util.List<java.lang.String> getRequiredProtocols();
+ method public java.lang.String getServicePackageName();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public static final class MediaRouteSelector.Builder {
+ ctor public MediaRouteSelector.Builder();
+ method public android.media.routing.MediaRouteSelector.Builder addOptionalProtocol(java.lang.Class<?>);
+ method public android.media.routing.MediaRouteSelector.Builder addOptionalProtocol(java.lang.String);
+ method public android.media.routing.MediaRouteSelector.Builder addRequiredProtocol(java.lang.Class<?>);
+ method public android.media.routing.MediaRouteSelector.Builder addRequiredProtocol(java.lang.String);
+ method public android.media.routing.MediaRouteSelector build();
+ method public android.media.routing.MediaRouteSelector.Builder setExtras(android.os.Bundle);
+ method public android.media.routing.MediaRouteSelector.Builder setOptionalFeatures(int);
+ method public android.media.routing.MediaRouteSelector.Builder setRequiredFeatures(int);
+ method public android.media.routing.MediaRouteSelector.Builder setServicePackageName(java.lang.String);
+ }
+
+ public abstract class MediaRouteService extends android.app.Service {
+ ctor public MediaRouteService();
+ method public android.media.routing.MediaRouter.ServiceMetadata getServiceMetadata();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract android.media.routing.MediaRouteService.ClientSession onCreateClientSession(android.media.routing.MediaRouteService.ClientInfo);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.media.routing.MediaRouteService";
+ }
+
+ public static final class MediaRouteService.ClientInfo {
+ method public java.lang.String getPackageName();
+ method public int getUid();
+ }
+
+ public static abstract class MediaRouteService.ClientSession {
+ ctor public MediaRouteService.ClientSession();
+ method public abstract boolean onConnect(android.media.routing.MediaRouter.ConnectionRequest, android.media.routing.MediaRouteService.ConnectionCallback);
+ method public abstract void onDisconnect();
+ method public void onPauseStream();
+ method public void onRelease();
+ method public void onResumeStream();
+ method public abstract boolean onStartDiscovery(android.media.routing.MediaRouter.DiscoveryRequest, android.media.routing.MediaRouteService.DiscoveryCallback);
+ method public abstract void onStopDiscovery();
+ }
+
+ public final class MediaRouteService.ConnectionCallback {
+ method public void onConnected(android.media.routing.MediaRouter.ConnectionInfo);
+ method public void onConnectionFailed(int, java.lang.CharSequence, android.os.Bundle);
+ method public void onDisconnected();
+ }
+
+ public final class MediaRouteService.DiscoveryCallback {
+ method public void onDestinationFound(android.media.routing.MediaRouter.DestinationInfo, java.util.List<android.media.routing.MediaRouter.RouteInfo>);
+ method public void onDestinationLost(android.media.routing.MediaRouter.DestinationInfo);
+ method public void onDiscoveryFailed(int, java.lang.CharSequence, android.os.Bundle);
+ }
+
+ public final class MediaRouter {
+ ctor public MediaRouter(android.content.Context);
+ method public void addSelector(android.media.routing.MediaRouteSelector);
+ method public void clearSelectors();
+ method public android.media.routing.MediaRouter.Delegate createDelegate();
+ method public android.media.routing.MediaRouter.ConnectionInfo getConnection();
+ method public int getConnectionState();
+ method public java.util.List<android.media.routing.MediaRouter.DestinationInfo> getDiscoveredDestinations();
+ method public java.util.List<android.media.routing.MediaRouter.RouteInfo> getDiscoveredRoutes(android.media.routing.MediaRouter.DestinationInfo);
+ method public int getDiscoveryState();
+ method public android.media.AudioAttributes getPreferredAudioAttributes();
+ method public android.view.Display getPreferredPresentationDisplay();
+ method public android.media.VolumeProvider getPreferredVolumeProvider();
+ method public android.media.routing.MediaRouter.DestinationInfo getSelectedDestination();
+ method public android.media.routing.MediaRouter.RouteInfo getSelectedRoute();
+ method public java.util.List<android.media.routing.MediaRouteSelector> getSelectors();
+ method public boolean isReleased();
+ method public void pauseStream();
+ method public void release();
+ method public void removeSelector(android.media.routing.MediaRouteSelector);
+ method public void resumeStream();
+ method public void setRoutingCallback(android.media.routing.MediaRouter.RoutingCallback, android.os.Handler);
+ field public static final int CONNECTION_ERROR_ABORTED = 1; // 0x1
+ field public static final int CONNECTION_ERROR_BARGED = 7; // 0x7
+ field public static final int CONNECTION_ERROR_BROKEN = 6; // 0x6
+ field public static final int CONNECTION_ERROR_BUSY = 4; // 0x4
+ field public static final int CONNECTION_ERROR_TIMEOUT = 5; // 0x5
+ field public static final int CONNECTION_ERROR_UNAUTHORIZED = 2; // 0x2
+ field public static final int CONNECTION_ERROR_UNKNOWN = 0; // 0x0
+ field public static final int CONNECTION_ERROR_UNREACHABLE = 3; // 0x3
+ field public static final int CONNECTION_FLAG_BARGE = 1; // 0x1
+ field public static final int CONNECTION_STATE_CONNECTED = 2; // 0x2
+ field public static final int CONNECTION_STATE_CONNECTING = 1; // 0x1
+ field public static final int CONNECTION_STATE_DISCONNECTED = 0; // 0x0
+ field public static final int DISCONNECTION_REASON_APPLICATION_REQUEST = 0; // 0x0
+ field public static final int DISCONNECTION_REASON_ERROR = 2; // 0x2
+ field public static final int DISCONNECTION_REASON_USER_REQUEST = 1; // 0x1
+ field public static final int DISCOVERY_ERROR_ABORTED = 1; // 0x1
+ field public static final int DISCOVERY_ERROR_NO_CONNECTIVITY = 2; // 0x2
+ field public static final int DISCOVERY_ERROR_UNKNOWN = 0; // 0x0
+ field public static final int DISCOVERY_FLAG_BACKGROUND = 1; // 0x1
+ field public static final int DISCOVERY_STATE_STARTED = 1; // 0x1
+ field public static final int DISCOVERY_STATE_STOPPED = 0; // 0x0
+ field public static final int ROUTE_FEATURE_LIVE_AUDIO = 1; // 0x1
+ field public static final int ROUTE_FEATURE_LIVE_VIDEO = 2; // 0x2
+ }
+
+ public static final class MediaRouter.ConnectionInfo {
+ method public android.media.AudioAttributes getAudioAttributes();
+ method public android.os.Bundle getExtras();
+ method public int getFeatures();
+ method public android.view.Display getPresentationDisplay();
+ method public android.os.IBinder getProtocolBinder(java.lang.String);
+ method public android.os.IBinder getProtocolBinder(int);
+ method public T getProtocolObject(java.lang.Class<T>);
+ method public java.util.List<java.lang.String> getProtocols();
+ method public android.media.routing.MediaRouter.RouteInfo getRoute();
+ method public android.media.VolumeProvider getVolumeProvider();
+ }
+
+ public static final class MediaRouter.ConnectionInfo.Builder {
+ ctor public MediaRouter.ConnectionInfo.Builder(android.media.routing.MediaRouter.RouteInfo);
+ method public android.media.routing.MediaRouter.ConnectionInfo build();
+ method public android.media.routing.MediaRouter.ConnectionInfo.Builder setAudioAttributes(android.media.AudioAttributes);
+ method public android.media.routing.MediaRouter.ConnectionInfo.Builder setExtras(android.os.Bundle);
+ method public android.media.routing.MediaRouter.ConnectionInfo.Builder setPresentationDisplay(android.view.Display);
+ method public android.media.routing.MediaRouter.ConnectionInfo.Builder setProtocolBinder(java.lang.String, android.os.IBinder);
+ method public android.media.routing.MediaRouter.ConnectionInfo.Builder setProtocolStub(java.lang.Class<?>, android.os.IInterface);
+ method public android.media.routing.MediaRouter.ConnectionInfo.Builder setVolumeProvider(android.media.VolumeProvider);
+ }
+
+ public static final class MediaRouter.ConnectionRequest {
+ method public android.os.Bundle getExtras();
+ method public int getFlags();
+ method public android.media.routing.MediaRouter.RouteInfo getRoute();
+ method public void setExtras(android.os.Bundle);
+ method public void setFlags(int);
+ method public void setRoute(android.media.routing.MediaRouter.RouteInfo);
+ }
+
+ public static final class MediaRouter.Delegate {
+ ctor public MediaRouter.Delegate();
+ method public void addStateCallback(android.media.routing.MediaRouter.StateCallback, android.os.Handler);
+ method public void connect(android.media.routing.MediaRouter.DestinationInfo, int);
+ method public void disconnect(int);
+ method public int getConnectionState();
+ method public java.util.List<android.media.routing.MediaRouter.DestinationInfo> getDiscoveredDestinations();
+ method public int getDiscoveryState();
+ method public android.media.routing.MediaRouter.DestinationInfo getSelectedDestination();
+ method public boolean isReleased();
+ method public void removeStateCallback(android.media.routing.MediaRouter.StateCallback);
+ method public void startDiscovery(int);
+ method public void stopDiscovery();
+ }
+
+ public static final class MediaRouter.DestinationInfo {
+ method public java.lang.CharSequence getDescription();
+ method public android.os.Bundle getExtras();
+ method public int getIconResourceId();
+ method public java.lang.String getId();
+ method public java.lang.CharSequence getName();
+ method public android.media.routing.MediaRouter.ServiceMetadata getServiceMetadata();
+ method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
+ }
+
+ public static final class MediaRouter.DestinationInfo.Builder {
+ ctor public MediaRouter.DestinationInfo.Builder(java.lang.String, android.media.routing.MediaRouter.ServiceMetadata, java.lang.CharSequence);
+ method public android.media.routing.MediaRouter.DestinationInfo build();
+ method public android.media.routing.MediaRouter.DestinationInfo.Builder setDescription(java.lang.CharSequence);
+ method public android.media.routing.MediaRouter.DestinationInfo.Builder setExtras(android.os.Bundle);
+ method public android.media.routing.MediaRouter.DestinationInfo.Builder setIconResourceId(int);
+ }
+
+ public static final class MediaRouter.DiscoveryRequest {
+ method public int getFlags();
+ method public java.util.List<android.media.routing.MediaRouteSelector> getSelectors();
+ method public void setFlags(int);
+ method public void setSelectors(java.util.List<android.media.routing.MediaRouteSelector>);
+ }
+
+ public static final class MediaRouter.RouteInfo {
+ method public android.media.routing.MediaRouter.DestinationInfo getDestination();
+ method public android.os.Bundle getExtras();
+ method public int getFeatures();
+ method public java.lang.String getId();
+ method public java.util.List<java.lang.String> getProtocols();
+ method public android.media.routing.MediaRouteSelector getSelector();
+ }
+
+ public static final class MediaRouter.RouteInfo.Builder {
+ ctor public MediaRouter.RouteInfo.Builder(java.lang.String, android.media.routing.MediaRouter.DestinationInfo, android.media.routing.MediaRouteSelector);
+ method public android.media.routing.MediaRouter.RouteInfo.Builder addProtocol(java.lang.Class<T>);
+ method public android.media.routing.MediaRouter.RouteInfo.Builder addProtocol(java.lang.String);
+ method public android.media.routing.MediaRouter.RouteInfo build();
+ method public android.media.routing.MediaRouter.RouteInfo.Builder setExtras(android.os.Bundle);
+ method public android.media.routing.MediaRouter.RouteInfo.Builder setFeatures(int);
+ }
+
+ public static abstract class MediaRouter.RoutingCallback extends android.media.routing.MediaRouter.StateCallback {
+ ctor public MediaRouter.RoutingCallback();
+ method public boolean onPrepareConnectionRequest(android.media.routing.MediaRouter.ConnectionRequest, android.media.routing.MediaRouter.DestinationInfo, java.util.List<android.media.routing.MediaRouter.RouteInfo>);
+ method public boolean onPrepareDiscoveryRequest(android.media.routing.MediaRouter.DiscoveryRequest, java.util.List<android.media.routing.MediaRouteSelector>);
+ }
+
+ public static final class MediaRouter.ServiceMetadata {
+ method public android.content.ComponentName getComponentName();
+ method public android.graphics.drawable.Drawable getIcon(android.content.pm.PackageManager);
+ method public java.lang.CharSequence getLabel(android.content.pm.PackageManager);
+ method public java.lang.String getPackageName();
+ method public android.content.pm.ServiceInfo getService();
+ }
+
+ public static abstract class MediaRouter.StateCallback {
+ ctor public MediaRouter.StateCallback();
+ method public void onConnected();
+ method public void onConnecting();
+ method public void onConnectionFailed(int, java.lang.CharSequence, android.os.Bundle);
+ method public void onConnectionStateChanged(int);
+ method public void onDestinationFound(android.media.routing.MediaRouter.DestinationInfo);
+ method public void onDestinationLost(android.media.routing.MediaRouter.DestinationInfo);
+ method public void onDisconnected();
+ method public void onDiscoveryFailed(int, java.lang.CharSequence, android.os.Bundle);
+ method public void onDiscoveryStarted();
+ method public void onDiscoveryStateChanged(int);
+ method public void onDiscoveryStopped();
+ method public void onReleased();
+ method public void onSelectedDestinationChanged(android.media.routing.MediaRouter.DestinationInfo);
+ }
+
+}
+
package android.media.session {
public final class MediaController {
+ ctor public MediaController(android.media.session.MediaSession.Token);
method public void addCallback(android.media.session.MediaController.Callback);
method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
- method public void adjustVolumeBy(int, int);
+ method public void adjustVolume(int, int);
+ method public android.media.routing.MediaRouter.Delegate createMediaRouterDelegate();
method public boolean dispatchMediaButtonEvent(android.view.KeyEvent);
- method public static android.media.session.MediaController fromToken(android.media.session.MediaSession.Token);
method public android.media.MediaMetadata getMetadata();
method public android.media.session.PlaybackState getPlaybackState();
method public int getRatingType();
@@ -15918,6 +16285,7 @@
}
public final class MediaSession {
+ ctor public MediaSession(android.content.Context, java.lang.String);
method public void addCallback(android.media.session.MediaSession.Callback);
method public void addCallback(android.media.session.MediaSession.Callback, android.os.Handler);
method public void addTransportControlsCallback(android.media.session.MediaSession.TransportControlsCallback);
@@ -15931,6 +16299,7 @@
method public void setActive(boolean);
method public void setFlags(int);
method public void setLaunchPendingIntent(android.app.PendingIntent);
+ method public void setMediaRouter(android.media.routing.MediaRouter);
method public void setMetadata(android.media.MediaMetadata);
method public void setPlaybackState(android.media.session.PlaybackState);
method public void setPlaybackToLocal(int);
@@ -15968,7 +16337,6 @@
public final class MediaSessionManager {
method public void addActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener, android.content.ComponentName);
- method public android.media.session.MediaSession createSession(java.lang.String);
method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName);
}
@@ -15978,19 +16346,14 @@
}
public final class PlaybackState implements android.os.Parcelable {
- ctor public PlaybackState();
- ctor public PlaybackState(android.media.session.PlaybackState);
method public int describeContents();
method public long getActions();
method public long getBufferPosition();
method public java.lang.CharSequence getErrorMessage();
- method public float getPlaybackRate();
+ method public long getLastPositionUpdateTime();
+ method public float getPlaybackSpeed();
method public long getPosition();
method public int getState();
- method public void setActions(long);
- method public void setBufferPosition(long);
- method public void setErrorMessage(java.lang.CharSequence);
- method public void setState(int, long, float);
method public void writeToParcel(android.os.Parcel, int);
field public static final long ACTION_FAST_FORWARD = 64L; // 0x40L
field public static final long ACTION_PAUSE = 2L; // 0x2L
@@ -16005,6 +16368,7 @@
field public static final android.os.Parcelable.Creator CREATOR;
field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
field public static final int STATE_BUFFERING = 6; // 0x6
+ field public static final int STATE_CONNECTING = 8; // 0x8
field public static final int STATE_ERROR = 7; // 0x7
field public static final int STATE_FAST_FORWARDING = 4; // 0x4
field public static final int STATE_NONE = 0; // 0x0
@@ -16016,16 +16380,50 @@
field public static final int STATE_STOPPED = 1; // 0x1
}
+ public static final class PlaybackState.Builder {
+ ctor public PlaybackState.Builder();
+ ctor public PlaybackState.Builder(android.media.session.PlaybackState);
+ method public android.media.session.PlaybackState build();
+ method public android.media.session.PlaybackState.Builder setActions(long);
+ method public android.media.session.PlaybackState.Builder setBufferPosition(long);
+ method public android.media.session.PlaybackState.Builder setErrorMessage(java.lang.CharSequence);
+ method public android.media.session.PlaybackState.Builder setState(int, long, float, long);
+ method public android.media.session.PlaybackState.Builder setState(int, long, float);
+ }
+
}
package android.media.tv {
+ public class TvContentRating {
+ ctor public TvContentRating(java.lang.String);
+ ctor public TvContentRating(java.lang.String, java.lang.String[]);
+ method public java.lang.String flattenToString();
+ method public static android.media.tv.TvContentRating unflattenFromString(java.lang.String);
+ field public static final java.lang.String RATING_KR_12 = "RATING_KR_12";
+ field public static final java.lang.String RATING_KR_15 = "RATING_KR_15";
+ field public static final java.lang.String RATING_KR_19 = "RATING_KR_19";
+ field public static final java.lang.String RATING_KR_7 = "RATING_KR_7";
+ field public static final java.lang.String RATING_KR_ALL = "RATING_KR_ALL";
+ field public static final java.lang.String RATING_US_TV_14 = "RATING_US_TV_14";
+ field public static final java.lang.String RATING_US_TV_G = "RATING_US_TV_G";
+ field public static final java.lang.String RATING_US_TV_MA = "RATING_US_TV_MA";
+ field public static final java.lang.String RATING_US_TV_PG = "RATING_US_TV_PG";
+ field public static final java.lang.String RATING_US_TV_Y = "RATING_US_TV_Y";
+ field public static final java.lang.String RATING_US_TV_Y7 = "RATING_US_TV_Y7";
+ field public static final java.lang.String SUBRATING_US_D = "SUBRATING_US_D";
+ field public static final java.lang.String SUBRATING_US_FV = "SUBRATING_US_FV";
+ field public static final java.lang.String SUBRATING_US_L = "SUBRATING_US_L";
+ field public static final java.lang.String SUBRATING_US_S = "SUBRATING_US_S";
+ field public static final java.lang.String SUBRATING_US_V = "SUBRATING_US_V";
+ }
+
public final class TvContract {
method public static final android.net.Uri buildChannelLogoUri(long);
method public static final android.net.Uri buildChannelLogoUri(android.net.Uri);
method public static final android.net.Uri buildChannelUri(long);
- method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName);
- method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName, boolean);
+ method public static final android.net.Uri buildChannelsUriForInput(java.lang.String);
+ method public static final android.net.Uri buildChannelsUriForInput(java.lang.String, boolean);
method public static final android.net.Uri buildProgramUri(long);
method public static final android.net.Uri buildProgramsUriForChannel(long);
method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri);
@@ -16045,12 +16443,12 @@
field public static final java.lang.String COLUMN_DESCRIPTION = "description";
field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name";
field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number";
+ field public static final java.lang.String COLUMN_INPUT_ID = "input_id";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
field public static final java.lang.String COLUMN_NETWORK_AFFILIATION = "network_affiliation";
field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
- field public static final java.lang.String COLUMN_SERVICE_NAME = "service_name";
field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
field public static final java.lang.String COLUMN_TYPE = "type";
@@ -16114,6 +16512,7 @@
field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_CONTENT_RATING = "content_rating";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
@@ -16156,7 +16555,7 @@
method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
method public void writeToParcel(android.os.Parcel, int);
- field public static final java.lang.String EXTRA_SERVICE_NAME = "serviceName";
+ field public static final java.lang.String EXTRA_INPUT_ID = "inputId";
field public static final int TYPE_HDMI = 1; // 0x1
field public static final int TYPE_PASSTHROUGH = 3; // 0x3
field public static final int TYPE_TUNER = 2; // 0x2
@@ -16164,13 +16563,22 @@
}
public final class TvInputManager {
- method public boolean getAvailability(java.lang.String);
+ method public int getInputState(java.lang.String);
method public java.util.List<android.media.tv.TvInputInfo> getTvInputList();
+ method public void registerListener(android.media.tv.TvInputManager.TvInputListener, android.os.Handler);
+ method public void unregisterListener(android.media.tv.TvInputManager.TvInputListener);
+ field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
+ field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
+ field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
+ field public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3; // 0x3
+ field public static final int VIDEO_UNAVAILABLE_REASON_TUNE = 1; // 0x1
+ field public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0; // 0x0
+ field public static final int VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 2; // 0x2
}
public static abstract class TvInputManager.TvInputListener {
ctor public TvInputManager.TvInputListener();
- method public void onAvailabilityChanged(java.lang.String, boolean);
+ method public void onInputStateChanged(java.lang.String, int);
}
public abstract class TvInputService extends android.app.Service {
@@ -16185,6 +16593,8 @@
ctor public TvInputService.Session();
method public void dispatchChannelRetuned(android.net.Uri);
method public void dispatchTrackInfoChanged(java.util.List<android.media.tv.TvTrackInfo>);
+ method public void dispatchVideoAvailable();
+ method public void dispatchVideoUnavailable(int);
method public android.view.View onCreateOverlayView();
method public boolean onGenericMotionEvent(android.view.MotionEvent);
method public boolean onKeyDown(int, android.view.KeyEvent);
@@ -16262,7 +16672,9 @@
method public void onChannelRetuned(java.lang.String, android.net.Uri);
method public void onError(java.lang.String, int);
method public void onTrackInfoChanged(java.lang.String, java.util.List<android.media.tv.TvTrackInfo>);
+ method public void onVideoAvailable(java.lang.String);
method public void onVideoSizeChanged(java.lang.String, int, int);
+ method public void onVideoUnavailable(java.lang.String, int);
}
}
@@ -22688,7 +23100,7 @@
method protected void onDisconnected();
method protected abstract void onPrintJobQueued(android.printservice.PrintJob);
method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob);
- field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.PRINTER_INFO";
+ field public static final java.lang.String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
field public static final java.lang.String EXTRA_PRINT_JOB_INFO = "android.intent.extra.print.PRINT_JOB_INFO";
field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
@@ -24651,11 +25063,13 @@
field public static final java.lang.String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS";
field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS";
field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS";
+ field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+ field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
@@ -24998,9 +25412,11 @@
}
public static abstract interface Telephony.BaseMmsColumns implements android.provider.BaseColumns {
+ field public static final java.lang.String ARCHIVED = "archived";
field public static final java.lang.String CONTENT_CLASS = "ct_cls";
field public static final java.lang.String CONTENT_LOCATION = "ct_l";
field public static final java.lang.String CONTENT_TYPE = "ct_t";
+ field public static final java.lang.String CREATOR = "creator";
field public static final java.lang.String DATE = "date";
field public static final java.lang.String DATE_SENT = "date_sent";
field public static final java.lang.String DELIVERY_REPORT = "d_rpt";
@@ -25097,6 +25513,8 @@
public static final class Telephony.Mms.Intents {
field public static final java.lang.String CONTENT_CHANGED_ACTION = "android.intent.action.CONTENT_CHANGED";
field public static final java.lang.String DELETED_CONTENTS = "deleted_contents";
+ field public static final java.lang.String MMS_DOWNLOAD_ACTION = "android.provider.Telephony.MMS_DOWNLOAD";
+ field public static final java.lang.String MMS_SEND_ACTION = "android.provider.Telephony.MMS_SEND";
}
public static final class Telephony.Mms.Outbox implements android.provider.Telephony.BaseMmsColumns {
@@ -25200,8 +25618,10 @@
field public static final java.lang.String SMS_CB_RECEIVED_ACTION = "android.provider.Telephony.SMS_CB_RECEIVED";
field public static final java.lang.String SMS_DELIVER_ACTION = "android.provider.Telephony.SMS_DELIVER";
field public static final java.lang.String SMS_EMERGENCY_CB_RECEIVED_ACTION = "android.provider.Telephony.SMS_EMERGENCY_CB_RECEIVED";
+ field public static final java.lang.String SMS_FILTER_ACTION = "android.provider.Telephony.SMS_FILTER";
field public static final java.lang.String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";
field public static final java.lang.String SMS_REJECTED_ACTION = "android.provider.Telephony.SMS_REJECTED";
+ field public static final java.lang.String SMS_SEND_ACTION = "android.provider.Telephony.SMS_SEND";
field public static final java.lang.String SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION = "android.provider.Telephony.SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED";
field public static final java.lang.String WAP_PUSH_DELIVER_ACTION = "android.provider.Telephony.WAP_PUSH_DELIVER";
field public static final java.lang.String WAP_PUSH_RECEIVED_ACTION = "android.provider.Telephony.WAP_PUSH_RECEIVED";
@@ -25219,7 +25639,9 @@
public static abstract interface Telephony.TextBasedSmsColumns {
field public static final java.lang.String ADDRESS = "address";
+ field public static final java.lang.String ARCHIVED = "archived";
field public static final java.lang.String BODY = "body";
+ field public static final java.lang.String CREATOR = "creator";
field public static final java.lang.String DATE = "date";
field public static final java.lang.String DATE_SENT = "date_sent";
field public static final java.lang.String ERROR_CODE = "error_code";
@@ -25332,6 +25754,7 @@
field public static final java.lang.String NUMBER = "number";
field public static final java.lang.String SOURCE_DATA = "source_data";
field public static final java.lang.String SOURCE_PACKAGE = "source_package";
+ field public static final java.lang.String TRANSCRIPTION = "transcription";
}
}
@@ -26537,7 +26960,8 @@
method public int getAvailability();
method public android.content.Intent getManageIntent(int);
method public int getRecognitionStatus();
- method public int startRecognition();
+ method public int getSupportedRecognitionModes();
+ method public int startRecognition(int);
method public int stopRecognition();
field public static final int KEYPHRASE_ENROLLED = 2; // 0x2
field public static final int KEYPHRASE_HARDWARE_UNAVAILABLE = -2; // 0xfffffffe
@@ -26546,17 +26970,21 @@
field public static final int MANAGE_ACTION_ENROLL = 0; // 0x0
field public static final int MANAGE_ACTION_RE_ENROLL = 1; // 0x1
field public static final int MANAGE_ACTION_UN_ENROLL = 2; // 0x2
- field public static final int RECOGNITION_ACTIVE = 2; // 0x2
- field public static final int RECOGNITION_DISABLED_TEMPORARILY = -1; // 0xffffffff
- field public static final int RECOGNITION_NOT_AVAILABLE = -3; // 0xfffffffd
- field public static final int RECOGNITION_NOT_REQUESTED = -2; // 0xfffffffe
- field public static final int RECOGNITION_REQUESTED = 1; // 0x1
+ field public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 1; // 0x1
+ field public static final int RECOGNITION_FLAG_NONE = 0; // 0x0
+ field public static final int RECOGNITION_MODE_USER_IDENTIFICATION = 2; // 0x2
+ field public static final int RECOGNITION_MODE_VOICE_TRIGGER = 1; // 0x1
+ field public static final int RECOGNITION_STATUS_ACTIVE = 16; // 0x10
+ field public static final int RECOGNITION_STATUS_DISABLED_TEMPORARILY = 8; // 0x8
+ field public static final int RECOGNITION_STATUS_NOT_AVAILABLE = 1; // 0x1
+ field public static final int RECOGNITION_STATUS_NOT_REQUESTED = 2; // 0x2
+ field public static final int RECOGNITION_STATUS_REQUESTED = 4; // 0x4
field public static final int STATUS_ERROR = -2147483648; // 0x80000000
field public static final int STATUS_OK = 1; // 0x1
}
public static abstract interface AlwaysOnHotwordDetector.Callback {
- method public abstract void onDetected();
+ method public abstract void onDetected(byte[]);
method public abstract void onDetectionStarted();
method public abstract void onDetectionStopped();
}
@@ -26564,7 +26992,9 @@
public class VoiceInteractionService extends android.app.Service {
ctor public VoiceInteractionService();
method public final android.service.voice.AlwaysOnHotwordDetector getAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback);
+ method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
method public android.os.IBinder onBind(android.content.Intent);
+ method public void onReady();
method public void startSession(android.os.Bundle);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
@@ -27585,6 +28015,63 @@
package android.telecomm {
+ public final class Call {
+ method public void addListener(android.telecomm.Call.Listener);
+ method public void answer();
+ method public void conference();
+ method public void disconnect();
+ method public android.telecomm.RemoteCallVideoProvider getCallVideoProvider();
+ method public java.util.List<java.lang.String> getCannedTextResponses();
+ method public java.util.List<android.telecomm.Call> getChildren();
+ method public android.telecomm.Call.Details getDetails();
+ method public android.telecomm.Call getParent();
+ method public java.lang.String getRemainingPostDialSequence();
+ method public int getState();
+ method public void hold();
+ method public void phoneAccountClicked();
+ method public void playDtmfTone(char);
+ method public void postDialContinue(boolean);
+ method public void reject(boolean, java.lang.String);
+ method public void removeListener(android.telecomm.Call.Listener);
+ method public void splitFromConference();
+ method public void stopDtmfTone();
+ method public void swapWithBackgroundCall();
+ method public void unhold();
+ field public static final int STATE_ACTIVE = 4; // 0x4
+ field public static final int STATE_DIALING = 1; // 0x1
+ field public static final int STATE_DISCONNECTED = 7; // 0x7
+ field public static final int STATE_HOLDING = 3; // 0x3
+ field public static final int STATE_NEW = 0; // 0x0
+ field public static final int STATE_RINGING = 2; // 0x2
+ }
+
+ public static class Call.Details {
+ method public android.telecomm.PhoneAccount getAccount();
+ method public java.lang.String getCallerDisplayName();
+ method public int getCallerDisplayNamePresentation();
+ method public int getCapabilities();
+ method public long getConnectTimeMillis();
+ method public int getDisconnectCauseCode();
+ method public java.lang.String getDisconnectCauseMsg();
+ method public android.telecomm.GatewayInfo getGatewayInfo();
+ method public android.net.Uri getHandle();
+ method public int getHandlePresentation();
+ method public int getVideoState();
+ }
+
+ public static abstract class Call.Listener {
+ ctor public Call.Listener();
+ method public void onCallDestroyed(android.telecomm.Call);
+ method public void onCallVideoProviderChanged(android.telecomm.Call, android.telecomm.RemoteCallVideoProvider);
+ method public void onCannedTextResponsesLoaded(android.telecomm.Call, java.util.List<java.lang.String>);
+ method public void onChildrenChanged(android.telecomm.Call, java.util.List<android.telecomm.Call>);
+ method public void onDetailsChanged(android.telecomm.Call, android.telecomm.Call.Details);
+ method public void onParentChanged(android.telecomm.Call, android.telecomm.Call);
+ method public void onPostDial(android.telecomm.Call, java.lang.String);
+ method public void onPostDialWait(android.telecomm.Call, java.lang.String);
+ method public void onStateChanged(android.telecomm.Call, int);
+ }
+
public final class CallAudioState implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -27628,39 +28115,10 @@
public class CallPropertyPresentation {
ctor public CallPropertyPresentation();
- field public static final int ALLOWED = 0; // 0x0
- field public static final int PAYPHONE = 3; // 0x3
- field public static final int RESTRICTED = 1; // 0x1
- field public static final int UNKNOWN = 2; // 0x2
- }
-
- public final class CallServiceDescriptor implements android.os.Parcelable {
- method public int describeContents();
- method public java.lang.String getConnectionServiceId();
- method public int getNetworkType();
- method public android.content.ComponentName getServiceComponent();
- method public static android.telecomm.CallServiceDescriptor.Builder newBuilder(android.content.Context);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- field public static final int FLAG_MOBILE = 4; // 0x4
- field public static final int FLAG_PSTN = 2; // 0x2
- field public static final int FLAG_WIFI = 1; // 0x1
- }
-
- public static class CallServiceDescriptor.Builder {
- method public android.telecomm.CallServiceDescriptor build();
- method public android.telecomm.CallServiceDescriptor.Builder setConnectionService(java.lang.Class<? extends android.telecomm.ConnectionService>);
- method public android.telecomm.CallServiceDescriptor.Builder setNetworkType(int);
- }
-
- public final class CallServiceLookupResponse {
- method public void setCallServiceDescriptors(java.util.List<android.telecomm.CallServiceDescriptor>);
- }
-
- public abstract class CallServiceProvider extends android.app.Service {
- ctor protected CallServiceProvider();
- method public abstract void lookupCallServices(android.telecomm.CallServiceLookupResponse);
- method public android.os.IBinder onBind(android.content.Intent);
+ field public static final int ALLOWED = 1; // 0x1
+ field public static final int PAYPHONE = 4; // 0x4
+ field public static final int RESTRICTED = 2; // 0x2
+ field public static final int UNKNOWN = 3; // 0x3
}
public final class CallState extends java.lang.Enum {
@@ -27671,8 +28129,6 @@
enum_constant public static final android.telecomm.CallState DISCONNECTED;
enum_constant public static final android.telecomm.CallState NEW;
enum_constant public static final android.telecomm.CallState ON_HOLD;
- enum_constant public static final android.telecomm.CallState POST_DIAL;
- enum_constant public static final android.telecomm.CallState POST_DIAL_WAIT;
enum_constant public static final android.telecomm.CallState RINGING;
}
@@ -27782,7 +28238,8 @@
public abstract class ConnectionService extends android.app.Service {
ctor public ConnectionService();
- method public final void createRemoteOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.OutgoingCallResponse<android.telecomm.RemoteConnection>);
+ method public final void createRemoteIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse<android.telecomm.RemoteConnection>);
+ method public final void createRemoteOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse<android.telecomm.RemoteConnection>);
method public final java.util.Collection<android.telecomm.Connection> getAllConnections();
method public final void lookupRemoteAccounts(android.net.Uri, android.telecomm.SimpleResponse<android.net.Uri, java.util.List<android.telecomm.PhoneAccount>>);
method public final void maybeRespondToAccountLookup();
@@ -27790,11 +28247,11 @@
method protected void onConnectionAdded(android.telecomm.Connection);
method protected void onConnectionRemoved(android.telecomm.Connection);
method protected void onCreateConferenceConnection(java.lang.String, android.telecomm.Connection, android.telecomm.Response<java.lang.String, android.telecomm.Connection>);
- method protected void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.OutgoingCallResponse<android.telecomm.Connection>);
- method protected void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
+ method protected void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse<android.telecomm.Connection>);
+ method protected void onCreateOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.ConnectionService.CreateConnectionResponse<android.telecomm.Connection>);
}
- public static abstract interface ConnectionService.OutgoingCallResponse {
+ public static abstract interface ConnectionService.CreateConnectionResponse {
method public abstract void onCancel(android.telecomm.ConnectionRequest);
method public abstract void onFailure(android.telecomm.ConnectionRequest, int, java.lang.String);
method public abstract void onSuccess(android.telecomm.ConnectionRequest, CONNECTION);
@@ -27834,7 +28291,6 @@
method public java.util.List<java.lang.String> getCannedSmsResponses();
method public int getCapabilities();
method public long getConnectTimeMillis();
- method public android.telecomm.CallServiceDescriptor getCurrentCallServiceDescriptor();
method public int getDisconnectCauseCode();
method public java.lang.String getDisconnectCauseMsg();
method public android.telecomm.GatewayInfo getGatewayInfo();
@@ -27843,35 +28299,57 @@
method public java.lang.String getId();
method public android.telecomm.CallState getState();
method public android.telecomm.StatusHints getStatusHints();
+ method public int getVideoState();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
- public abstract class InCallService extends android.app.Service {
+ public abstract class InCallService {
ctor protected InCallService();
- method protected abstract void addCall(android.telecomm.InCallCall);
- method protected abstract void bringToForeground(boolean);
- method protected final android.telecomm.InCallAdapter getAdapter();
- method protected void onAdapterAttached(android.telecomm.InCallAdapter);
- method protected abstract void onAudioStateChanged(android.telecomm.CallAudioState);
- method public final android.os.IBinder onBind(android.content.Intent);
- method protected abstract void setPostDial(java.lang.String, java.lang.String);
- method protected abstract void setPostDialWait(java.lang.String, java.lang.String);
- method protected abstract void updateCall(android.telecomm.InCallCall);
+ method public final android.os.IBinder getBinder();
+ method public android.telecomm.Phone getPhone();
+ method public void onPhoneCreated(android.telecomm.Phone);
+ method public void onPhoneDestroyed(android.telecomm.Phone);
}
- public final class PhoneAccount implements android.os.Parcelable {
- ctor public PhoneAccount(android.content.ComponentName, java.lang.String, android.net.Uri, java.lang.String, java.lang.String, boolean, boolean);
+ public final class Phone {
+ method public final void addListener(android.telecomm.Phone.Listener);
+ method public final android.telecomm.CallAudioState getAudioState();
+ method public final java.util.List<android.telecomm.Call> getCalls();
+ method public final void removeListener(android.telecomm.Phone.Listener);
+ method public final void setAudioRoute(int);
+ method public final void setMuted(boolean);
+ }
+
+ public static abstract class Phone.Listener {
+ ctor public Phone.Listener();
+ method public void onAudioStateChanged(android.telecomm.Phone, android.telecomm.CallAudioState);
+ method public void onBringToForeground(android.telecomm.Phone, boolean);
+ method public void onCallAdded(android.telecomm.Phone, android.telecomm.Call);
+ method public void onCallRemoved(android.telecomm.Phone, android.telecomm.Call);
+ }
+
+ public class PhoneAccount implements android.os.Parcelable {
+ ctor public PhoneAccount(android.content.ComponentName, java.lang.String, android.net.Uri, int);
method public int describeContents();
+ method public int getCapabilities();
method public android.content.ComponentName getComponentName();
method public android.net.Uri getHandle();
- method public android.graphics.drawable.Drawable getIcon(android.content.Context);
- method public android.graphics.drawable.Drawable getIcon(android.content.Context, int);
method public java.lang.String getId();
- method public java.lang.String getLabel(android.content.Context);
- method public java.lang.String getShortDescription(android.content.Context);
- method public boolean isEnabled();
- method public boolean isSystemDefault();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CAPABILITY_CALL_PROVIDER = 2; // 0x2
+ field public static final int CAPABILITY_SIM_CALL_MANAGER = 1; // 0x1
+ field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public class PhoneAccountMetadata implements android.os.Parcelable {
+ ctor public PhoneAccountMetadata(android.telecomm.PhoneAccount, int, java.lang.String, java.lang.String);
+ method public int describeContents();
+ method public android.telecomm.PhoneAccount getAccount();
+ method public android.graphics.drawable.Drawable getIcon(android.content.Context);
+ method public java.lang.String getLabel();
+ method public java.lang.String getShortDescription();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
@@ -27886,18 +28364,17 @@
method public void updatePeerDimensions(int, int) throws android.os.RemoteException;
}
- public class RemoteCallVideoProvider implements android.os.IBinder.DeathRecipient {
- method public void binderDied();
- method public void requestCallDataUsage() throws android.os.RemoteException;
- method public void requestCameraCapabilities() throws android.os.RemoteException;
- method public void sendSessionModifyRequest(android.telecomm.VideoCallProfile) throws android.os.RemoteException;
- method public void sendSessionModifyResponse(android.telecomm.VideoCallProfile) throws android.os.RemoteException;
- method public void setCallVideoClient(android.telecomm.CallVideoClient) throws android.os.RemoteException;
+ public class RemoteCallVideoProvider {
+ method public void requestCallDataUsage();
+ method public void requestCameraCapabilities();
+ method public void sendSessionModifyRequest(android.telecomm.VideoCallProfile);
+ method public void sendSessionModifyResponse(android.telecomm.VideoCallProfile);
+ method public void setCallVideoClient(android.telecomm.CallVideoClient);
method public void setCamera(java.lang.String) throws android.os.RemoteException;
- method public void setDeviceOrientation(int) throws android.os.RemoteException;
- method public void setDisplaySurface(android.view.Surface) throws android.os.RemoteException;
- method public void setPauseImage(java.lang.String) throws android.os.RemoteException;
- method public void setPreviewSurface(android.view.Surface) throws android.os.RemoteException;
+ method public void setDeviceOrientation(int);
+ method public void setDisplaySurface(android.view.Surface);
+ method public void setPauseImage(java.lang.String);
+ method public void setPreviewSurface(android.view.Surface);
method public void setZoom(float) throws android.os.RemoteException;
}
@@ -27964,20 +28441,28 @@
public final class TelecommConstants {
ctor public TelecommConstants();
- field public static final java.lang.String ACTION_CALL_SERVICE_PROVIDER;
field public static final java.lang.String ACTION_CONNECTION_SERVICE;
+ field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
field public static final java.lang.String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecomm.extra.CALL_DISCONNECT_CAUSE";
field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecomm.extra.CALL_DISCONNECT_MESSAGE";
- field public static final java.lang.String EXTRA_CALL_SERVICE_DESCRIPTOR = "android.intent.extra.CALL_SERVICE_DESCRIPTOR";
field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecomm.extra.CONNECTION_SERVICE";
field public static final java.lang.String EXTRA_INCOMING_CALL_EXTRAS = "android.intent.extra.INCOMING_CALL_EXTRAS";
+ field public static final java.lang.String EXTRA_PHONE_ACCOUNT = "android.intent.extra.PHONE_ACCOUNT";
field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.intent.extra.START_CALL_WITH_SPEAKERPHONE";
field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.intent.extra.START_CALL_WITH_VIDEO_STATE";
}
+ public class TelecommManager {
+ method public void clearAccounts(java.lang.String);
+ method public java.util.List<android.telecomm.PhoneAccount> getEnabledPhoneAccounts();
+ method public android.telecomm.PhoneAccountMetadata getPhoneAccountMetadata(android.telecomm.PhoneAccount);
+ method public void registerPhoneAccount(android.telecomm.PhoneAccount, android.telecomm.PhoneAccountMetadata);
+ method public void unregisterPhoneAccount(android.telecomm.PhoneAccount);
+ }
+
public class VideoCallProfile implements android.os.Parcelable {
ctor public VideoCallProfile(int, int);
method public int describeContents();
@@ -28195,6 +28680,44 @@
field public static final int VOICEMAIL_NUMBER_MISSING = 40; // 0x28
}
+ public class MessagingConfigurationManager {
+ method public boolean getCarrierConfigBoolean(java.lang.String, boolean);
+ method public int getCarrierConfigInt(java.lang.String, int);
+ method public java.lang.String getCarrierConfigString(java.lang.String, java.lang.String);
+ method public static android.telephony.MessagingConfigurationManager getDefault();
+ method public void setCarrierConfigBoolean(java.lang.String, boolean);
+ method public void setCarrierConfigInt(java.lang.String, int);
+ method public void setCarrierConfigString(java.lang.String, java.lang.String);
+ field public static final java.lang.String CONF_ALIAS_ENABLED = "aliasEnabled";
+ field public static final java.lang.String CONF_ALIAS_MAX_CHARS = "aliasMaxChars";
+ field public static final java.lang.String CONF_ALIAS_MIN_CHARS = "aliasMinChars";
+ field public static final java.lang.String CONF_ALLOW_ATTACH_AUDIO = "allowAttachAudio";
+ field public static final java.lang.String CONF_APPEND_TRANSACTION_ID = "enabledTransID";
+ field public static final java.lang.String CONF_EMAIL_GATEWAY_NUMBER = "emailGatewayNumber";
+ field public static final java.lang.String CONF_HTTP_PARAMS = "httpParams";
+ field public static final java.lang.String CONF_HTTP_SOCKET_TIMEOUT = "httpSocketTimeout";
+ field public static final java.lang.String CONF_MAX_IMAGE_HEIGHT = "maxImageHeight";
+ field public static final java.lang.String CONF_MAX_IMAGE_WIDTH = "maxImageWidth";
+ field public static final java.lang.String CONF_MAX_MESSAGE_SIZE = "maxMessageSize";
+ field public static final java.lang.String CONF_MESSAGE_TEXT_MAX_SIZE = "maxMessageTextSize";
+ field public static final java.lang.String CONF_MMS_DELIVERY_REPORT_ENABLED = "enableMMSDeliveryReports";
+ field public static final java.lang.String CONF_MMS_ENABLED = "enabledMMS";
+ field public static final java.lang.String CONF_MMS_READ_REPORT_ENABLED = "enableMMSReadReports";
+ field public static final java.lang.String CONF_MULTIPART_SMS_ENABLED = "enableMultipartSMS";
+ field public static final java.lang.String CONF_NAI_SUFFIX = "naiSuffix";
+ field public static final java.lang.String CONF_NOTIFY_WAP_MMSC_ENABLED = "enabledNotifyWapMMSC";
+ field public static final java.lang.String CONF_RECIPIENT_LIMIT = "recipientLimit";
+ field public static final java.lang.String CONF_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES = "sendMultipartSmsAsSeparateMessages";
+ field public static final java.lang.String CONF_SMS_DELIVERY_REPORT_ENABLED = "enableSMSDeliveryReports";
+ field public static final java.lang.String CONF_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD = "smsToMmsTextLengthThreshold";
+ field public static final java.lang.String CONF_SMS_TO_MMS_TEXT_THRESHOLD = "smsToMmsTextThreshold";
+ field public static final java.lang.String CONF_SUBJECT_MAX_LENGTH = "maxSubjectLength";
+ field public static final java.lang.String CONF_SUPPORT_MMS_CONTENT_DISPOSITION = "supportMmsContentDisposition";
+ field public static final java.lang.String CONF_UA_PROF_TAG_NAME = "uaProfTagName";
+ field public static final java.lang.String CONF_UA_PROF_URL = "uaProfUrl";
+ field public static final java.lang.String CONF_USER_AGENT = "userAgent";
+ }
+
public class NeighboringCellInfo implements android.os.Parcelable {
ctor public deprecated NeighboringCellInfo();
ctor public deprecated NeighboringCellInfo(int, int);
@@ -28337,15 +28860,43 @@
}
public final class SmsManager {
+ method public android.net.Uri addMultimediaMessageDraft(byte[]);
+ method public android.net.Uri addTextMessageDraft(java.lang.String, java.lang.String);
+ method public boolean deleteStoredConversation(long);
+ method public boolean deleteStoredMessage(android.net.Uri);
method public java.util.ArrayList<java.lang.String> divideMessage(java.lang.String);
+ method public void downloadMultimediaMessage(java.lang.String, android.app.PendingIntent);
+ method public boolean getAutoPersisting();
method public static android.telephony.SmsManager getDefault();
+ method public android.net.Uri importMultimediaMessage(byte[], java.lang.String, long, boolean, boolean);
+ method public android.net.Uri importTextMessage(java.lang.String, int, java.lang.String, long, boolean, boolean);
+ method public void injectSmsPdu(byte[], java.lang.String, android.app.PendingIntent);
method public void sendDataMessage(java.lang.String, java.lang.String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
+ method public void sendMultimediaMessage(byte[], java.lang.String, android.app.PendingIntent);
method public void sendMultipartTextMessage(java.lang.String, java.lang.String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
+ method public void sendStoredMultimediaMessage(android.net.Uri, android.app.PendingIntent);
+ method public void sendStoredMultipartTextMessage(android.net.Uri, java.lang.String, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
+ method public void sendStoredTextMessage(android.net.Uri, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
method public void sendTextMessage(java.lang.String, java.lang.String, java.lang.String, android.app.PendingIntent, android.app.PendingIntent);
+ method public void setAutoPersisting(boolean);
+ method public void updateMmsDownloadStatus(int, byte[]);
+ method public void updateMmsSendStatus(int, boolean);
+ method public void updateSmsSendStatus(int, boolean);
+ method public boolean updateStoredMessageStatus(android.net.Uri, android.content.ContentValues);
+ field public static final java.lang.String MESSAGE_STATUS_ARCHIVED = "archived";
+ field public static final java.lang.String MESSAGE_STATUS_READ = "read";
+ field public static final java.lang.String MESSAGE_STATUS_SEEN = "seen";
+ field public static final int MMS_ERROR_HTTP_FAILURE = 4; // 0x4
+ field public static final int MMS_ERROR_INVALID_APN = 2; // 0x2
+ field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3
+ field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1
+ field public static final java.lang.String MMS_EXTRA_DATA = "data";
field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4
field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3
field public static final int RESULT_ERROR_RADIO_OFF = 2; // 0x2
+ field public static final int SMS_TYPE_INCOMING = 0; // 0x0
+ field public static final int SMS_TYPE_OUTGOING = 1; // 0x1
field public static final int STATUS_ON_ICC_FREE = 0; // 0x0
field public static final int STATUS_ON_ICC_READ = 1; // 0x1
field public static final int STATUS_ON_ICC_SENT = 5; // 0x5
@@ -28412,8 +28963,10 @@
}
public class TelephonyManager {
- method public java.util.List<android.telecomm.PhoneAccount> getAccounts();
+ method public void enableSimplifiedNetworkSettings(boolean);
+ method public void enableSimplifiedNetworkSettings(long, boolean);
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+ method public int getCalculatedPreferredNetworkType();
method public int getCallState();
method public android.telephony.CellLocation getCellLocation();
method public int getDataActivity();
@@ -28430,19 +28983,30 @@
method public java.lang.String getNetworkOperatorName();
method public int getNetworkType();
method public int getPhoneType();
+ method public int getPreferredNetworkType();
method public java.lang.String getSimCountryIso();
method public java.lang.String getSimOperator();
method public java.lang.String getSimOperatorName();
method public java.lang.String getSimSerialNumber();
method public int getSimState();
+ method public boolean getSimplifiedNetworkSettingsEnabled();
+ method public boolean getSimplifiedNetworkSettingsEnabled(long);
method public java.lang.String getSubscriberId();
method public java.lang.String getVoiceMailAlphaTag();
method public java.lang.String getVoiceMailNumber();
method public int hasCarrierPrivileges();
method public boolean hasIccCard();
+ method public boolean iccCloseLogicalChannel(int);
+ method public int iccOpenLogicalChannel(java.lang.String);
+ method public java.lang.String iccTransmitApduLogicalChannel(int, int, int, int, int, int, java.lang.String);
method public boolean isNetworkRoaming();
method public boolean isSmsCapable();
method public void listen(android.telephony.PhoneStateListener, int);
+ method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public boolean setCdmaSubscription(int);
+ method public void setLine1NumberForDisplay(java.lang.String, java.lang.String);
+ method public void setLine1NumberForDisplay(long, java.lang.String, java.lang.String);
+ method public boolean setPreferredNetworkType(int);
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
field public static final int CALL_STATE_IDLE = 0; // 0x0
@@ -28461,7 +29025,6 @@
field public static final int DATA_CONNECTING = 1; // 0x1
field public static final int DATA_DISCONNECTED = 0; // 0x0
field public static final int DATA_SUSPENDED = 3; // 0x3
- field public static final java.lang.String EXTRA_ACCOUNT = "account";
field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
field public static final java.lang.String EXTRA_STATE = "state";
field public static final java.lang.String EXTRA_STATE_IDLE;
@@ -28966,6 +29529,7 @@
method public android.content.res.AssetManager getAssets();
method public java.io.File getCacheDir();
method public java.lang.ClassLoader getClassLoader();
+ method public java.io.File getCodeCacheDir();
method public android.content.ContentResolver getContentResolver();
method public java.io.File getDatabasePath(java.lang.String);
method public java.io.File getDir(java.lang.String, int);
@@ -28977,6 +29541,7 @@
method public java.io.File getFileStreamPath(java.lang.String);
method public java.io.File getFilesDir();
method public android.os.Looper getMainLooper();
+ method public java.io.File getNoBackupFilesDir();
method public java.io.File getObbDir();
method public java.io.File[] getObbDirs();
method public java.lang.String getPackageCodePath();
@@ -29113,8 +29678,10 @@
method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+ method public android.content.pm.PackageInstaller getInstaller();
method public java.lang.String getInstallerPackageName(java.lang.String);
method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public android.content.pm.KeySet getKeySetByAlias(java.lang.String, java.lang.String);
method public android.content.Intent getLaunchIntentForPackage(java.lang.String);
method public android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
method public java.lang.String getNameForUid(int);
@@ -29132,12 +29699,15 @@
method public android.content.res.Resources getResourcesForApplication(android.content.pm.ApplicationInfo);
method public android.content.res.Resources getResourcesForApplication(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
method public android.content.pm.ServiceInfo getServiceInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public android.content.pm.KeySet getSigningKeySet(java.lang.String);
method public android.content.pm.FeatureInfo[] getSystemAvailableFeatures();
method public java.lang.String[] getSystemSharedLibraryNames();
method public java.lang.CharSequence getText(java.lang.String, int, android.content.pm.ApplicationInfo);
method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
method public boolean hasSystemFeature(java.lang.String);
method public boolean isSafeMode();
+ method public boolean isSignedBy(java.lang.String, android.content.pm.KeySet);
+ method public boolean isSignedByExactly(java.lang.String, android.content.pm.KeySet);
method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
method public java.util.List<android.content.pm.ProviderInfo> queryContentProviders(java.lang.String, int, int);
method public java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(java.lang.String, int);
@@ -34027,6 +34597,7 @@
method protected final int getForcedWindowFlags();
method public abstract android.view.LayoutInflater getLayoutInflater();
method protected final int getLocalFeatures();
+ method public android.media.session.MediaController getMediaController();
method public abstract int getNavigationBarColor();
method public android.transition.Transition getSharedElementEnterTransition();
method public android.transition.Transition getSharedElementExitTransition();
@@ -34083,6 +34654,7 @@
method public void setLayout(int, int);
method public void setLocalFocus(boolean, boolean);
method public void setLogo(int);
+ method public void setMediaController(android.media.session.MediaController);
method public abstract void setNavigationBarColor(int);
method public void setSharedElementEnterTransition(android.transition.Transition);
method public void setSharedElementExitTransition(android.transition.Transition);
@@ -35754,14 +36326,28 @@
method public abstract void onReceivedIcon(java.lang.String, android.graphics.Bitmap);
}
+ public abstract interface WebResourceRequest {
+ method public abstract java.lang.String getMethod();
+ method public abstract java.util.Map<java.lang.String, java.lang.String> getRequestHeaders();
+ method public abstract android.net.Uri getUrl();
+ method public abstract boolean hasUserGestureInsecure();
+ method public abstract boolean isForMainFrame();
+ }
+
public class WebResourceResponse {
ctor public WebResourceResponse(java.lang.String, java.lang.String, java.io.InputStream);
+ ctor public WebResourceResponse(java.lang.String, java.lang.String, int, java.lang.String, java.util.Map<java.lang.String, java.lang.String>, java.io.InputStream);
method public java.io.InputStream getData();
method public java.lang.String getEncoding();
method public java.lang.String getMimeType();
+ method public java.lang.String getReasonPhrase();
+ method public java.util.Map<java.lang.String, java.lang.String> getResponseHeaders();
+ method public int getStatusCode();
method public void setData(java.io.InputStream);
method public void setEncoding(java.lang.String);
method public void setMimeType(java.lang.String);
+ method public void setResponseHeaders(java.util.Map<java.lang.String, java.lang.String>);
+ method public void setStatusCodeAndReasonPhrase(int, java.lang.String);
}
public abstract class WebSettings {
@@ -36085,7 +36671,8 @@
method public deprecated void onTooManyRedirects(android.webkit.WebView, android.os.Message, android.os.Message);
method public void onUnhandledInputEvent(android.webkit.WebView, android.view.InputEvent);
method public deprecated void onUnhandledKeyEvent(android.webkit.WebView, android.view.KeyEvent);
- method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, java.lang.String);
+ method public deprecated android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, java.lang.String);
+ method public android.webkit.WebResourceResponse shouldInterceptRequest(android.webkit.WebView, android.webkit.WebResourceRequest);
method public boolean shouldOverrideKeyEvent(android.webkit.WebView, android.view.KeyEvent);
method public boolean shouldOverrideUrlLoading(android.webkit.WebView, java.lang.String);
field public static final int ERROR_AUTHENTICATION = -4; // 0xfffffffc
@@ -36749,8 +37336,16 @@
ctor public DatePicker(android.content.Context, android.util.AttributeSet);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int);
ctor public DatePicker(android.content.Context, android.util.AttributeSet, int, int);
+ method public android.content.res.ColorStateList getCalendarTextColor();
method public android.widget.CalendarView getCalendarView();
method public boolean getCalendarViewShown();
+ method public int getDateSelectorBackgroundColor();
+ method public int getDateSelectorDayOfMonthTextAppearance();
+ method public int getDateSelectorDayOfWeekBackgroundColor();
+ method public int getDateSelectorDayOfWeekTextAppearance();
+ method public int getDateSelectorMonthTextAppearance();
+ method public int getDateSelectorYearListItemTextAppearance();
+ method public int getDateSelectorYearTextAppearance();
method public int getDayOfMonth();
method public long getMaxDate();
method public long getMinDate();
@@ -36758,7 +37353,15 @@
method public boolean getSpinnersShown();
method public int getYear();
method public void init(int, int, int, android.widget.DatePicker.OnDateChangedListener);
+ method public void setCalendarTextColor(android.content.res.ColorStateList);
method public void setCalendarViewShown(boolean);
+ method public void setDateSelectorBackgroundColor(int);
+ method public void setDateSelectorDayOfMonthTextAppearance(int);
+ method public void setDateSelectorDayOfWeekBackgroundColor(int);
+ method public void setDateSelectorDayOfWeekTextAppearance(int);
+ method public void setDateSelectorMonthTextAppearance(int);
+ method public void setDateSelectorYearListItemTextAppearance(int);
+ method public void setDateSelectorYearTextAppearance(int);
method public void setMaxDate(long);
method public void setMinDate(long);
method public void setSpinnersShown(boolean);
diff --git a/cmds/media/src/com/android/commands/media/Media.java b/cmds/media/src/com/android/commands/media/Media.java
index 4e91361..c771f65 100644
--- a/cmds/media/src/com/android/commands/media/Media.java
+++ b/cmds/media/src/com/android/commands/media/Media.java
@@ -25,7 +25,6 @@
import android.media.session.MediaController;
import android.media.session.MediaSessionInfo;
import android.media.session.PlaybackState;
-import android.media.session.RouteInfo;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -115,7 +114,7 @@
List<IBinder> sessions = mSessionService
.getSessions(null, ActivityManager.getCurrentUser());
for (IBinder session : sessions) {
- MediaController controller = MediaController.fromBinder(ISessionController.Stub
+ MediaController controller = new MediaController(ISessionController.Stub
.asInterface(session));
if (controller != null && controller.getSessionInfo().getId().equals(id)) {
ControllerMonitor monitor = new ControllerMonitor(controller);
@@ -181,11 +180,6 @@
}
@Override
- public void onRouteChanged(RouteInfo route) {
- System.out.println("onRouteChanged " + route);
- }
-
- @Override
public void onPlaybackStateChanged(PlaybackState state) {
System.out.println("onPlaybackStateChanged " + state);
}
@@ -254,7 +248,7 @@
List<IBinder> sessions = mSessionService
.getSessions(null, ActivityManager.getCurrentUser());
for (IBinder session : sessions) {
- MediaController controller = MediaController.fromBinder(ISessionController.Stub
+ MediaController controller = new MediaController(ISessionController.Stub
.asInterface(session));
if (controller != null) {
MediaSessionInfo info = controller.getSessionInfo();
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 3d0eec4..d6c17ae 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -50,6 +50,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.content.PackageHelper;
@@ -923,33 +924,13 @@
return;
}
} else if (opt.equals("--abi")) {
- abi = nextOptionData();
- if (abi == null) {
- System.err.println("Error: must supply argument for --abi");
- return;
- }
+ abi = checkAbiArgument(nextOptionData());
} else {
System.err.println("Error: Unknown option: " + opt);
return;
}
}
- if (abi != null) {
- final String[] supportedAbis = Build.SUPPORTED_ABIS;
- boolean matched = false;
- for (String supportedAbi : supportedAbis) {
- if (supportedAbi.equals(abi)) {
- matched = true;
- break;
- }
- }
-
- if (!matched) {
- System.err.println("Error: abi " + abi + " not supported on this device.");
- return;
- }
- }
-
final Uri verificationURI;
final Uri originatingURI;
final Uri referrerURI;
@@ -1017,8 +998,8 @@
final InstallSessionParams params = new InstallSessionParams();
params.installFlags = PackageManager.INSTALL_ALL_USERS;
- params.fullInstall = true;
- params.progressMax = -1;
+ params.setModeFullInstall();
+ params.setProgressMax(-1);
String opt;
while ((opt = nextOption()) != null) {
@@ -1040,10 +1021,13 @@
} else if (opt.equals("-d")) {
params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
} else if (opt.equals("-p")) {
- params.fullInstall = false;
+ params.setModeInheritExisting();
} else if (opt.equals("-S")) {
- params.deltaSize = Long.parseLong(nextOptionData());
- params.progressMax = (int) params.deltaSize;
+ final long deltaSize = Long.parseLong(nextOptionData());
+ params.setDeltaSize(deltaSize);
+ params.setProgressMax((int) params.deltaSize);
+ } else if (opt.equals("--abi")) {
+ params.abiOverride = checkAbiArgument(nextOptionData());
} else {
throw new IllegalArgumentException("Unknown option " + opt);
}
@@ -1684,6 +1668,21 @@
}
}
+ private static String checkAbiArgument(String abi) {
+ if (TextUtils.isEmpty(abi)) {
+ throw new IllegalArgumentException("Missing ABI argument");
+ }
+
+ final String[] supportedAbis = Build.SUPPORTED_ABIS;
+ for (String supportedAbi : supportedAbis) {
+ if (supportedAbi.equals(abi)) {
+ return abi;
+ }
+ }
+
+ throw new IllegalArgumentException("ABI " + abi + " not supported on this device");
+ }
+
private String nextOption() {
if (mNextArg >= mArgs.length) {
return null;
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 129e52c..95f83ac 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -356,6 +356,22 @@
public void setTarget(Object target) {
}
+ // Hide reverse() and canReverse() for now since reverse() only work for simple
+ // cases, like we don't support sequential, neither startDelay.
+ // TODO: make reverse() works for all the Animators.
+ /**
+ * @hide
+ */
+ public boolean canReverse() {
+ return false;
+ }
+
+ /**
+ * @hide
+ */
+ public void reverse() {
+ }
+
/**
* <p>An animation listener receives notifications from an animation.
* Notifications indicate animation related events, such as the end or the
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 018a2d6..9156eeb 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -124,7 +124,7 @@
// was set on this AnimatorSet, so it should not be passed down to the children.
private TimeInterpolator mInterpolator = null;
-
+ private boolean mReversible = true;
/**
* Sets up this AnimatorSet to play all of the supplied animations at the same time.
* This is equivalent to calling {@link #play(Animator)} with the first animator in the
@@ -177,6 +177,7 @@
if (items.length == 1) {
play(items[0]);
} else {
+ mReversible = false;
for (int i = 0; i < items.length - 1; ++i) {
play(items[i]).before(items[i+1]);
}
@@ -196,6 +197,7 @@
if (items.size() == 1) {
play(items.get(0));
} else {
+ mReversible = false;
for (int i = 0; i < items.size() - 1; ++i) {
play(items.get(i)).before(items.get(i+1));
}
@@ -407,6 +409,9 @@
*/
@Override
public void setStartDelay(long startDelay) {
+ if (mStartDelay > 0) {
+ mReversible = false;
+ }
mStartDelay = startDelay;
}
@@ -512,7 +517,7 @@
node.animation.setInterpolator(mInterpolator);
}
}
- // First, sort the nodes (if necessary). This will ensure that sortedNodes
+ // First, sort the nodes (if necessary). This will ensure that sortedNodes
// contains the animation nodes in the correct order.
sortNodes();
@@ -626,6 +631,7 @@
anim.mNodeMap = new HashMap<Animator, Node>();
anim.mNodes = new ArrayList<Node>();
anim.mSortedNodes = new ArrayList<Node>();
+ anim.mReversible = mReversible;
// Walk through the old nodes list, cloning each node and adding it to the new nodemap.
// One problem is that the old node dependencies point to nodes in the old AnimatorSet.
@@ -908,6 +914,35 @@
}
/**
+ * @hide
+ */
+ @Override
+ public boolean canReverse() {
+ if (!mReversible) {
+ return false;
+ }
+ // Loop to make sure all the Nodes can reverse.
+ for (Node node : mNodes) {
+ if (!node.animation.canReverse() || node.animation.getStartDelay() > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void reverse() {
+ if (canReverse()) {
+ for (Node node : mNodes) {
+ node.animation.reverse();
+ }
+ }
+ }
+
+ /**
* Dependency holds information about the node that some other node is
* dependent upon and the nature of that dependency.
*
@@ -1124,6 +1159,7 @@
* {@link AnimatorSet#play(Animator)} method ends.
*/
public Builder before(Animator anim) {
+ mReversible = false;
Node node = mNodeMap.get(anim);
if (node == null) {
node = new Node(anim);
@@ -1144,6 +1180,7 @@
* {@link AnimatorSet#play(Animator)} method to play.
*/
public Builder after(Animator anim) {
+ mReversible = false;
Node node = mNodeMap.get(anim);
if (node == null) {
node = new Node(anim);
diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java
index 377b5a05..2d87e13 100644
--- a/core/java/android/animation/FloatKeyframeSet.java
+++ b/core/java/android/animation/FloatKeyframeSet.java
@@ -57,6 +57,11 @@
return newSet;
}
+ @Override
+ void invalidateCache() {
+ firstTime = true;
+ }
+
public float getFloatValue(float fraction) {
if (mNumKeyframes == 2) {
if (firstTime) {
diff --git a/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java
index 7b7c876..ce47e2b 100644
--- a/core/java/android/animation/IntKeyframeSet.java
+++ b/core/java/android/animation/IntKeyframeSet.java
@@ -57,6 +57,11 @@
return newSet;
}
+ @Override
+ void invalidateCache() {
+ firstTime = true;
+ }
+
public int getIntValue(float fraction) {
if (mNumKeyframes == 2) {
if (firstTime) {
diff --git a/core/java/android/animation/Keyframe.java b/core/java/android/animation/Keyframe.java
index dc8538f..5483c49 100644
--- a/core/java/android/animation/Keyframe.java
+++ b/core/java/android/animation/Keyframe.java
@@ -35,6 +35,20 @@
*/
public abstract class Keyframe implements Cloneable {
/**
+ * Flag to indicate whether this keyframe has a valid value. This flag is used when an
+ * animation first starts, to populate placeholder keyframes with real values derived
+ * from the target object.
+ */
+ boolean mHasValue;
+
+ /**
+ * Flag to indicate whether the value in the keyframe was read from the target object or not.
+ * If so, its value will be recalculated if target changes.
+ */
+ boolean mValueWasSetOnStart;
+
+
+ /**
* The time at which mValue will hold true.
*/
float mFraction;
@@ -51,12 +65,7 @@
*/
private TimeInterpolator mInterpolator = null;
- /**
- * Flag to indicate whether this keyframe has a valid value. This flag is used when an
- * animation first starts, to populate placeholder keyframes with real values derived
- * from the target object.
- */
- boolean mHasValue = false;
+
/**
* Constructs a Keyframe object with the given time and value. The time defines the
@@ -166,6 +175,20 @@
}
/**
+ * If the Keyframe's value was acquired from the target object, this flag should be set so that,
+ * if target changes, value will be reset.
+ *
+ * @return boolean Whether this Keyframe's value was retieved from the target object or not.
+ */
+ boolean valueWasSetOnStart() {
+ return mValueWasSetOnStart;
+ }
+
+ void setValueWasSetOnStart(boolean valueWasSetOnStart) {
+ mValueWasSetOnStart = valueWasSetOnStart;
+ }
+
+ /**
* Gets the value for this Keyframe.
*
* @return The value for this Keyframe.
@@ -261,7 +284,8 @@
@Override
public ObjectKeyframe clone() {
- ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), mHasValue ? mValue : null);
+ ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), hasValue() ? mValue : null);
+ kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
kfClone.setInterpolator(getInterpolator());
return kfClone;
}
@@ -310,6 +334,7 @@
new IntKeyframe(getFraction(), mValue) :
new IntKeyframe(getFraction());
kfClone.setInterpolator(getInterpolator());
+ kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
return kfClone;
}
}
@@ -356,6 +381,7 @@
new FloatKeyframe(getFraction(), mValue) :
new FloatKeyframe(getFraction());
kfClone.setInterpolator(getInterpolator());
+ kfClone.mValueWasSetOnStart = mValueWasSetOnStart;
return kfClone;
}
}
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index 4026f7f..a3db3a1 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -48,6 +48,13 @@
mInterpolator = mLastKeyframe.getInterpolator();
}
+ /**
+ * If subclass has variables that it calculates based on the Keyframes, it should reset them
+ * when this method is called because Keyframe contents might have changed.
+ */
+ void invalidateCache() {
+ }
+
public static KeyframeSet ofInt(int... values) {
int numKeyframes = values.length;
IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)];
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index da56a77..a4ac73f 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -883,10 +883,7 @@
final Object oldTarget = getTarget();
if (oldTarget != target) {
mTarget = target == null ? null : new WeakReference<Object>(target);
- if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) {
- return;
- }
- // New target type should cause re-initialization prior to starting
+ // New target should cause re-initialization prior to starting
mInitialized = false;
}
}
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index bf2924c..73b83ef 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -631,6 +631,9 @@
public void setObjectValues(Object... values) {
mValueType = values[0].getClass();
mKeyframeSet = KeyframeSet.ofObject(values);
+ if (mEvaluator != null) {
+ mKeyframeSet.setEvaluator(mEvaluator);
+ }
}
/**
@@ -772,16 +775,18 @@
* @param target The object on which the setter (and possibly getter) exist.
*/
void setupSetterAndGetter(Object target) {
+ mKeyframeSet.invalidateCache();
if (mProperty != null) {
// check to make sure that mProperty is on the class of target
try {
Object testValue = null;
for (Keyframe kf : mKeyframeSet.mKeyframes) {
- if (!kf.hasValue()) {
+ if (!kf.hasValue() || kf.valueWasSetOnStart()) {
if (testValue == null) {
testValue = convertBack(mProperty.get(target));
}
kf.setValue(testValue);
+ kf.setValueWasSetOnStart(true);
}
}
return;
@@ -796,7 +801,7 @@
setupSetter(targetClass);
}
for (Keyframe kf : mKeyframeSet.mKeyframes) {
- if (!kf.hasValue()) {
+ if (!kf.hasValue() || kf.valueWasSetOnStart()) {
if (mGetter == null) {
setupGetter(targetClass);
if (mGetter == null) {
@@ -807,6 +812,7 @@
try {
Object value = convertBack(mGetter.invoke(target));
kf.setValue(value);
+ kf.setValueWasSetOnStart(true);
} catch (InvocationTargetException e) {
Log.e("PropertyValuesHolder", e.toString());
} catch (IllegalAccessException e) {
diff --git a/core/java/android/animation/StateListAnimator.java b/core/java/android/animation/StateListAnimator.java
index 810f050..7256a06 100644
--- a/core/java/android/animation/StateListAnimator.java
+++ b/core/java/android/animation/StateListAnimator.java
@@ -57,6 +57,7 @@
private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ animation.setTarget(null);
if (mRunningAnimator == animation) {
mRunningAnimator = null;
}
@@ -151,7 +152,7 @@
private void start(Tuple match) {
match.mAnimator.setTarget(getTarget());
- mRunningAnimator = match.mAnimator.clone();
+ mRunningAnimator = match.mAnimator;
mRunningAnimator.start();
}
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 5338dd0..e3380a9 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1038,6 +1038,7 @@
* play backwards. This behavior is only set for the current animation; future playing
* of the animation will use the default behavior of playing forward.
*/
+ @Override
public void reverse() {
mPlayingBackwards = !mPlayingBackwards;
if (mPlayingState == RUNNING) {
@@ -1053,6 +1054,14 @@
}
/**
+ * @hide
+ */
+ @Override
+ public boolean canReverse() {
+ return true;
+ }
+
+ /**
* Called internally to end an animation by removing it from the animations list. Must be
* called on the UI thread.
*/
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index f1a2576..cac646d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -23,6 +23,7 @@
import android.util.ArrayMap;
import android.util.SuperNotCalledException;
import android.widget.Toolbar;
+
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.WindowDecorActionBar;
import com.android.internal.app.ToolbarActionBar;
@@ -51,6 +52,8 @@
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -109,14 +112,14 @@
* or embedded inside of another activity (using {@link ActivityGroup}).
*
* There are two methods almost all subclasses of Activity will implement:
- *
+ *
* <ul>
* <li> {@link #onCreate} is where you initialize your activity. Most
* importantly, here you will usually call {@link #setContentView(int)}
* with a layout resource defining your UI, and using {@link #findViewById}
* to retrieve the widgets in that UI that you need to interact with
* programmatically.
- *
+ *
* <li> {@link #onPause} is where you deal with the user leaving your
* activity. Most importantly, any changes made by the user should at this
* point be committed (usually to the
@@ -127,7 +130,7 @@
* activity classes must have a corresponding
* {@link android.R.styleable#AndroidManifestActivity <activity>}
* declaration in their package's <code>AndroidManifest.xml</code>.</p>
- *
+ *
* <p>Topics covered here:
* <ol>
* <li><a href="#Fragments">Fragments</a>
@@ -170,14 +173,14 @@
* and becomes the running activity -- the previous activity always remains
* below it in the stack, and will not come to the foreground again until
* the new activity exits.</p>
- *
+ *
* <p>An activity has essentially four states:</p>
* <ul>
* <li> If an activity in the foreground of the screen (at the top of
* the stack),
* it is <em>active</em> or <em>running</em>. </li>
* <li>If an activity has lost focus but is still visible (that is, a new non-full-sized
- * or transparent activity has focus on top of your activity), it
+ * or transparent activity has focus on top of your activity), it
* is <em>paused</em>. A paused activity is completely alive (it
* maintains all state and member information and remains attached to
* the window manager), but can be killed by the system in extreme
@@ -197,13 +200,13 @@
* The square rectangles represent callback methods you can implement to
* perform operations when the Activity moves between states. The colored
* ovals are major states the Activity can be in.</p>
- *
+ *
* <p><img src="../../../images/activity_lifecycle.png"
* alt="State diagram for an Android Activity Lifecycle." border="0" /></p>
- *
+ *
* <p>There are three key loops you may be interested in monitoring within your
* activity:
- *
+ *
* <ul>
* <li>The <b>entire lifetime</b> of an activity happens between the first call
* to {@link android.app.Activity#onCreate} through to a single final call
@@ -212,7 +215,7 @@
* onDestroy(). For example, if it has a thread running in the background
* to download data from the network, it may create that thread in onCreate()
* and then stop the thread in onDestroy().
- *
+ *
* <li>The <b>visible lifetime</b> of an activity happens between a call to
* {@link android.app.Activity#onStart} until a corresponding call to
* {@link android.app.Activity#onStop}. During this time the user can see the
@@ -224,7 +227,7 @@
* longer sees what you are displaying. The onStart() and onStop() methods
* can be called multiple times, as the activity becomes visible and hidden
* to the user.
- *
+ *
* <li>The <b>foreground lifetime</b> of an activity happens between a call to
* {@link android.app.Activity#onResume} until a corresponding call to
* {@link android.app.Activity#onPause}. During this time the activity is
@@ -234,7 +237,7 @@
* intent is delivered -- so the code in these methods should be fairly
* lightweight.
* </ul>
- *
+ *
* <p>The entire lifecycle of an activity is defined by the following
* Activity methods. All of these are hooks that you can override
* to do appropriate work when the activity changes state. All
@@ -250,7 +253,7 @@
* protected void onCreate(Bundle savedInstanceState);
*
* protected void onStart();
- *
+ *
* protected void onRestart();
*
* protected void onResume();
@@ -366,7 +369,7 @@
* {@link #onSaveInstanceState(Bundle)} is called before placing the activity
* in such a background state, allowing you to save away any dynamic instance
* state in your activity into the given Bundle, to be later received in
- * {@link #onCreate} if the activity needs to be re-created.
+ * {@link #onCreate} if the activity needs to be re-created.
* See the <a href="#ProcessLifecycle">Process Lifecycle</a>
* section for more information on how the lifecycle of a process is tied
* to the activities it is hosting. Note that it is important to save
@@ -390,14 +393,14 @@
*
* <a name="ConfigurationChanges"></a>
* <h3>Configuration Changes</h3>
- *
+ *
* <p>If the configuration of the device (as defined by the
* {@link Configuration Resources.Configuration} class) changes,
* then anything displaying a user interface will need to update to match that
* configuration. Because Activity is the primary mechanism for interacting
* with the user, it includes special support for handling configuration
* changes.</p>
- *
+ *
* <p>Unless you specify otherwise, a configuration change (such as a change
* in screen orientation, language, input devices, etc) will cause your
* current activity to be <em>destroyed</em>, going through the normal activity
@@ -407,7 +410,7 @@
* called in that instance then a new instance of the activity will be
* created, with whatever savedInstanceState the previous instance had generated
* from {@link #onSaveInstanceState}.</p>
- *
+ *
* <p>This is done because any application resource,
* including layout files, can change based on any configuration value. Thus
* the only safe way to handle a configuration change is to re-retrieve all
@@ -415,7 +418,7 @@
* must already know how to save their state and re-create themselves from
* that state, this is a convenient way to have an activity restart itself
* with a new configuration.</p>
- *
+ *
* <p>In some special cases, you may want to bypass restarting of your
* activity based on one or more types of configuration changes. This is
* done with the {@link android.R.attr#configChanges android:configChanges}
@@ -425,7 +428,7 @@
* a configuration change involves any that you do not handle, however, the
* activity will still be restarted and {@link #onConfigurationChanged}
* will not be called.</p>
- *
+ *
* <a name="StartingActivities"></a>
* <h3>Starting Activities and Getting Results</h3>
*
@@ -440,10 +443,10 @@
* ends. For example, you may start an activity that lets the user pick
* a person in a list of contacts; when it ends, it returns the person
* that was selected. To do this, you call the
- * {@link android.app.Activity#startActivityForResult(Intent, int)}
- * version with a second integer parameter identifying the call. The result
+ * {@link android.app.Activity#startActivityForResult(Intent, int)}
+ * version with a second integer parameter identifying the call. The result
* will come back through your {@link android.app.Activity#onActivityResult}
- * method.</p>
+ * method.</p>
*
* <p>When an activity exits, it can call
* {@link android.app.Activity#setResult(int)}
@@ -570,17 +573,17 @@
*
* protected void onPause() {
* super.onPause();
- *
+ *
* SharedPreferences.Editor ed = mPrefs.edit();
* ed.putInt("view_mode", mCurViewMode);
* ed.commit();
* }
* }
* </pre>
- *
+ *
* <a name="Permissions"></a>
* <h3>Permissions</h3>
- *
+ *
* <p>The ability to start a particular Activity can be enforced when it is
* declared in its
* manifest's {@link android.R.styleable#AndroidManifestActivity <activity>}
@@ -601,10 +604,10 @@
*
* <p>See the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
* document for more information on permissions and security in general.
- *
+ *
* <a name="ProcessLifecycle"></a>
* <h3>Process Lifecycle</h3>
- *
+ *
* <p>The Android system attempts to keep application process around for as
* long as possible, but eventually will need to remove old processes when
* memory runs low. As described in <a href="#ActivityLifecycle">Activity
@@ -614,7 +617,7 @@
* listed here in order of importance. The system will kill less important
* processes (the last ones) before it resorts to killing more important
* processes (the first ones).
- *
+ *
* <ol>
* <li> <p>The <b>foreground activity</b> (the activity at the top of the screen
* that the user is currently interacting with) is considered the most important.
@@ -642,7 +645,7 @@
* context of an activity BroadcastReceiver or Service to ensure that the system
* knows it needs to keep your process around.
* </ol>
- *
+ *
* <p>Sometimes an Activity may need to do a long-running operation that exists
* independently of the activity lifecycle itself. An example may be a camera
* application that allows you to upload a picture to a web site. The upload
@@ -720,7 +723,7 @@
VoiceInteractor voiceInteractor;
}
/* package */ NonConfigurationInstances mLastNonConfigurationInstances;
-
+
private Window mWindow;
private WindowManager mWindowManager;
@@ -764,7 +767,7 @@
private final ArrayList<ManagedCursor> mManagedCursors =
new ArrayList<ManagedCursor>();
- // protected by synchronized (this)
+ // protected by synchronized (this)
int mResultCode = RESULT_CANCELED;
Intent mResultData = null;
@@ -775,7 +778,7 @@
private int mDefaultKeyMode = DEFAULT_KEYS_DISABLE;
private SpannableStringBuilder mDefaultKeySsb = null;
-
+
protected static final int[] FOCUSED_STATE_SET = {com.android.internal.R.attr.state_focused};
@SuppressWarnings("unused")
@@ -793,16 +796,16 @@
return mIntent;
}
- /**
- * Change the intent returned by {@link #getIntent}. This holds a
- * reference to the given intent; it does not copy it. Often used in
- * conjunction with {@link #onNewIntent}.
- *
- * @param newIntent The new Intent object to return from getIntent
- *
+ /**
+ * Change the intent returned by {@link #getIntent}. This holds a
+ * reference to the given intent; it does not copy it. Often used in
+ * conjunction with {@link #onNewIntent}.
+ *
+ * @param newIntent The new Intent object to return from getIntent
+ *
* @see #getIntent
* @see #onNewIntent
- */
+ */
public void setIntent(Intent newIntent) {
mIntent = newIntent;
}
@@ -816,7 +819,7 @@
public final boolean isChild() {
return mParent != null;
}
-
+
/** Return the parent activity if this view is an embedded child. */
public final Activity getParent() {
return mParent;
@@ -831,7 +834,7 @@
* Retrieve the current {@link android.view.Window} for the activity.
* This can be used to directly access parts of the Window API that
* are not available through Activity/Screen.
- *
+ *
* @return Window The current window, or null if the activity is not
* visual.
*/
@@ -850,7 +853,7 @@
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);
return mLoaderManager;
}
-
+
LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
if (mAllLoaderManagers == null) {
mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>();
@@ -866,13 +869,13 @@
}
return lm;
}
-
+
/**
* Calls {@link android.view.Window#getCurrentFocus} on the
* Window of this Activity to return the currently focused view.
- *
+ *
* @return View The current View with focus or null.
- *
+ *
* @see #getWindow
* @see android.view.Window#getCurrentFocus
*/
@@ -888,20 +891,20 @@
* with widgets in the UI, calling
* {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve
* cursors for data being displayed, etc.
- *
+ *
* <p>You can call {@link #finish} from within this function, in
* which case onDestroy() will be immediately called without any of the rest
* of the activity lifecycle ({@link #onStart}, {@link #onResume},
* {@link #onPause}, etc) executing.
- *
+ *
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @param savedInstanceState If the activity is being re-initialized after
* previously being shut down then this Bundle contains the data it most
* recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b>
- *
+ *
* @see #onStart
* @see #onSaveInstanceState
* @see #onRestoreInstanceState
@@ -996,12 +999,12 @@
* decide whether to use your default implementation. The default
* implementation of this method performs a restore of any view state that
* had previously been frozen by {@link #onSaveInstanceState}.
- *
+ *
* <p>This method is called between {@link #onStart} and
* {@link #onPostCreate}.
- *
+ *
* @param savedInstanceState the data most recently supplied in {@link #onSaveInstanceState}.
- *
+ *
* @see #onCreate
* @see #onPostCreate
* @see #onResume
@@ -1098,11 +1101,11 @@
* and {@link #onRestoreInstanceState} have been called). Applications will
* generally not implement this method; it is intended for system
* classes to do final initialization after application code has run.
- *
+ *
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @param savedInstanceState If the activity is being re-initialized after
* previously being shut down then this Bundle contains the data it most
* recently supplied in {@link #onSaveInstanceState}. <b><i>Note: Otherwise it is null.</i></b>
@@ -1133,14 +1136,14 @@
}
/**
- * Called after {@link #onCreate} — or after {@link #onRestart} when
- * the activity had been stopped, but is now again being displayed to the
+ * Called after {@link #onCreate} — or after {@link #onRestart} when
+ * the activity had been stopped, but is now again being displayed to the
* user. It will be followed by {@link #onResume}.
*
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @see #onCreate
* @see #onStop
* @see #onResume
@@ -1148,7 +1151,7 @@
protected void onStart() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStart " + this);
mCalled = true;
-
+
if (!mLoadersStarted) {
mLoadersStarted = true;
if (mLoaderManager != null) {
@@ -1173,11 +1176,11 @@
* this is usually the place
* where the cursor should be requeried (because you had deactivated it in
* {@link #onStop}.
- *
+ *
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @see #onStop
* @see #onStart
* @see #onResume
@@ -1200,7 +1203,7 @@
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @see #onRestoreInstanceState
* @see #onRestart
* @see #onPostResume
@@ -1218,11 +1221,11 @@
* been called). Applications will generally not implement this method;
* it is intended for system classes to do final setup after application
* resume code has run.
- *
+ *
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @see #onResume
*/
protected void onPostResume() {
@@ -1256,19 +1259,19 @@
* activity is re-launched while at the top of the activity stack instead
* of a new instance of the activity being started, onNewIntent() will be
* called on the existing instance with the Intent that was used to
- * re-launch it.
- *
- * <p>An activity will always be paused before receiving a new intent, so
- * you can count on {@link #onResume} being called after this method.
- *
- * <p>Note that {@link #getIntent} still returns the original Intent. You
- * can use {@link #setIntent} to update it to this new Intent.
- *
- * @param intent The new intent that was started for the activity.
- *
+ * re-launch it.
+ *
+ * <p>An activity will always be paused before receiving a new intent, so
+ * you can count on {@link #onResume} being called after this method.
+ *
+ * <p>Note that {@link #getIntent} still returns the original Intent. You
+ * can use {@link #setIntent} to update it to this new Intent.
+ *
+ * @param intent The new intent that was started for the activity.
+ *
* @see #getIntent
- * @see #setIntent
- * @see #onResume
+ * @see #setIntent
+ * @see #onResume
*/
protected void onNewIntent(Intent intent) {
}
@@ -1342,9 +1345,9 @@
*
* <p>If called, this method will occur before {@link #onStop}. There are
* no guarantees about whether it will occur before or after {@link #onPause}.
- *
+ *
* @param outState Bundle in which to place your saved state.
- *
+ *
* @see #onCreate
* @see #onRestoreInstanceState
* @see #onPause
@@ -1429,23 +1432,23 @@
* noticeable amount of CPU in order to make the switch to the next activity
* as fast as possible, or to close resources that are exclusive access
* such as the camera.
- *
+ *
* <p>In situations where the system needs more memory it may kill paused
* processes to reclaim resources. Because of this, you should be sure
* that all of your state is saved by the time you return from
* this function. In general {@link #onSaveInstanceState} is used to save
* per-instance state in the activity and this method is used to store
* global persistent data (in content providers, files, etc.)
- *
+ *
* <p>After receiving this call you will usually receive a following call
* to {@link #onStop} (after the next activity has been resumed and
* displayed), however in some cases there will be a direct call back to
* {@link #onResume} without going through the stopped state.
- *
+ *
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @see #onResume
* @see #onSaveInstanceState
* @see #onStop
@@ -1464,32 +1467,32 @@
* brought to the foreground, {@link #onUserLeaveHint} will not be called on
* the activity being interrupted. In cases when it is invoked, this method
* is called right before the activity's {@link #onPause} callback.
- *
+ *
* <p>This callback and {@link #onUserInteraction} are intended to help
* activities manage status bar notifications intelligently; specifically,
* for helping activities determine the proper time to cancel a notfication.
- *
+ *
* @see #onUserInteraction()
*/
protected void onUserLeaveHint() {
}
-
+
/**
* Generate a new thumbnail for this activity. This method is called before
* pausing the activity, and should draw into <var>outBitmap</var> the
* imagery for the desired thumbnail in the dimensions of that bitmap. It
* can use the given <var>canvas</var>, which is configured to draw into the
* bitmap, for rendering if desired.
- *
+ *
* <p>The default implementation returns fails and does not draw a thumbnail;
* this will result in the platform creating its own thumbnail if needed.
- *
+ *
* @param outBitmap The bitmap to contain the thumbnail.
* @param canvas Can be used to render into the bitmap.
- *
+ *
* @return Return true if you have drawn into the bitmap; otherwise after
* you return it will be filled with a default thumbnail.
- *
+ *
* @see #onCreateDescription
* @see #onSaveInstanceState
* @see #onPause
@@ -1502,15 +1505,15 @@
* Generate a new description for this activity. This method is called
* before pausing the activity and can, if desired, return some textual
* description of its current state to be displayed to the user.
- *
+ *
* <p>The default implementation returns null, which will cause you to
* inherit the description from the previous activity. If all activities
* return null, generally the label of the top activity will be used as the
* description.
- *
+ *
* @return A description of what the user is doing. It should be short and
* sweet (only a few words).
- *
+ *
* @see #onCreateThumbnail
* @see #onSaveInstanceState
* @see #onPause
@@ -1538,15 +1541,15 @@
* Called when you are no longer visible to the user. You will next
* receive either {@link #onRestart}, {@link #onDestroy}, or nothing,
* depending on later user activity.
- *
+ *
* <p>Note that this method may never be called, in low memory situations
* where the system does not have enough memory to keep your activity's
* process running after its {@link #onPause} method is called.
- *
+ *
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @see #onRestart
* @see #onResume
* @see #onSaveInstanceState
@@ -1567,7 +1570,7 @@
* {@link #finish} on it, or because the system is temporarily destroying
* this instance of the activity to save space. You can distinguish
* between these two scenarios with the {@link #isFinishing} method.
- *
+ *
* <p><em>Note: do not count on this method being called as a place for
* saving data! For example, if an activity is editing data in a content
* provider, those edits should be committed in either {@link #onPause} or
@@ -1579,11 +1582,11 @@
* calling this method (or any others) in it, so it should not be used to
* do things that are intended to remain around after the process goes
* away.
- *
+ *
* <p><em>Derived classes must call through to the super class's
* implementation of this method. If they do not, an exception will be
* thrown.</em></p>
- *
+ *
* @see #onPause
* @see #onStop
* @see #finish
@@ -1657,11 +1660,11 @@
* by that attribute, then instead of reporting it the system will stop
* and restart the activity (to have it launched with the new
* configuration).
- *
+ *
* <p>At the time that this function has been called, your Resources
* object will have been updated to return resource values matching the
* new configuration.
- *
+ *
* @param newConfig The new device configuration.
*/
public void onConfigurationChanged(Configuration newConfig) {
@@ -1681,7 +1684,7 @@
mActionBar.onConfigurationChanged(newConfig);
}
}
-
+
/**
* If this activity is being destroyed because it can not handle a
* configuration parameter being changed (and thus its
@@ -1691,7 +1694,7 @@
* destroyed. Note that there is no guarantee that these will be
* accurate (other changes could have happened at any time), so you should
* only use this as an optimization hint.
- *
+ *
* @return Returns a bit field of the configuration parameters that are
* changing, as defined by the {@link android.content.res.Configuration}
* class.
@@ -1699,21 +1702,21 @@
public int getChangingConfigurations() {
return mConfigChangeFlags;
}
-
+
/**
* Retrieve the non-configuration instance data that was previously
* returned by {@link #onRetainNonConfigurationInstance()}. This will
* be available from the initial {@link #onCreate} and
* {@link #onStart} calls to the new instance, allowing you to extract
* any useful dynamic state from the previous instance.
- *
+ *
* <p>Note that the data you retrieve here should <em>only</em> be used
* as an optimization for handling configuration changes. You should always
* be able to handle getting a null pointer back, and an activity must
* still be able to restore itself to its previous state (through the
* normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
* function returns null.
- *
+ *
* @return Returns the object previously returned by
* {@link #onRetainNonConfigurationInstance()}.
*
@@ -1727,7 +1730,7 @@
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
-
+
/**
* Called by the system, as part of destroying an
* activity due to a configuration change, when it is known that a new
@@ -1736,7 +1739,7 @@
* itself, which can later be retrieved by calling
* {@link #getLastNonConfigurationInstance()} in the new activity
* instance.
- *
+ *
* <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
* or later, consider instead using a {@link Fragment} with
* {@link Fragment#setRetainInstance(boolean)
@@ -1756,14 +1759,14 @@
* the {@link #getLastNonConfigurationInstance()} method of the following
* activity instance as described there.
* </ul>
- *
+ *
* <p>These guarantees are designed so that an activity can use this API
* to propagate extensive state from the old to new activity instance, from
* loaded bitmaps, to network connections, to evenly actively running
* threads. Note that you should <em>not</em> propagate any data that
* may change based on the configuration, including any data loaded from
* resources such as strings, layouts, or drawables.
- *
+ *
* <p>The guarantee of no message handling during the switch to the next
* activity simplifies use with active objects. For example if your retained
* state is an {@link android.os.AsyncTask} you are guaranteed that its
@@ -1783,21 +1786,21 @@
public Object onRetainNonConfigurationInstance() {
return null;
}
-
+
/**
* Retrieve the non-configuration instance data that was previously
* returned by {@link #onRetainNonConfigurationChildInstances()}. This will
* be available from the initial {@link #onCreate} and
* {@link #onStart} calls to the new instance, allowing you to extract
* any useful dynamic state from the previous instance.
- *
+ *
* <p>Note that the data you retrieve here should <em>only</em> be used
* as an optimization for handling configuration changes. You should always
* be able to handle getting a null pointer back, and an activity must
* still be able to restore itself to its previous state (through the
* normal {@link #onSaveInstanceState(Bundle)} mechanism) even if this
* function returns null.
- *
+ *
* @return Returns the object previously returned by
* {@link #onRetainNonConfigurationChildInstances()}
*/
@@ -1806,7 +1809,7 @@
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.children : null;
}
-
+
/**
* This method is similar to {@link #onRetainNonConfigurationInstance()} except that
* it should return either a mapping from child activity id strings to arbitrary objects,
@@ -1818,7 +1821,7 @@
HashMap<String,Object> onRetainNonConfigurationChildInstances() {
return null;
}
-
+
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
HashMap<String, Object> children = onRetainNonConfigurationChildInstances();
@@ -1846,7 +1849,7 @@
&& mVoiceInteractor == null) {
return null;
}
-
+
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
nci.children = children;
@@ -1886,7 +1889,7 @@
}
}
}
-
+
/**
* Called when a Fragment is being attached to this activity, immediately
* after the call to its {@link Fragment#onAttach Fragment.onAttach()}
@@ -1894,14 +1897,14 @@
*/
public void onAttachFragment(Fragment fragment) {
}
-
+
/**
* Wrapper around
* {@link ContentResolver#query(android.net.Uri , String[], String, String[], String)}
* that gives the resulting {@link Cursor} to call
* {@link #startManagingCursor} so that the activity will manage its
* lifecycle for you.
- *
+ *
* <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
* or later, consider instead using {@link LoaderManager} instead, available
* via {@link #getLoaderManager()}.</em>
@@ -1911,14 +1914,14 @@
* you call {@link #stopManagingCursor} on a cursor from a managed query, the system <em>will
* not</em> automatically close the cursor and, in that case, you must call
* {@link Cursor#close()}.</p>
- *
+ *
* @param uri The URI of the content provider to query.
* @param projection List of columns to return.
* @param selection SQL WHERE clause.
* @param sortOrder SQL ORDER BY clause.
- *
+ *
* @return The Cursor that was returned by query().
- *
+ *
* @see ContentResolver#query(android.net.Uri , String[], String, String[], String)
* @see #startManagingCursor
* @hide
@@ -1941,7 +1944,7 @@
* that gives the resulting {@link Cursor} to call
* {@link #startManagingCursor} so that the activity will manage its
* lifecycle for you.
- *
+ *
* <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
* or later, consider instead using {@link LoaderManager} instead, available
* via {@link #getLoaderManager()}.</em>
@@ -1951,15 +1954,15 @@
* you call {@link #stopManagingCursor} on a cursor from a managed query, the system <em>will
* not</em> automatically close the cursor and, in that case, you must call
* {@link Cursor#close()}.</p>
- *
+ *
* @param uri The URI of the content provider to query.
* @param projection List of columns to return.
* @param selection SQL WHERE clause.
* @param selectionArgs The arguments to selection, if any ?s are pesent
* @param sortOrder SQL ORDER BY clause.
- *
+ *
* @return The Cursor that was returned by query().
- *
+ *
* @see ContentResolver#query(android.net.Uri , String[], String, String[], String)
* @see #startManagingCursor
*
@@ -1982,7 +1985,7 @@
* {@link Cursor#deactivate} on the given Cursor, and when it is later restarted
* it will call {@link Cursor#requery} for you. When the activity is
* destroyed, all managed Cursors will be closed automatically.
- *
+ *
* <em>If you are targeting {@link android.os.Build.VERSION_CODES#HONEYCOMB}
* or later, consider instead using {@link LoaderManager} instead, available
* via {@link #getLoaderManager()}.</em>
@@ -1992,9 +1995,9 @@
* However, if you call {@link #stopManagingCursor} on a cursor from a managed query, the system
* <em>will not</em> automatically close the cursor and, in that case, you must call
* {@link Cursor#close()}.</p>
- *
+ *
* @param c The Cursor to be managed.
- *
+ *
* @see #managedQuery(android.net.Uri , String[], String, String[], String)
* @see #stopManagingCursor
*
@@ -2013,13 +2016,13 @@
* Given a Cursor that was previously given to
* {@link #startManagingCursor}, stop the activity's management of that
* cursor.
- *
+ *
* <p><strong>Warning:</strong> After calling this method on a cursor from a managed query,
- * the system <em>will not</em> automatically close the cursor and you must call
+ * the system <em>will not</em> automatically close the cursor and you must call
* {@link Cursor#close()}.</p>
- *
+ *
* @param c The Cursor that was being managed.
- *
+ *
* @see #startManagingCursor
*
* @deprecated Use the new {@link android.content.CursorLoader} class with
@@ -2058,7 +2061,7 @@
public View findViewById(int id) {
return getWindow().findViewById(id);
}
-
+
/**
* Retrieve a reference to this activity's ActionBar.
*
@@ -2094,7 +2097,7 @@
mActionBar = new ToolbarActionBar(toolbar, getTitle(), this);
mActionBar.invalidateOptionsMenu();
}
-
+
/**
* Creates a new ActionBar, locates the inflated ActionBarView,
* initializes the ActionBar with the view, and sets mActionBar.
@@ -2116,13 +2119,13 @@
mWindow.setDefaultIcon(mActivityInfo.getIconResource());
mWindow.setDefaultLogo(mActivityInfo.getLogoResource());
}
-
+
/**
* Set the activity content from a layout resource. The resource will be
* inflated, adding all top-level views to the activity.
*
* @param layoutResID Resource ID to be inflated.
- *
+ *
* @see #setContentView(android.view.View)
* @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)
*/
@@ -2140,7 +2143,7 @@
* your own layout parameters, invoke
* {@link #setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}
* instead.
- *
+ *
* @param view The desired content to display.
*
* @see #setContentView(int)
@@ -2155,7 +2158,7 @@
* Set the activity content to an explicit view. This view is placed
* directly into the activity's view hierarchy. It can itself be a complex
* view hierarchy.
- *
+ *
* @param view The desired content to display.
* @param params Layout parameters for the view.
*
@@ -2170,7 +2173,7 @@
/**
* Add an additional content view to the activity. Added after any existing
* ones in the activity -- existing views are NOT removed.
- *
+ *
* @param view The desired content to display.
* @param params Layout parameters for the view.
*/
@@ -2235,23 +2238,23 @@
/**
* Use with {@link #setDefaultKeyMode} to turn off default handling of
* keys.
- *
+ *
* @see #setDefaultKeyMode
*/
static public final int DEFAULT_KEYS_DISABLE = 0;
/**
* Use with {@link #setDefaultKeyMode} to launch the dialer during default
* key handling.
- *
+ *
* @see #setDefaultKeyMode
*/
static public final int DEFAULT_KEYS_DIALER = 1;
/**
* Use with {@link #setDefaultKeyMode} to execute a menu shortcut in
* default key handling.
- *
+ *
* <p>That is, the user does not need to hold down the menu key to execute menu shortcuts.
- *
+ *
* @see #setDefaultKeyMode
*/
static public final int DEFAULT_KEYS_SHORTCUT = 2;
@@ -2259,9 +2262,9 @@
* Use with {@link #setDefaultKeyMode} to specify that unhandled keystrokes
* will start an application-defined search. (If the application or activity does not
* actually define a search, the the keys will be ignored.)
- *
+ *
* <p>See {@link android.app.SearchManager android.app.SearchManager} for more details.
- *
+ *
* @see #setDefaultKeyMode
*/
static public final int DEFAULT_KEYS_SEARCH_LOCAL = 3;
@@ -2270,9 +2273,9 @@
* Use with {@link #setDefaultKeyMode} to specify that unhandled keystrokes
* will start a global search (typically web search, but some platforms may define alternate
* methods for global search)
- *
+ *
* <p>See {@link android.app.SearchManager android.app.SearchManager} for more details.
- *
+ *
* @see #setDefaultKeyMode
*/
static public final int DEFAULT_KEYS_SEARCH_GLOBAL = 4;
@@ -2284,16 +2287,16 @@
* floor. Other modes allow you to launch the dialer
* ({@link #DEFAULT_KEYS_DIALER}), execute a shortcut in your options
* menu without requiring the menu key be held down
- * ({@link #DEFAULT_KEYS_SHORTCUT}), or launch a search ({@link #DEFAULT_KEYS_SEARCH_LOCAL}
+ * ({@link #DEFAULT_KEYS_SHORTCUT}), or launch a search ({@link #DEFAULT_KEYS_SEARCH_LOCAL}
* and {@link #DEFAULT_KEYS_SEARCH_GLOBAL}).
- *
+ *
* <p>Note that the mode selected here does not impact the default
* handling of system keys, such as the "back" and "menu" keys, and your
* activity and its views always get a first chance to receive and handle
* all application keys.
- *
+ *
* @param mode The desired default key mode constant.
- *
+ *
* @see #DEFAULT_KEYS_DISABLE
* @see #DEFAULT_KEYS_DIALER
* @see #DEFAULT_KEYS_SHORTCUT
@@ -2303,7 +2306,7 @@
*/
public final void setDefaultKeyMode(@DefaultKeyMode int mode) {
mDefaultKeyMode = mode;
-
+
// Some modes use a SpannableStringBuilder to track & dispatch input events
// This list must remain in sync with the switch in onKeyDown()
switch (mode) {
@@ -2324,10 +2327,10 @@
/**
* Called when a key was pressed down and not handled by any of the views
- * inside of the activity. So, for example, key presses while the cursor
+ * inside of the activity. So, for example, key presses while the cursor
* is inside a TextView will not trigger the event (unless it is a navigation
* to another object) because TextView handles its own key presses.
- *
+ *
* <p>If the focused view didn't want this event, this method is called.
*
* <p>The default implementation takes care of {@link KeyEvent#KEYCODE_BACK}
@@ -2338,12 +2341,12 @@
* will be performed; for earlier applications, it will perform the
* action immediately in on-down, as those versions of the platform
* behaved.
- *
+ *
* <p>Other additional default key handling may be performed
* if configured with {@link #setDefaultKeyMode}.
- *
+ *
* @return Return <code>true</code> to prevent this event from being propagated
- * further, or <code>false</code> to indicate that you have not handled
+ * further, or <code>false</code> to indicate that you have not handled
* this event and it should continue to be propagated.
* @see #onKeyUp
* @see android.view.KeyEvent
@@ -2358,11 +2361,11 @@
}
return true;
}
-
+
if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {
return false;
} else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {
- if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,
+ if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL,
keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {
return true;
}
@@ -2382,12 +2385,12 @@
final String str = mDefaultKeySsb.toString();
clearSpannable = true;
-
+
switch (mDefaultKeyMode) {
case DEFAULT_KEYS_DIALER:
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + str));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
+ startActivity(intent);
break;
case DEFAULT_KEYS_SEARCH_LOCAL:
startSearch(str, false, null, false);
@@ -2418,16 +2421,16 @@
/**
* Called when a key was released and not handled by any of the views
- * inside of the activity. So, for example, key presses while the cursor
+ * inside of the activity. So, for example, key presses while the cursor
* is inside a TextView will not trigger the event (unless it is a navigation
* to another object) because TextView handles its own key presses.
- *
+ *
* <p>The default implementation handles KEYCODE_BACK to stop the activity
* and go back.
- *
+ *
* @return Return <code>true</code> to prevent this event from being propagated
- * further, or <code>false</code> to indicate that you have not handled
- * this event and it should continue to be propagated.
+ * further, or <code>false</code> to indicate that you have not handled
+ * this event and it should continue to be propagated.
* @see #onKeyDown
* @see KeyEvent
*/
@@ -2451,7 +2454,7 @@
public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
return false;
}
-
+
/**
* Called when the activity has detected the user's press of the back
* key. The default implementation simply finishes the current activity,
@@ -2485,9 +2488,9 @@
* Called when a touch screen event was not handled by any of the views
* under it. This is most useful to process touch events that happen
* outside of your window bounds, where there is no view to receive it.
- *
+ *
* @param event The touch screen event being processed.
- *
+ *
* @return Return true if you have consumed the event, false if you haven't.
* The default implementation always returns false.
*/
@@ -2496,10 +2499,10 @@
finish();
return true;
}
-
+
return false;
}
-
+
/**
* Called when the trackball was moved and not handled by any of the
* views inside of the activity. So, for example, if the trackball moves
@@ -2508,9 +2511,9 @@
* here happens <em>before</em> trackball movements are converted to
* DPAD key events, which then get sent back to the view hierarchy, and
* will be processed at the point for things like focus navigation.
- *
+ *
* @param event The trackball event being processed.
- *
+ *
* @return Return true if you have consumed the event, false if you haven't.
* The default implementation always returns false.
*/
@@ -2554,21 +2557,21 @@
* This callback and {@link #onUserLeaveHint} are intended to help
* activities manage status bar notifications intelligently; specifically,
* for helping activities determine the proper time to cancel a notfication.
- *
+ *
* <p>All calls to your activity's {@link #onUserLeaveHint} callback will
* be accompanied by calls to {@link #onUserInteraction}. This
* ensures that your activity will be told of relevant user activity such
* as pulling down the notification pane and touching an item there.
- *
+ *
* <p>Note that this callback will be invoked for the touch down action
* that begins a touch gesture, but may not be invoked for the touch-moved
* and touch-up actions that follow.
- *
+ *
* @see #onUserLeaveHint()
*/
public void onUserInteraction() {
}
-
+
public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
// Update window manager if: we have a view, that view is
// attached to its parent (which will be a RootView), and
@@ -2589,14 +2592,14 @@
* focus. This is the best indicator of whether this activity is visible
* to the user. The default implementation clears the key tracking
* state, so should always be called.
- *
+ *
* <p>Note that this provides information about global focus state, which
* is managed independently of activity lifecycles. As such, while focus
* changes will generally have some relation to lifecycle changes (an
* activity that is stopped will not generally get window focus), you
* should not rely on any particular order between the callbacks here and
* those in the other lifecycle methods such as {@link #onResume}.
- *
+ *
* <p>As a general rule, however, a resumed activity will have window
* focus... unless it has displayed other dialogs or popups that take
* input focus, in which case the activity itself will not have focus
@@ -2606,14 +2609,14 @@
* pausing the foreground activity.
*
* @param hasFocus Whether the window of this activity has focus.
- *
+ *
* @see #hasWindowFocus()
* @see #onResume
* @see View#onWindowFocusChanged(boolean)
*/
public void onWindowFocusChanged(boolean hasFocus) {
}
-
+
/**
* Called when the main window associated with the activity has been
* attached to the window manager.
@@ -2623,7 +2626,7 @@
*/
public void onAttachedToWindow() {
}
-
+
/**
* Called when the main window associated with the activity has been
* detached from the window manager.
@@ -2633,13 +2636,13 @@
*/
public void onDetachedFromWindow() {
}
-
+
/**
* Returns true if this activity's <em>main</em> window currently has window focus.
* Note that this is not the same as the view itself having focus.
- *
+ *
* @return True if this activity's main window currently has window focus.
- *
+ *
* @see #onWindowAttributesChanged(android.view.WindowManager.LayoutParams)
*/
public boolean hasWindowFocus() {
@@ -2661,14 +2664,14 @@
public void onWindowDismissed() {
finish();
}
-
+
/**
- * Called to process key events. You can override this to intercept all
- * key events before they are dispatched to the window. Be sure to call
+ * Called to process key events. You can override this to intercept all
+ * key events before they are dispatched to the window. Be sure to call
* this implementation for key events that should be handled normally.
- *
+ *
* @param event The key event.
- *
+ *
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchKeyEvent(KeyEvent event) {
@@ -2713,9 +2716,9 @@
* intercept all touch screen events before they are dispatched to the
* window. Be sure to call this implementation for touch screen events
* that should be handled normally.
- *
+ *
* @param ev The touch screen event.
- *
+ *
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
@@ -2727,15 +2730,15 @@
}
return onTouchEvent(ev);
}
-
+
/**
* Called to process trackball events. You can override this to
* intercept all trackball events before they are dispatched to the
* window. Be sure to call this implementation for trackball events
* that should be handled normally.
- *
+ *
* @param ev The trackball event.
- *
+ *
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTrackballEvent(MotionEvent ev) {
@@ -2830,7 +2833,7 @@
/**
* {@inheritDoc}
- *
+ *
* @return The default implementation returns true.
*/
public boolean onMenuOpened(int featureId, Menu menu) {
@@ -2880,7 +2883,7 @@
}
}
return false;
-
+
case Window.FEATURE_CONTEXT_MENU:
if(titleCondensed != null) {
EventLog.writeEvent(50000, 1, titleCondensed.toString());
@@ -2894,7 +2897,7 @@
return false;
}
}
-
+
/**
* Default implementation of
* {@link android.view.Window.Callback#onPanelClosed(int, Menu)} for
@@ -2910,7 +2913,7 @@
mFragments.dispatchOptionsMenuClosed(menu);
onOptionsMenuClosed(menu);
break;
-
+
case Window.FEATURE_CONTEXT_MENU:
onContextMenuClosed(menu);
break;
@@ -2932,32 +2935,32 @@
mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
}
}
-
+
/**
* Initialize the contents of the Activity's standard options menu. You
* should place your menu items in to <var>menu</var>.
- *
+ *
* <p>This is only called once, the first time the options menu is
* displayed. To update the menu every time it is displayed, see
* {@link #onPrepareOptionsMenu}.
- *
+ *
* <p>The default implementation populates the menu with standard system
- * menu items. These are placed in the {@link Menu#CATEGORY_SYSTEM} group so that
- * they will be correctly ordered with application-defined menu items.
- * Deriving classes should always call through to the base implementation.
- *
+ * menu items. These are placed in the {@link Menu#CATEGORY_SYSTEM} group so that
+ * they will be correctly ordered with application-defined menu items.
+ * Deriving classes should always call through to the base implementation.
+ *
* <p>You can safely hold on to <var>menu</var> (and any items created
* from it), making modifications to it as desired, until the next
* time onCreateOptionsMenu() is called.
- *
+ *
* <p>When you add items to the menu, you can implement the Activity's
* {@link #onOptionsItemSelected} method to handle them there.
- *
+ *
* @param menu The options menu in which you place your items.
- *
+ *
* @return You must return true for the menu to be displayed;
* if you return false it will not be shown.
- *
+ *
* @see #onPrepareOptionsMenu
* @see #onOptionsItemSelected
*/
@@ -2973,17 +2976,17 @@
* called right before the menu is shown, every time it is shown. You can
* use this method to efficiently enable/disable items or otherwise
* dynamically modify the contents.
- *
+ *
* <p>The default implementation updates the system menu items based on the
* activity's state. Deriving classes should always call through to the
* base class implementation.
- *
+ *
* @param menu The options menu as last shown or first initialized by
* onCreateOptionsMenu().
- *
+ *
* @return You must return true for the menu to be displayed;
* if you return false it will not be shown.
- *
+ *
* @see #onCreateOptionsMenu
*/
public boolean onPrepareOptionsMenu(Menu menu) {
@@ -3000,15 +3003,15 @@
* its Handler as appropriate). You can use this method for any items
* for which you would like to do processing without those other
* facilities.
- *
+ *
* <p>Derived classes should call through to the base class for it to
* perform the default menu handling.</p>
- *
+ *
* @param item The menu item that was selected.
- *
+ *
* @return boolean Return false to allow normal menu processing to
* proceed, true to consume it here.
- *
+ *
* @see #onCreateOptionsMenu
*/
public boolean onOptionsItemSelected(MenuItem item) {
@@ -3125,7 +3128,7 @@
/**
* This hook is called whenever the options menu is being closed (either by the user canceling
* the menu with the back/menu button, or when an item is selected).
- *
+ *
* @param menu The options menu as last shown or first initialized by
* onCreateOptionsMenu().
*/
@@ -3134,7 +3137,7 @@
mParent.onOptionsMenuClosed(menu);
}
}
-
+
/**
* Programmatically opens the options menu. If the options menu is already
* open, this method does nothing.
@@ -3144,7 +3147,7 @@
mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
}
}
-
+
/**
* Progammatically closes the options menu. If the options menu is already
* closed, this method does nothing.
@@ -3175,43 +3178,43 @@
* {@link OnCreateContextMenuListener} on the view to this activity, so
* {@link #onCreateContextMenu(ContextMenu, View, ContextMenuInfo)} will be
* called when it is time to show the context menu.
- *
+ *
* @see #unregisterForContextMenu(View)
* @param view The view that should show a context menu.
*/
public void registerForContextMenu(View view) {
view.setOnCreateContextMenuListener(this);
}
-
+
/**
* Prevents a context menu to be shown for the given view. This method will remove the
* {@link OnCreateContextMenuListener} on the view.
- *
+ *
* @see #registerForContextMenu(View)
* @param view The view that should stop showing a context menu.
*/
public void unregisterForContextMenu(View view) {
view.setOnCreateContextMenuListener(null);
}
-
+
/**
* Programmatically opens the context menu for a particular {@code view}.
* The {@code view} should have been added via
* {@link #registerForContextMenu(View)}.
- *
+ *
* @param view The view to show the context menu for.
*/
public void openContextMenu(View view) {
view.showContextMenu();
}
-
+
/**
* Programmatically closes the most recently opened context menu, if showing.
*/
public void closeContextMenu() {
mWindow.closePanel(Window.FEATURE_CONTEXT_MENU);
}
-
+
/**
* This hook is called whenever an item in a context menu is selected. The
* default implementation simply returns false to have the normal processing
@@ -3224,7 +3227,7 @@
* <p>
* Derived classes should call through to the base class for it to perform
* the default menu handling.
- *
+ *
* @param item The context menu item that was selected.
* @return boolean Return false to allow normal context menu processing to
* proceed, true to consume it here.
@@ -3240,7 +3243,7 @@
* This hook is called whenever the context menu is being closed (either by
* the user canceling the menu with the back/menu button, or when an item is
* selected).
- *
+ *
* @param menu The context menu that is being closed.
*/
public void onContextMenuClosed(Menu menu) {
@@ -3309,14 +3312,14 @@
* Provides an opportunity to prepare a managed dialog before it is being
* shown. The default implementation calls through to
* {@link #onPrepareDialog(int, Dialog)} for compatibility.
- *
+ *
* <p>
* Override this if you need to update a managed dialog based on the state
* of the application each time it is shown. For example, a time picker
* dialog might want to be updated with the current time. You should call
* through to the superclass's implementation. The default implementation
* will set this Activity as the owner activity on the Dialog.
- *
+ *
* @param id The id of the managed dialog.
* @param dialog The dialog.
* @param args The dialog arguments provided to {@link #showDialog(int, Bundle)}.
@@ -3367,7 +3370,7 @@
* If you need to rebuild the dialog, call {@link #removeDialog(int)} first.
* @return Returns true if the Dialog was created; false is returned if
* it is not created because {@link #onCreateDialog(int, Bundle)} returns false.
- *
+ *
* @see Dialog
* @see #onCreateDialog(int, Bundle)
* @see #onPrepareDialog(int, Dialog, Bundle)
@@ -3393,7 +3396,7 @@
}
mManagedDialogs.put(id, md);
}
-
+
md.mArgs = args;
onPrepareDialog(id, md.mDialog, args);
md.mDialog.show();
@@ -3422,7 +3425,7 @@
if (mManagedDialogs == null) {
throw missingDialog(id);
}
-
+
final ManagedDialog md = mManagedDialogs.get(id);
if (md == null) {
throw missingDialog(id);
@@ -3449,7 +3452,7 @@
* <p>As of {@link android.os.Build.VERSION_CODES#GINGERBREAD}, this function
* will not throw an exception if you try to remove an ID that does not
* currently have an associated dialog.</p>
- *
+ *
* @param id The id of the managed dialog.
*
* @see #onCreateDialog(int, Bundle)
@@ -3474,37 +3477,37 @@
/**
* This hook is called when the user signals the desire to start a search.
- *
+ *
* <p>You can use this function as a simple way to launch the search UI, in response to a
- * menu item, search button, or other widgets within your activity. Unless overidden,
+ * menu item, search button, or other widgets within your activity. Unless overidden,
* calling this function is the same as calling
* {@link #startSearch startSearch(null, false, null, false)}, which launches
* search for the current activity as specified in its manifest, see {@link SearchManager}.
- *
+ *
* <p>You can override this function to force global search, e.g. in response to a dedicated
* search key, or to block search entirely (by simply returning false).
- *
+ *
* @return Returns {@code true} if search launched, and {@code false} if activity blocks it.
* The default implementation always returns {@code true}.
- *
+ *
* @see android.app.SearchManager
*/
public boolean onSearchRequested() {
- startSearch(null, false, null, false);
+ startSearch(null, false, null, false);
return true;
}
-
+
/**
* This hook is called to launch the search UI.
- *
- * <p>It is typically called from onSearchRequested(), either directly from
- * Activity.onSearchRequested() or from an overridden version in any given
+ *
+ * <p>It is typically called from onSearchRequested(), either directly from
+ * Activity.onSearchRequested() or from an overridden version in any given
* Activity. If your goal is simply to activate search, it is preferred to call
* onSearchRequested(), which may have been overridden elsewhere in your Activity. If your goal
* is to inject specific data such as context data, it is preferred to <i>override</i>
* onSearchRequested(), so that any callers to it will benefit from the override.
- *
- * @param initialQuery Any non-null non-empty string will be inserted as
+ *
+ * @param initialQuery Any non-null non-empty string will be inserted as
* pre-entered text in the search query box.
* @param selectInitialQuery If true, the initial query will be preselected, which means that
* any further typing will replace it. This is useful for cases where an entire pre-formed
@@ -3512,15 +3515,15 @@
* inserted query. This is useful when the inserted query is text that the user entered,
* and the user would expect to be able to keep typing. <i>This parameter is only meaningful
* if initialQuery is a non-empty string.</i>
- * @param appSearchData An application can insert application-specific
- * context here, in order to improve quality or specificity of its own
+ * @param appSearchData An application can insert application-specific
+ * context here, in order to improve quality or specificity of its own
* searches. This data will be returned with SEARCH intent(s). Null if
* no extra data is required.
* @param globalSearch If false, this will only launch the search that has been specifically
- * defined by the application (which is usually defined as a local search). If no default
+ * defined by the application (which is usually defined as a local search). If no default
* search is defined in the current application or activity, global search will be launched.
* If true, this will always launch a platform-global (e.g. web-based) search instead.
- *
+ *
* @see android.app.SearchManager
* @see #onSearchRequested
*/
@@ -3528,7 +3531,7 @@
@Nullable Bundle appSearchData, boolean globalSearch) {
ensureSearchManager();
mSearchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(),
- appSearchData, globalSearch);
+ appSearchData, globalSearch);
}
/**
@@ -3550,7 +3553,7 @@
* Request that key events come to this activity. Use this if your
* activity has no views with focus, but the activity still wants
* a chance to process key events.
- *
+ *
* @see android.view.Window#takeKeyEvents
*/
public void takeKeyEvents(boolean get) {
@@ -3560,12 +3563,12 @@
/**
* Enable extended window features. This is a convenience for calling
* {@link android.view.Window#requestFeature getWindow().requestFeature()}.
- *
+ *
* @param featureId The desired feature as defined in
* {@link android.view.Window}.
* @return Returns true if the requested feature is supported and now
* enabled.
- *
+ *
* @see android.view.Window#requestFeature
*/
public final boolean requestWindowFeature(int featureId) {
@@ -3677,7 +3680,7 @@
* Launch an activity for which you would like a result when it finished.
* When this activity exits, your
* onActivityResult() method will be called with the given requestCode.
- * Using a negative requestCode is the same as calling
+ * Using a negative requestCode is the same as calling
* {@link #startActivity} (the activity is not launched as a sub-activity).
*
* <p>Note that this method should only be used with Intent protocols
@@ -3687,7 +3690,7 @@
* are launching uses the singleTask launch mode, it will not run in your
* task and thus you will immediately receive a cancel result.
*
- * <p>As a special case, if you call startActivityForResult() with a requestCode
+ * <p>As a special case, if you call startActivityForResult() with a requestCode
* >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your
* activity, then your window will not be displayed until a result is
* returned back from the started activity. This is to avoid visible
@@ -3751,6 +3754,48 @@
/**
* @hide Implement to provide correct calling token.
*/
+ public void startActivityForResultAsUser(Intent intent, int requestCode, UserHandle user) {
+ startActivityForResultAsUser(intent, requestCode, null, user);
+ }
+
+ /**
+ * @hide Implement to provide correct calling token.
+ */
+ public void startActivityForResultAsUser(Intent intent, int requestCode,
+ @Nullable Bundle options, UserHandle user) {
+ if (options != null) {
+ mActivityTransitionState.startExitOutTransition(this, options);
+ }
+ if (mParent != null) {
+ throw new RuntimeException("Can't be called from a child");
+ }
+ Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
+ this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode,
+ options, user);
+ if (ar != null) {
+ mMainThread.sendActivityResult(
+ mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData());
+ }
+ if (requestCode >= 0) {
+ // If this start is requesting a result, we can avoid making
+ // the activity visible until the result is received. Setting
+ // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
+ // activity hidden during this time, to avoid flickering.
+ // This can only be done when a result is requested because
+ // that guarantees we will get information back when the
+ // activity is finished, no matter what happens to it.
+ mStartedActivity = true;
+ }
+
+ final View decor = mWindow != null ? mWindow.peekDecorView() : null;
+ if (decor != null) {
+ decor.cancelPendingInputEvents();
+ }
+ }
+
+ /**
+ * @hide Implement to provide correct calling token.
+ */
public void startActivityAsUser(Intent intent, UserHandle user) {
startActivityAsUser(intent, null, user);
}
@@ -3760,7 +3805,7 @@
*/
public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
if (mParent != null) {
- throw new RuntimeException("Called be called from a child");
+ throw new RuntimeException("Can't be called from a child");
}
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
@@ -3803,7 +3848,7 @@
* here; otherwise, its associated action will be executed (such as
* sending a broadcast) as if you had called
* {@link IntentSender#sendIntent IntentSender.sendIntent} on it.
- *
+ *
* @param intent The IntentSender to launch.
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits.
@@ -3894,19 +3939,19 @@
* information, the {@link Intent#FLAG_ACTIVITY_NEW_TASK} launch flag is not
* required; if not specified, the new activity will be added to the
* task of the caller.
- *
+ *
* <p>This method throws {@link android.content.ActivityNotFoundException}
* if there was no Activity found to run the given Intent.
- *
- * @param intent The intent to start.
+ *
+ * @param intent The intent to start.
* @param options Additional options for how the Activity should be started.
* See {@link android.content.Context#startActivity(Intent, Bundle)
* Context.startActivity(Intent, Bundle)} for more details.
- *
+ *
* @throws android.content.ActivityNotFoundException
*
* @see {@link #startActivity(Intent)}
- * @see #startActivityForResult
+ * @see #startActivityForResult
*/
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
@@ -3966,7 +4011,7 @@
/**
* Same as calling {@link #startIntentSender(IntentSender, Intent, int, int, int, Bundle)}
* with no options.
- *
+ *
* @param intent The IntentSender to launch.
* @param fillInIntent If non-null, this will be provided as the
* intent parameter to {@link IntentSender#sendIntent}.
@@ -4039,19 +4084,19 @@
/**
* A special variation to launch an activity only if a new activity
* instance is needed to handle the given Intent. In other words, this is
- * just like {@link #startActivityForResult(Intent, int)} except: if you are
+ * just like {@link #startActivityForResult(Intent, int)} except: if you are
* using the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP} flag, or
- * singleTask or singleTop
+ * singleTask or singleTop
* {@link android.R.styleable#AndroidManifestActivity_launchMode launchMode},
- * and the activity
- * that handles <var>intent</var> is the same as your currently running
- * activity, then a new instance is not needed. In this case, instead of
- * the normal behavior of calling {@link #onNewIntent} this function will
- * return and you can handle the Intent yourself.
- *
+ * and the activity
+ * that handles <var>intent</var> is the same as your currently running
+ * activity, then a new instance is not needed. In this case, instead of
+ * the normal behavior of calling {@link #onNewIntent} this function will
+ * return and you can handle the Intent yourself.
+ *
* <p>This function can only be called from a top-level activity; if it is
* called from a child activity, a runtime exception will be thrown.
- *
+ *
* @param intent The intent to start.
* @param requestCode If >= 0, this code will be returned in
* onActivityResult() when the activity exits, as described in
@@ -4059,10 +4104,10 @@
* @param options Additional options for how the Activity should be started.
* See {@link android.content.Context#startActivity(Intent, Bundle)
* Context.startActivity(Intent, Bundle)} for more details.
- *
+ *
* @return If a new activity was launched then true is returned; otherwise
* false is returned and you must handle the Intent yourself.
- *
+ *
* @see #startActivity
* @see #startActivityForResult
*/
@@ -4125,7 +4170,7 @@
* other activity components. You can use this to hand the Intent off
* to the next Activity that can handle it. You typically call this in
* {@link #onCreate} with the Intent returned by {@link #getIntent}.
- *
+ *
* @param intent The intent to dispatch to the next activity. For
* correct behavior, this must be the same as the Intent that started
* your own activity; the only changes you can make are to the extras
@@ -4133,7 +4178,7 @@
* @param options Additional options for how the Activity should be started.
* See {@link android.content.Context#startActivity(Intent, Bundle)
* Context.startActivity(Intent, Bundle)} for more details.
- *
+ *
* @return Returns a boolean indicating whether there was another Activity
* to start: true if there was a next activity to start, false if there
* wasn't. In general, if true is returned you will then want to call
@@ -4175,23 +4220,23 @@
}
/**
- * This is called when a child activity of this one calls its
+ * This is called when a child activity of this one calls its
* {@link #startActivity} or {@link #startActivityForResult} method.
- *
+ *
* <p>This method throws {@link android.content.ActivityNotFoundException}
* if there was no Activity found to run the given Intent.
- *
+ *
* @param child The activity making the call.
* @param intent The intent to start.
* @param requestCode Reply request code. < 0 if reply is not requested.
* @param options Additional options for how the Activity should be started.
* See {@link android.content.Context#startActivity(Intent, Bundle)
* Context.startActivity(Intent, Bundle)} for more details.
- *
+ *
* @throws android.content.ActivityNotFoundException
- *
- * @see #startActivity
- * @see #startActivityForResult
+ *
+ * @see #startActivity
+ * @see #startActivityForResult
*/
public void startActivityFromChild(@NonNull Activity child, Intent intent,
int requestCode, @Nullable Bundle options) {
@@ -4225,24 +4270,24 @@
}
/**
- * This is called when a Fragment in this activity calls its
+ * This is called when a Fragment in this activity calls its
* {@link Fragment#startActivity} or {@link Fragment#startActivityForResult}
* method.
- *
+ *
* <p>This method throws {@link android.content.ActivityNotFoundException}
* if there was no Activity found to run the given Intent.
- *
+ *
* @param fragment The fragment making the call.
* @param intent The intent to start.
- * @param requestCode Reply request code. < 0 if reply is not requested.
+ * @param requestCode Reply request code. < 0 if reply is not requested.
* @param options Additional options for how the Activity should be started.
* See {@link android.content.Context#startActivity(Intent, Bundle)
* Context.startActivity(Intent, Bundle)} for more details.
- *
+ *
* @throws android.content.ActivityNotFoundException
- *
- * @see Fragment#startActivity
- * @see Fragment#startActivityForResult
+ *
+ * @see Fragment#startActivity
+ * @see Fragment#startActivityForResult
*/
public void startActivityFromFragment(@NonNull Fragment fragment, Intent intent,
int requestCode, @Nullable Bundle options) {
@@ -4310,14 +4355,14 @@
} catch (RemoteException e) {
}
}
-
+
/**
* Call this to set the result that your activity will return to its
* caller.
- *
+ *
* @param resultCode The result code to propagate back to the originating
* activity, often RESULT_CANCELED or RESULT_OK
- *
+ *
* @see #RESULT_CANCELED
* @see #RESULT_OK
* @see #RESULT_FIRST_USER
@@ -4346,7 +4391,7 @@
* @param resultCode The result code to propagate back to the originating
* activity, often RESULT_CANCELED or RESULT_OK
* @param data The data to propagate back to the originating activity.
- *
+ *
* @see #RESULT_CANCELED
* @see #RESULT_OK
* @see #RESULT_FIRST_USER
@@ -4364,10 +4409,10 @@
* the data in {@link #setResult setResult()} will be sent to. You can
* use this information to validate that the recipient is allowed to
* receive the data.
- *
+ *
* <p class="note">Note: if the calling activity is not expecting a result (that is it
- * did not use the {@link #startActivityForResult}
- * form that includes a request code), then the calling package will be
+ * did not use the {@link #startActivityForResult}
+ * form that includes a request code), then the calling package will be
* null.</p>
*
* <p class="note">Note: prior to {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
@@ -4375,7 +4420,7 @@
* package was no longer running, it would return null instead of the proper package
* name. You can use {@link #getCallingActivity()} and retrieve the package name
* from that instead.</p>
- *
+ *
* @return The package of the activity that will receive your
* reply, or null if none.
*/
@@ -4393,12 +4438,12 @@
* who the data in {@link #setResult setResult()} will be sent to. You
* can use this information to validate that the recipient is allowed to
* receive the data.
- *
+ *
* <p class="note">Note: if the calling activity is not expecting a result (that is it
- * did not use the {@link #startActivityForResult}
- * form that includes a request code), then the calling package will be
- * null.
- *
+ * did not use the {@link #startActivityForResult}
+ * form that includes a request code), then the calling package will be
+ * null.
+ *
* @return The ComponentName of the activity that will receive your
* reply, or null if none.
*/
@@ -4417,7 +4462,7 @@
* UI itself, but can't just finish prior to onResume() because it needs
* to wait for a service binding or such. Setting this to false allows
* you to prevent your UI from being shown during that time.
- *
+ *
* <p>The default value for this is taken from the
* {@link android.R.attr#windowNoDisplay} attribute of the activity's theme.
*/
@@ -4430,7 +4475,7 @@
}
}
}
-
+
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
@@ -4439,16 +4484,16 @@
}
mDecor.setVisibility(View.VISIBLE);
}
-
+
/**
* Check to see whether this activity is in the process of finishing,
* either because you called {@link #finish} on it or someone else
* has requested that it finished. This is often used in
* {@link #onPause} to determine whether the activity is simply pausing or
* completely finishing.
- *
+ *
* @return If the activity is finishing, returns true; else returns false.
- *
+ *
* @see #finish
*/
public boolean isFinishing() {
@@ -4468,7 +4513,7 @@
* recreated with a new configuration. This is often used in
* {@link #onStop} to determine whether the state needs to be cleaned up or will be passed
* on to the next instance of the activity via {@link #onRetainNonConfigurationInstance()}.
- *
+ *
* @return If the activity is being torn down in order to be recreated with a new configuration,
* returns true; else returns false.
*/
@@ -4561,12 +4606,12 @@
}
/**
- * This is called when a child activity of this one calls its
+ * This is called when a child activity of this one calls its
* {@link #finish} method. The default implementation simply calls
* finish() on this activity (the parent), finishing the entire group.
- *
+ *
* @param child The activity making the call.
- *
+ *
* @see #finish
*/
public void finishFromChild(Activity child) {
@@ -4589,7 +4634,7 @@
/**
* Force finish another activity that you had previously started with
* {@link #startActivityForResult}.
- *
+ *
* @param requestCode The request code of the activity that you had
* given to startActivityForResult(). If there are multiple
* activities started with this request code, they
@@ -4611,7 +4656,7 @@
/**
* This is called when a child activity of this one calls its
* finishActivity().
- *
+ *
* @param child The activity making the call.
* @param requestCode Request code that had been used to start the
* activity.
@@ -4639,10 +4684,10 @@
* data from it. The <var>resultCode</var> will be
* {@link #RESULT_CANCELED} if the activity explicitly returned that,
* didn't return any result, or crashed during its operation.
- *
+ *
* <p>You will receive this call immediately before onResume() when your
* activity is re-starting.
- *
+ *
* @param requestCode The integer request code originally supplied to
* startActivityForResult(), allowing you to identify who this
* result came from.
@@ -4650,7 +4695,7 @@
* through its setResult().
* @param data An Intent, which can return result data to the caller
* (various data can be attached to Intent "extras").
- *
+ *
* @see #startActivityForResult
* @see #createPendingResult
* @see #setResult(int)
@@ -4680,12 +4725,12 @@
}
/**
- * Create a new PendingIntent object which you can hand to others
- * for them to use to send result data back to your
- * {@link #onActivityResult} callback. The created object will be either
- * one-shot (becoming invalid after a result is sent back) or multiple
- * (allowing any number of results to be sent through it).
- *
+ * Create a new PendingIntent object which you can hand to others
+ * for them to use to send result data back to your
+ * {@link #onActivityResult} callback. The created object will be either
+ * one-shot (becoming invalid after a result is sent back) or multiple
+ * (allowing any number of results to be sent through it).
+ *
* @param requestCode Private request code for the sender that will be
* associated with the result data when it is returned. The sender can not
* modify this value, allowing you to identify incoming results.
@@ -4698,12 +4743,12 @@
* or any of the flags as supported by
* {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts
* of the intent that can be supplied when the actual send happens.
- *
+ *
* @return Returns an existing or new PendingIntent matching the given
* parameters. May return null only if
* {@link PendingIntent#FLAG_NO_CREATE PendingIntent.FLAG_NO_CREATE} has been
* supplied.
- *
+ *
* @see PendingIntent
*/
public PendingIntent createPendingResult(int requestCode, @NonNull Intent data,
@@ -4730,7 +4775,7 @@
* orientation, the screen will immediately be changed (possibly causing
* the activity to be restarted). Otherwise, this will be used the next
* time the activity is visible.
- *
+ *
* @param requestedOrientation An orientation constant as used in
* {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}.
*/
@@ -4746,13 +4791,13 @@
mParent.setRequestedOrientation(requestedOrientation);
}
}
-
+
/**
* Return the current requested orientation of the activity. This will
* either be the orientation requested in its component's manifest, or
* the last requested orientation given to
* {@link #setRequestedOrientation(int)}.
- *
+ *
* @return Returns an orientation constant as used in
* {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}.
*/
@@ -4770,11 +4815,11 @@
}
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
-
+
/**
* Return the identifier of the task this activity is in. This identifier
* will remain the same for the lifetime of the activity.
- *
+ *
* @return Task identifier, an opaque integer.
*/
public int getTaskId() {
@@ -4789,7 +4834,7 @@
/**
* Return whether this activity is the root of a task. The root is the
* first activity in a task.
- *
+ *
* @return True if this is the root activity, else false.
*/
public boolean isTaskRoot() {
@@ -4804,11 +4849,11 @@
/**
* Move the task containing this activity to the back of the activity
* stack. The activity's order within the task is unchanged.
- *
+ *
* @param nonRoot If false then this only works if the activity is the root
* of a task; if true it will work for any activity in
* a task.
- *
+ *
* @return If the task was moved (or it was already at the
* back) true is returned, else false.
*/
@@ -4825,7 +4870,7 @@
/**
* Returns class name for this activity with the package prefix removed.
* This is the default name used to read and write settings.
- *
+ *
* @return The local class name.
*/
@NonNull
@@ -4839,10 +4884,10 @@
}
return cls.substring(packageLen+1);
}
-
+
/**
* Returns complete component name of this activity.
- *
+ *
* @return Returns the complete component name for this activity
*/
public ComponentName getComponentName()
@@ -4855,9 +4900,9 @@
* that are private to this activity. This simply calls the underlying
* {@link #getSharedPreferences(String, int)} method by passing in this activity's
* class name as the preferences name.
- *
- * @param mode Operating mode. Use {@link #MODE_PRIVATE} for the default
- * operation, {@link #MODE_WORLD_READABLE} and
+ *
+ * @param mode Operating mode. Use {@link #MODE_PRIVATE} for the default
+ * operation, {@link #MODE_WORLD_READABLE} and
* {@link #MODE_WORLD_WRITEABLE} to control permissions.
*
* @return Returns the single SharedPreferences instance that can be used
@@ -4866,12 +4911,12 @@
public SharedPreferences getPreferences(int mode) {
return getSharedPreferences(getLocalClassName(), mode);
}
-
+
private void ensureSearchManager() {
if (mSearchManager != null) {
return;
}
-
+
mSearchManager = new SearchManager(this, null);
}
@@ -4989,7 +5034,7 @@
* <p>
* In order for the progress bar to be shown, the feature must be requested
* via {@link #requestWindowFeature(int)}.
- *
+ *
* @param visible Whether to show the progress bars in the title.
*/
public final void setProgressBarVisibility(boolean visible) {
@@ -5009,14 +5054,14 @@
getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
visible ? Window.PROGRESS_VISIBILITY_ON : Window.PROGRESS_VISIBILITY_OFF);
}
-
+
/**
* Sets whether the horizontal progress bar in the title should be indeterminate (the circular
* is always indeterminate).
* <p>
* In order for the progress bar to be shown, the feature must be requested
* via {@link #requestWindowFeature(int)}.
- *
+ *
* @param indeterminate Whether the horizontal progress bar should be indeterminate.
*/
public final void setProgressBarIndeterminate(boolean indeterminate) {
@@ -5024,13 +5069,13 @@
indeterminate ? Window.PROGRESS_INDETERMINATE_ON
: Window.PROGRESS_INDETERMINATE_OFF);
}
-
+
/**
* Sets the progress for the progress bars in the title.
* <p>
* In order for the progress bar to be shown, the feature must be requested
* via {@link #requestWindowFeature(int)}.
- *
+ *
* @param progress The progress for the progress bar. Valid ranges are from
* 0 to 10000 (both inclusive). If 10000 is given, the progress
* bar will be completely filled and will fade out.
@@ -5038,7 +5083,7 @@
public final void setProgress(int progress) {
getWindow().setFeatureInt(Window.FEATURE_PROGRESS, progress + Window.PROGRESS_START);
}
-
+
/**
* Sets the secondary progress for the progress bar in the title. This
* progress is drawn between the primary progress (set via
@@ -5048,7 +5093,7 @@
* <p>
* In order for the progress bar to be shown, the feature must be requested
* via {@link #requestWindowFeature(int)}.
- *
+ *
* @param secondaryProgress The secondary progress for the progress bar. Valid ranges are from
* 0 to 10000 (both inclusive).
*/
@@ -5062,16 +5107,16 @@
* volume controls.
* <p>
* The suggested audio stream will be tied to the window of this Activity.
- * If the Activity is switched, the stream set here is no longer the
- * suggested stream. The client does not need to save and restore the old
- * suggested stream value in onPause and onResume.
- *
+ * Volume requests which are received while the Activity is in the
+ * foreground will affect this stream.
+ * <p>
+ * It is not guaranteed that the hardware volume controls will always change
+ * this stream's volume (for example, if a call is in progress, its stream's
+ * volume may be changed instead). To reset back to the default, use
+ * {@link AudioManager#USE_DEFAULT_STREAM_TYPE}.
+ *
* @param streamType The type of the audio stream whose volume should be
- * changed by the hardware volume controls. It is not guaranteed that
- * the hardware volume controls will always change this stream's
- * volume (for example, if a call is in progress, its stream's volume
- * may be changed instead). To reset back to the default, use
- * {@link AudioManager#USE_DEFAULT_STREAM_TYPE}.
+ * changed by the hardware volume controls.
*/
public final void setVolumeControlStream(int streamType) {
getWindow().setVolumeControlStream(streamType);
@@ -5080,7 +5125,7 @@
/**
* Gets the suggested audio stream whose volume should be changed by the
* hardware volume controls.
- *
+ *
* @return The suggested audio stream type whose volume should be changed by
* the hardware volume controls.
* @see #setVolumeControlStream(int)
@@ -5088,7 +5133,40 @@
public final int getVolumeControlStream() {
return getWindow().getVolumeControlStream();
}
-
+
+ /**
+ * Sets a {@link MediaController} to send media keys and volume changes to.
+ * <p>
+ * The controller will be tied to the window of this Activity. Media key and
+ * volume events which are received while the Activity is in the foreground
+ * will be forwarded to the controller and used to invoke transport controls
+ * or adjust the volume. This may be used instead of or in addition to
+ * {@link #setVolumeControlStream} to affect a specific session instead of a
+ * specific stream.
+ * <p>
+ * It is not guaranteed that the hardware volume controls will always change
+ * this session's volume (for example, if a call is in progress, its
+ * stream's volume may be changed instead). To reset back to the default use
+ * null as the controller.
+ *
+ * @param controller The controller for the session which should receive
+ * media keys and volume changes.
+ */
+ public final void setMediaController(MediaController controller) {
+ getWindow().setMediaController(controller);
+ }
+
+ /**
+ * Gets the controller which should be receiving media key and volume events
+ * while this activity is in the foreground.
+ *
+ * @return The controller which should receive events.
+ * @see #setMediaController(android.media.session.MediaController)
+ */
+ public final MediaController getMediaController() {
+ return getWindow().getMediaController();
+ }
+
/**
* Runs the specified action on the UI thread. If the current thread is the UI
* thread, then the action is executed immediately. If the current thread is
@@ -5134,7 +5212,7 @@
if (!"fragment".equals(name)) {
return onCreateView(name, context, attrs);
}
-
+
return mFragments.onCreateView(parent, name, context, attrs);
}
@@ -5695,7 +5773,7 @@
}
// ------------------ Internal API ------------------
-
+
final void setParent(Activity parent) {
mParent = parent;
}
@@ -5709,7 +5787,7 @@
attachBaseContext(context);
mFragments.attachActivity(this, mContainer, null);
-
+
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
@@ -5804,7 +5882,7 @@
}
mActivityTransitionState.enterReady(this);
}
-
+
final void performRestart() {
mFragments.noteStateNotSaved();
@@ -5843,14 +5921,14 @@
performStart();
}
}
-
+
final void performResume() {
performRestart();
-
+
mFragments.execPendingActions();
-
+
mLastNonConfigurationInstances = null;
-
+
mCalled = false;
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);
@@ -5862,10 +5940,10 @@
// Now really resume, and install the current status bar and menu.
mCalled = false;
-
+
mFragments.dispatchResume();
mFragments.execPendingActions();
-
+
onPostResume();
if (!mCalled) {
throw new SuperNotCalledException(
@@ -5888,12 +5966,12 @@
}
mResumed = false;
}
-
+
final void performUserLeaving() {
onUserInteraction();
onUserLeaveHint();
}
-
+
final void performStop() {
mDoReportFullyDrawn = false;
if (mLoadersStarted) {
@@ -5906,7 +5984,7 @@
}
}
}
-
+
if (!mStopped) {
if (mWindow != null) {
mWindow.closeAllPanels();
@@ -5915,9 +5993,9 @@
if (mToken != null && mParent == null) {
WindowManagerGlobal.getInstance().setStoppedState(mToken, true);
}
-
+
mFragments.dispatchStop();
-
+
mCalled = false;
mInstrumentation.callActivityOnStop(this);
if (!mCalled) {
@@ -5925,7 +6003,7 @@
"Activity " + mComponent.toShortString() +
" did not call through to super.onStop()");
}
-
+
synchronized (mManagedCursors) {
final int N = mManagedCursors.size();
for (int i=0; i<N; i++) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index e1d0b86..d2540f1 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1819,7 +1819,29 @@
* actively running code.
*/
public static final int IMPORTANCE_EMPTY = 500;
-
+
+ /**
+ * Constant for {@link #importance}: this process does not exist.
+ */
+ public static final int IMPORTANCE_GONE = 1000;
+
+ /** @hide */
+ public static int procStateToImportance(int procState) {
+ if (procState >= ActivityManager.PROCESS_STATE_HOME) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
+ } else if (procState >= ActivityManager.PROCESS_STATE_SERVICE) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
+ } else if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
+ } else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
+ } else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+ } else {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+ }
+ }
+
/**
* The relative importance level that the system places on this
* process. May be one of {@link #IMPORTANCE_FOREGROUND},
@@ -2456,7 +2478,10 @@
}
/**
- * @hide
+ * Return whether currently in lock task mode. When in this mode
+ * no new tasks can be created or switched to.
+ *
+ * @see Activity#startLockTask()
*/
public boolean isInLockTaskMode() {
try {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4a70e15..fb70098 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -30,7 +30,6 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
-import android.graphics.Bitmap;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -1466,7 +1465,15 @@
reply.writeNoException();
return true;
}
-
+
+ case ADD_PACKAGE_DEPENDENCY_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String packageName = data.readString();
+ addPackageDependency(packageName);
+ reply.writeNoException();
+ return true;
+ }
+
case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String pkg = data.readString();
@@ -1476,7 +1483,7 @@
reply.writeNoException();
return true;
}
-
+
case CLOSE_SYSTEM_DIALOGS_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String reason = data.readString();
@@ -2196,13 +2203,21 @@
return true;
}
- case MEDIA_RESOURCES_RELEASED: {
+ case MEDIA_RESOURCES_RELEASED_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
mediaResourcesReleased(token);
reply.writeNoException();
return true;
}
+
+ case NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ notifyLaunchTaskBehindComplete(token);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -4043,7 +4058,18 @@
reply.recycle();
data.recycle();
}
-
+
+ public void addPackageDependency(String packageName) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ mRemote.transact(ADD_PACKAGE_DEPENDENCY_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
public void killApplicationWithAppId(String pkg, int appid, String reason)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -5069,7 +5095,20 @@
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
- mRemote.transact(MEDIA_RESOURCES_RELEASED, data, reply, IBinder.FLAG_ONEWAY);
+ mRemote.transact(MEDIA_RESOURCES_RELEASED_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
+ public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ mRemote.transact(NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION, data, reply,
+ IBinder.FLAG_ONEWAY);
reply.readException();
data.recycle();
reply.recycle();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index fafa948..4c02314 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -126,6 +126,8 @@
public static final int ANIM_SCENE_TRANSITION = 5;
/** @hide */
public static final int ANIM_DEFAULT = 6;
+ /** @hide */
+ public static final int ANIM_LAUNCH_TASK_BEHIND = 7;
private String mPackageName;
private int mAnimationType = ANIM_NONE;
@@ -432,6 +434,27 @@
return opts;
}
+ /**
+ * If set along with Intent.FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
+ * presented to the user but will instead be only available through the recents task list.
+ * In addition, the new task wil be affiliated with the launching activity's task.
+ * Affiliated tasks are grouped together in the recents task list.
+ *
+ * <p>This behavior is not supported for activities with {@link
+ * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
+ * <code>singleInstance</code> or <code>singleTask</code>.
+ */
+ public static ActivityOptions makeLaunchTaskBehindAnimation() {
+ final ActivityOptions opts = new ActivityOptions();
+ opts.mAnimationType = ANIM_LAUNCH_TASK_BEHIND;
+ return opts;
+ }
+
+ /** @hide */
+ public boolean getLaunchTaskBehind() {
+ return mAnimationType == ANIM_LAUNCH_TASK_BEHIND;
+ }
+
private ActivityOptions() {
}
@@ -647,16 +670,15 @@
if (mPackageName != null) {
b.putString(KEY_PACKAGE_NAME, mPackageName);
}
+ b.putInt(KEY_ANIM_TYPE, mAnimationType);
switch (mAnimationType) {
case ANIM_CUSTOM:
- b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId);
b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId);
b.putBinder(KEY_ANIM_START_LISTENER, mAnimationStartedListener
!= null ? mAnimationStartedListener.asBinder() : null);
break;
case ANIM_SCALE_UP:
- b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
b.putInt(KEY_ANIM_START_WIDTH, mStartWidth);
@@ -664,7 +686,6 @@
break;
case ANIM_THUMBNAIL_SCALE_UP:
case ANIM_THUMBNAIL_SCALE_DOWN:
- b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
b.putInt(KEY_ANIM_START_X, mStartX);
b.putInt(KEY_ANIM_START_Y, mStartY);
@@ -672,7 +693,6 @@
!= null ? mAnimationStartedListener.asBinder() : null);
break;
case ANIM_SCENE_TRANSITION:
- b.putInt(KEY_ANIM_TYPE, mAnimationType);
if (mTransitionReceiver != null) {
b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionReceiver);
}
@@ -683,6 +703,7 @@
b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
break;
}
+
return b;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7c8c83a..15f3a75 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1684,6 +1684,7 @@
&& ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
: true);
+ boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0;
if ((flags&(Context.CONTEXT_INCLUDE_CODE
|Context.CONTEXT_IGNORE_SECURITY))
== Context.CONTEXT_INCLUDE_CODE) {
@@ -1698,12 +1699,13 @@
throw new SecurityException(msg);
}
}
- return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode);
+ return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,
+ registerPackage);
}
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
- return getPackageInfo(ai, compatInfo, null, false, true);
+ return getPackageInfo(ai, compatInfo, null, false, true, false);
}
public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
@@ -1719,7 +1721,8 @@
}
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
- ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
+ ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
+ boolean registerPackage) {
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (includeCode) {
@@ -1738,7 +1741,7 @@
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
- (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
+ (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (includeCode) {
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
@@ -4394,7 +4397,7 @@
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
- appContext.getClassLoader(), false, true);
+ appContext.getClassLoader(), false, true, false);
ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 15be9b1..e074219 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -403,20 +403,18 @@
view.layout(left, top, right, bottom);
}
- protected ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> setSharedElementState(
+ protected ArrayList<SharedElementOriginalState> setSharedElementState(
Bundle sharedElementState, final ArrayList<View> snapshots) {
- ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalImageState =
- new ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>>();
+ ArrayList<SharedElementOriginalState> originalImageState =
+ new ArrayList<SharedElementOriginalState>();
if (sharedElementState != null) {
int[] tempLoc = new int[2];
for (int i = 0; i < mSharedElementNames.size(); i++) {
View sharedElement = mSharedElements.get(i);
String name = mSharedElementNames.get(i);
- Pair<ImageView.ScaleType, Matrix> originalState = getOldImageState(sharedElement,
+ SharedElementOriginalState originalState = getOldSharedElementState(sharedElement,
name, sharedElementState);
- if (originalState != null) {
- originalImageState.put((ImageView) sharedElement, originalState);
- }
+ originalImageState.add(originalState);
View parent = (View) sharedElement.getParent();
parent.getLocationOnScreen(tempLoc);
setSharedElementState(sharedElement, name, sharedElementState, tempLoc);
@@ -438,29 +436,34 @@
return originalImageState;
}
- private static Pair<ImageView.ScaleType, Matrix> getOldImageState(View view, String name,
+ private static SharedElementOriginalState getOldSharedElementState(View view, String name,
Bundle transitionArgs) {
+
+ SharedElementOriginalState state = new SharedElementOriginalState();
+ state.mLeft = view.getLeft();
+ state.mTop = view.getTop();
+ state.mRight = view.getRight();
+ state.mBottom = view.getBottom();
+ state.mMeasuredWidth = view.getMeasuredWidth();
+ state.mMeasuredHeight = view.getMeasuredHeight();
if (!(view instanceof ImageView)) {
- return null;
+ return state;
}
Bundle bundle = transitionArgs.getBundle(name);
if (bundle == null) {
- return null;
+ return state;
}
int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1);
if (scaleTypeInt < 0) {
- return null;
+ return state;
}
ImageView imageView = (ImageView) view;
- ImageView.ScaleType originalScaleType = imageView.getScaleType();
-
- Matrix originalMatrix = null;
- if (originalScaleType == ImageView.ScaleType.MATRIX) {
- originalMatrix = new Matrix(imageView.getImageMatrix());
+ state.mScaleType = imageView.getScaleType();
+ if (state.mScaleType == ImageView.ScaleType.MATRIX) {
+ state.mMatrix = new Matrix(imageView.getImageMatrix());
}
-
- return Pair.create(originalScaleType, originalMatrix);
+ return state;
}
protected ArrayList<View> createSnapshots(Bundle state, Collection<String> names) {
@@ -489,13 +492,26 @@
return snapshots;
}
- protected static void setOriginalImageViewState(
- ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalState) {
+ protected static void setOriginalSharedElementState(ArrayList<View> sharedElements,
+ ArrayList<SharedElementOriginalState> originalState) {
for (int i = 0; i < originalState.size(); i++) {
- ImageView imageView = originalState.keyAt(i);
- Pair<ImageView.ScaleType, Matrix> state = originalState.valueAt(i);
- imageView.setScaleType(state.first);
- imageView.setImageMatrix(state.second);
+ View view = sharedElements.get(i);
+ SharedElementOriginalState state = originalState.get(i);
+ if (view instanceof ImageView && state.mScaleType != null) {
+ ImageView imageView = (ImageView) view;
+ imageView.setScaleType(state.mScaleType);
+ if (state.mScaleType == ImageView.ScaleType.MATRIX) {
+ imageView.setImageMatrix(state.mMatrix);
+ }
+ }
+ // origignal widthspec might be AT_MOST, but it should work for most
+ // cases.
+ int widthSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredWidth,
+ View.MeasureSpec.EXACTLY);
+ int heightSpec = View.MeasureSpec.makeMeasureSpec(state.mMeasuredHeight,
+ View.MeasureSpec.EXACTLY);
+ view.measure(widthSpec, heightSpec);
+ view.layout(state.mLeft, state.mTop, state.mRight, state.mBottom);
}
}
@@ -622,4 +638,15 @@
}
}
+ static class SharedElementOriginalState {
+ int mLeft;
+ int mTop;
+ int mRight;
+ int mBottom;
+ int mMeasuredWidth;
+ int mMeasuredHeight;
+ ImageView.ScaleType mScaleType;
+ Matrix mMatrix;
+ }
+
}
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 0d2af8c..4f556a8 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -95,6 +95,8 @@
*/
private int mExitTransitionCoordinatorsKey = 1;
+ private boolean mIsEnterTriggered;
+
public ActivityTransitionState() {
}
@@ -142,8 +144,10 @@
public void setEnterActivityOptions(Activity activity, ActivityOptions options) {
if (activity.getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)
&& options != null && mEnterActivityOptions == null
+ && mEnterTransitionCoordinator == null
&& options.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
mEnterActivityOptions = options;
+ mIsEnterTriggered = false;
if (mEnterActivityOptions.isReturning()) {
int result = mEnterActivityOptions.getResultCode();
if (result != 0) {
@@ -154,9 +158,10 @@
}
public void enterReady(Activity activity) {
- if (mEnterActivityOptions == null) {
+ if (mEnterActivityOptions == null || mIsEnterTriggered) {
return;
}
+ mIsEnterTriggered = true;
mHasExited = false;
ArrayList<String> sharedElementNames = mEnterActivityOptions.getSharedElementNames();
ResultReceiver resultReceiver = mEnterActivityOptions.getResultReceiver();
@@ -259,6 +264,7 @@
return;
}
ActivityOptions activityOptions = new ActivityOptions(options);
+ mEnterTransitionCoordinator = null;
if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
int key = activityOptions.getExitCoordinatorKey();
int index = mExitTransitionCoordinators.indexOfKey(key);
diff --git a/core/java/android/app/AppImportanceMonitor.java b/core/java/android/app/AppImportanceMonitor.java
new file mode 100644
index 0000000..c760e1e
--- /dev/null
+++ b/core/java/android/app/AppImportanceMonitor.java
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+
+import java.util.List;
+
+/**
+ * Helper for monitoring the current importance of applications.
+ * @hide
+ */
+public class AppImportanceMonitor {
+ final Context mContext;
+
+ final SparseArray<AppEntry> mApps = new SparseArray<>();
+
+ static class AppEntry {
+ final int uid;
+ final SparseArray<Integer> procs = new SparseArray<>(1);
+ int importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
+
+ AppEntry(int _uid) {
+ uid = _uid;
+ }
+ }
+
+ final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
+ @Override
+ public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
+ }
+
+ @Override
+ public void onProcessStateChanged(int pid, int uid, int procState) {
+ synchronized (mApps) {
+ updateImportanceLocked(pid, uid,
+ ActivityManager.RunningAppProcessInfo.procStateToImportance(procState),
+ true);
+ }
+ }
+
+ @Override
+ public void onProcessDied(int pid, int uid) {
+ synchronized (mApps) {
+ updateImportanceLocked(pid, uid,
+ ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, true);
+ }
+ }
+ };
+
+ static final int MSG_UPDATE = 1;
+
+ final Handler mHandler;
+
+ public AppImportanceMonitor(Context context, Looper looper) {
+ mContext = context;
+ mHandler = new Handler(looper) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE:
+ onImportanceChanged(msg.arg1, msg.arg2&0xffff, msg.arg2>>16);
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ };
+ ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
+ try {
+ ActivityManagerNative.getDefault().registerProcessObserver(mProcessObserver);
+ } catch (RemoteException e) {
+ }
+ List<ActivityManager.RunningAppProcessInfo> apps = am.getRunningAppProcesses();
+ if (apps != null) {
+ for (int i=0; i<apps.size(); i++) {
+ ActivityManager.RunningAppProcessInfo app = apps.get(i);
+ updateImportanceLocked(app.uid, app.pid, app.importance, false);
+ }
+ }
+ }
+
+ public int getImportance(int uid) {
+ AppEntry ent = mApps.get(uid);
+ if (ent == null) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
+ }
+ return ent.importance;
+ }
+
+ /**
+ * Report when an app's importance changed. Called on looper given to constructor.
+ */
+ public void onImportanceChanged(int uid, int importance, int oldImportance) {
+ }
+
+ void updateImportanceLocked(int uid, int pid, int importance, boolean repChange) {
+ AppEntry ent = mApps.get(uid);
+ if (ent == null) {
+ ent = new AppEntry(uid);
+ mApps.put(uid, ent);
+ }
+ if (importance >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
+ ent.procs.remove(pid);
+ } else {
+ ent.procs.put(pid, importance);
+ }
+ updateImportanceLocked(ent, repChange);
+ }
+
+ void updateImportanceLocked(AppEntry ent, boolean repChange) {
+ int appImp = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
+ for (int i=0; i<ent.procs.size(); i++) {
+ int procImp = ent.procs.valueAt(i);
+ if (procImp < appImp) {
+ appImp = procImp;
+ }
+ }
+ if (appImp != ent.importance) {
+ int impCode = appImp | (ent.importance<<16);
+ ent.importance = appImp;
+ if (appImp >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
+ mApps.remove(ent.uid);
+ }
+ if (repChange) {
+ mHandler.obtainMessage(MSG_UPDATE, ent.uid, impCode).sendToTarget();
+ }
+ }
+ }
+}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 2935b8e..6a51371 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -33,6 +33,7 @@
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
+import android.content.pm.KeySet;
import android.content.pm.ManifestDigest;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
@@ -52,6 +53,7 @@
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -59,6 +61,8 @@
import android.util.ArrayMap;
import android.util.Log;
import android.view.Display;
+import com.android.internal.util.Preconditions;
+import dalvik.system.VMRuntime;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -248,6 +252,10 @@
try {
ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags, mContext.getUserId());
if (ai != null) {
+ // This is a temporary hack. Callers must use
+ // createPackageContext(packageName).getApplicationInfo() to
+ // get the right paths.
+ maybeAdjustApplicationInfo(ai);
return ai;
}
} catch (RemoteException e) {
@@ -257,6 +265,24 @@
throw new NameNotFoundException(packageName);
}
+ private static void maybeAdjustApplicationInfo(ApplicationInfo info) {
+ // If we're dealing with a multi-arch application that has both
+ // 32 and 64 bit shared libraries, we might need to choose the secondary
+ // depending on what the current runtime's instruction set is.
+ if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
+ final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
+ final String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
+
+ // If the runtimeIsa is the same as the primary isa, then we do nothing.
+ // Everything will be set up correctly because info.nativeLibraryDir will
+ // correspond to the right ISA.
+ if (runtimeIsa.equals(secondaryIsa)) {
+ info.nativeLibraryDir = info.secondaryNativeLibraryDir;
+ }
+ }
+ }
+
+
@Override
public ActivityInfo getActivityInfo(ComponentName className, int flags)
throws NameNotFoundException {
@@ -1447,6 +1473,62 @@
return false;
}
+ @Override
+ public KeySet getKeySetByAlias(String packageName, String alias) {
+ Preconditions.checkNotNull(packageName);
+ Preconditions.checkNotNull(alias);
+ IBinder keySetToken;
+ try {
+ keySetToken = mPM.getKeySetByAlias(packageName, alias);
+ } catch (RemoteException e) {
+ return null;
+ }
+ if (keySetToken == null) {
+ return null;
+ }
+ return new KeySet(keySetToken);
+ }
+
+ @Override
+ public KeySet getSigningKeySet(String packageName) {
+ Preconditions.checkNotNull(packageName);
+ IBinder keySetToken;
+ try {
+ keySetToken = mPM.getSigningKeySet(packageName);
+ } catch (RemoteException e) {
+ return null;
+ }
+ if (keySetToken == null) {
+ return null;
+ }
+ return new KeySet(keySetToken);
+ }
+
+
+ @Override
+ public boolean isSignedBy(String packageName, KeySet ks) {
+ Preconditions.checkNotNull(packageName);
+ Preconditions.checkNotNull(ks);
+ IBinder keySetToken = ks.getToken();
+ try {
+ return mPM.isPackageSignedByKeySet(packageName, keySetToken);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isSignedByExactly(String packageName, KeySet ks) {
+ Preconditions.checkNotNull(packageName);
+ Preconditions.checkNotNull(ks);
+ IBinder keySetToken = ks.getToken();
+ try {
+ return mPM.isPackageSignedByKeySetExactly(packageName, keySetToken);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
/**
* @hide
*/
@@ -1461,7 +1543,7 @@
}
@Override
- public PackageInstaller getPackageInstaller() {
+ public PackageInstaller getInstaller() {
try {
return new PackageInstaller(this, mPM.getPackageInstaller(), mContext.getPackageName(),
mContext.getUserId());
@@ -1470,6 +1552,15 @@
}
}
+ @Override
+ public boolean isPackageAvailable(String packageName) {
+ try {
+ return mPM.isPackageAvailable(packageName, mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index bbfb05e..cbfde14 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -16,8 +16,6 @@
package android.app;
-import android.net.wifi.IWifiScanner;
-import android.net.wifi.WifiScanner;
import android.os.Build;
import android.service.persistentdata.IPersistentDataBlockService;
@@ -93,6 +91,10 @@
import android.net.wifi.passpoint.WifiPasspointManager;
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.IWifiScanner;
+import android.net.wifi.WifiScanner;
+import android.net.wifi.IRttManager;
+import android.net.wifi.RttManager;
import android.nfc.NfcManager;
import android.os.BatteryManager;
import android.os.Binder;
@@ -247,7 +249,11 @@
@GuardedBy("mSync")
private File mFilesDir;
@GuardedBy("mSync")
+ private File mNoBackupFilesDir;
+ @GuardedBy("mSync")
private File mCacheDir;
+ @GuardedBy("mSync")
+ private File mCodeCacheDir;
@GuardedBy("mSync")
private File[] mExternalObbDirs;
@@ -558,9 +564,7 @@
registerService(TELECOMM_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
- IBinder b = ServiceManager.getService(TELECOMM_SERVICE);
- return new TelecommManager(ctx.getOuterContext(),
- ITelecommService.Stub.asInterface(b));
+ return new TelecommManager(ctx.getOuterContext());
}});
registerService(PHONE_SERVICE, new ServiceFetcher() {
@@ -620,6 +624,13 @@
return new WifiScanner(ctx.getOuterContext(), service);
}});
+ registerService(WIFI_RTT_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(WIFI_RTT_SERVICE);
+ IRttManager service = IRttManager.Stub.asInterface(b);
+ return new RttManager(ctx.getOuterContext(), service);
+ }});
+
registerService(ETHERNET_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(ETHERNET_SERVICE);
@@ -963,27 +974,42 @@
return f.delete();
}
+ // Common-path handling of app data dir creation
+ private static File createFilesDirLocked(File file) {
+ if (!file.exists()) {
+ if (!file.mkdirs()) {
+ if (file.exists()) {
+ // spurious failure; probably racing with another process for this app
+ return file;
+ }
+ Log.w(TAG, "Unable to create files subdir " + file.getPath());
+ return null;
+ }
+ FileUtils.setPermissions(
+ file.getPath(),
+ FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+ -1, -1);
+ }
+ return file;
+ }
+
@Override
public File getFilesDir() {
synchronized (mSync) {
if (mFilesDir == null) {
mFilesDir = new File(getDataDirFile(), "files");
}
- if (!mFilesDir.exists()) {
- if(!mFilesDir.mkdirs()) {
- if (mFilesDir.exists()) {
- // spurious failure; probably racing with another process for this app
- return mFilesDir;
- }
- Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath());
- return null;
- }
- FileUtils.setPermissions(
- mFilesDir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
+ return createFilesDirLocked(mFilesDir);
+ }
+ }
+
+ @Override
+ public File getNoBackupFilesDir() {
+ synchronized (mSync) {
+ if (mNoBackupFilesDir == null) {
+ mNoBackupFilesDir = new File(getDataDirFile(), "no_backup");
}
- return mFilesDir;
+ return createFilesDirLocked(mNoBackupFilesDir);
}
}
@@ -1035,22 +1061,18 @@
if (mCacheDir == null) {
mCacheDir = new File(getDataDirFile(), "cache");
}
- if (!mCacheDir.exists()) {
- if(!mCacheDir.mkdirs()) {
- if (mCacheDir.exists()) {
- // spurious failure; probably racing with another process for this app
- return mCacheDir;
- }
- Log.w(TAG, "Unable to create cache directory " + mCacheDir.getAbsolutePath());
- return null;
- }
- FileUtils.setPermissions(
- mCacheDir.getPath(),
- FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
- -1, -1);
- }
+ return createFilesDirLocked(mCacheDir);
}
- return mCacheDir;
+ }
+
+ @Override
+ public File getCodeCacheDir() {
+ synchronized (mSync) {
+ if (mCodeCacheDir == null) {
+ mCodeCacheDir = new File(getDataDirFile(), "code_cache");
+ }
+ return createFilesDirLocked(mCodeCacheDir);
+ }
}
@Override
@@ -2075,7 +2097,7 @@
}
LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
- flags, user.getIdentifier());
+ flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
if (pi != null) {
ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
user, restricted, mDisplay, mOverrideConfiguration);
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 26c2c30..d7fb707 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -21,6 +21,7 @@
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.text.format.DateUtils;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.DatePicker;
@@ -44,10 +45,11 @@
private static final String DAY = "day";
private final DatePicker mDatePicker;
- private final OnDateSetListener mCallBack;
+ private final OnDateSetListener mDateSetListener;
private final Calendar mCalendar;
private boolean mTitleNeedsUpdate = true;
+ private boolean mIsCanceled = false;
/**
* The callback used to indicate the user is done filling in the date.
@@ -79,29 +81,36 @@
this(context, 0, callBack, year, monthOfYear, dayOfMonth);
}
+ static int resolveDialogTheme(Context context, int resid) {
+ if (resid == 0) {
+ TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(R.attr.datePickerDialogTheme, outValue, true);
+ return outValue.resourceId;
+ } else {
+ return resid;
+ }
+ }
+
/**
* @param context The context the dialog is to run in.
* @param theme the theme to apply to this dialog
- * @param callBack How the parent is notified that the date is set.
+ * @param listener How the parent is notified that the date is set.
* @param year The initial year of the dialog.
* @param monthOfYear The initial month of the dialog.
* @param dayOfMonth The initial day of the dialog.
*/
public DatePickerDialog(Context context,
int theme,
- OnDateSetListener callBack,
+ OnDateSetListener listener,
int year,
int monthOfYear,
int dayOfMonth) {
- super(context, theme);
+ super(context, resolveDialogTheme(context, theme));
- mCallBack = callBack;
-
+ mDateSetListener = listener;
mCalendar = Calendar.getInstance();
Context themeContext = getContext();
- setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_done), this);
- setIcon(0);
LayoutInflater inflater =
(LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -109,20 +118,53 @@
setView(view);
setButtonPanelLayoutHint(LAYOUT_HINT_SIDE);
mDatePicker = (DatePicker) view.findViewById(R.id.datePicker);
+
+ // Initialize state
+ mDatePicker.setLegacyMode(false, null);
+ mDatePicker.setShowDoneButton(true);
+ mDatePicker.setDismissCallback(new DatePicker.DatePickerDismissCallback() {
+ @Override
+ public void dismiss(DatePicker view, boolean isCancel, int year, int month, int dayOfMonth) {
+ mIsCanceled = isCancel;
+ if (!isCancel) {
+ mDateSetListener.onDateSet(view, year, month, dayOfMonth);
+ }
+ DatePickerDialog.this.dismiss();
+ }
+ });
mDatePicker.init(year, monthOfYear, dayOfMonth, this);
- updateTitle(year, monthOfYear, dayOfMonth);
}
public void onClick(DialogInterface dialog, int which) {
tryNotifyDateSet();
}
+ @Override
+ public void cancel() {
+ mIsCanceled = true;
+ super.cancel();
+ }
+
+ @Override
+ protected void onStop() {
+ tryNotifyDateSet();
+ super.onStop();
+ }
+
public void onDateChanged(DatePicker view, int year,
int month, int day) {
mDatePicker.init(year, month, day, this);
updateTitle(year, month, day);
}
+ private void tryNotifyDateSet() {
+ if (mDateSetListener != null && !mIsCanceled) {
+ mDatePicker.clearFocus();
+ mDateSetListener.onDateSet(mDatePicker, mDatePicker.getYear(),
+ mDatePicker.getMonth(), mDatePicker.getDayOfMonth());
+ }
+ }
+
/**
* Gets the {@link DatePicker} contained in this dialog.
*
@@ -143,20 +185,6 @@
mDatePicker.updateDate(year, monthOfYear, dayOfMonth);
}
- private void tryNotifyDateSet() {
- if (mCallBack != null) {
- mDatePicker.clearFocus();
- mCallBack.onDateSet(mDatePicker, mDatePicker.getYear(),
- mDatePicker.getMonth(), mDatePicker.getDayOfMonth());
- }
- }
-
- @Override
- protected void onStop() {
- tryNotifyDateSet();
- super.onStop();
- }
-
private void updateTitle(int year, int month, int day) {
if (!mDatePicker.getCalendarViewShown()) {
mCalendar.set(Calendar.YEAR, year);
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index f50c93b..1326064 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -282,7 +282,7 @@
ArrayList<View> sharedElementSnapshots = createSnapshots(sharedElementState,
mSharedElementNames);
setTransitionAlpha(mSharedElements, 1);
- ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalImageViewState =
+ ArrayList<SharedElementOriginalState> originalImageViewState =
setSharedElementState(sharedElementState, sharedElementSnapshots);
requestLayoutForSharedElements();
@@ -294,7 +294,7 @@
startEnterTransition(transition);
}
- setOriginalImageViewState(originalImageViewState);
+ setOriginalSharedElementState(mSharedElements, originalImageViewState);
if (mResultReceiver != null) {
// We can't trust that the view will disappear on the same frame that the shared
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 3f3e00c..4f5a098 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -329,7 +329,7 @@
private Bundle captureExitSharedElementsState() {
Bundle bundle = new Bundle();
Rect bounds = new Rect();
- for (int i = 0; i < mSharedElementNames.size(); i++) {
+ for (int i = 0; i < mSharedElements.size(); i++) {
String name = mSharedElementNames.get(i);
Bundle sharedElementState = mExitSharedElementBundle.getBundle(name);
if (sharedElementState != null) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index b3a8a8a..ac29161 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -294,7 +294,9 @@
public void stopAppSwitches() throws RemoteException;
public void resumeAppSwitches() throws RemoteException;
-
+
+ public void addPackageDependency(String packageName) throws RemoteException;
+
public void killApplicationWithAppId(String pkg, int appid, String reason)
throws RemoteException;
@@ -444,6 +446,8 @@
public boolean isBackgroundMediaPlaying(IBinder token) throws RemoteException;
public void mediaResourcesReleased(IBinder token) throws RemoteException;
+ public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -638,7 +642,7 @@
int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
- int ___AVAILABLE_2___ = IBinder.FIRST_CALL_TRANSACTION+94;
+ int ADD_PACKAGE_DEPENDENCY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95;
int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96;
int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97;
@@ -750,5 +754,6 @@
int IS_TOP_OF_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+224;
int SET_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+225;
int IS_BG_MEDIA_PLAYING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+226;
- int MEDIA_RESOURCES_RELEASED = IBinder.FIRST_CALL_TRANSACTION+227;
+ int MEDIA_RESOURCES_RELEASED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+227;
+ int NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+228;
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index a3ffc00..5b92538 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -44,6 +44,9 @@
void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled);
boolean areNotificationsEnabledForPackage(String pkg, int uid);
+ void setPackagePriority(String pkg, int uid, int priority);
+ int getPackagePriority(String pkg, int uid);
+
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
StatusBarNotification[] getActiveNotifications(String callingPkg);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 065e88d..24c2835 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -44,6 +44,7 @@
import android.util.SparseArray;
import android.view.DisplayAdjustments;
import android.view.Display;
+import dalvik.system.VMRuntime;
import java.io.File;
import java.io.IOException;
@@ -55,6 +56,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Objects;
final class IntentReceiverLeaked extends AndroidRuntimeException {
public IntentReceiverLeaked(String msg) {
@@ -91,6 +93,7 @@
private final ClassLoader mBaseClassLoader;
private final boolean mSecurityViolation;
private final boolean mIncludeCode;
+ private final boolean mRegisterPackage;
private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Resources mResources;
private ClassLoader mClassLoader;
@@ -119,8 +122,10 @@
*/
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
CompatibilityInfo compatInfo, ClassLoader baseLoader,
- boolean securityViolation, boolean includeCode) {
+ boolean securityViolation, boolean includeCode, boolean registerPackage) {
final int myUid = Process.myUid();
+ aInfo = adjustNativeLibraryPaths(aInfo);
+
mActivityThread = activityThread;
mApplicationInfo = aInfo;
mPackageName = aInfo.packageName;
@@ -140,9 +145,31 @@
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
+ mRegisterPackage = registerPackage;
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
}
+ private static ApplicationInfo adjustNativeLibraryPaths(ApplicationInfo info) {
+ // If we're dealing with a multi-arch application that has both
+ // 32 and 64 bit shared libraries, we might need to choose the secondary
+ // depending on what the current runtime's instruction set is.
+ if (info.primaryCpuAbi != null && info.secondaryCpuAbi != null) {
+ final String runtimeIsa = VMRuntime.getRuntime().vmInstructionSet();
+ final String secondaryIsa = VMRuntime.getInstructionSet(info.secondaryCpuAbi);
+
+ // If the runtimeIsa is the same as the primary isa, then we do nothing.
+ // Everything will be set up correctly because info.nativeLibraryDir will
+ // correspond to the right ISA.
+ if (runtimeIsa.equals(secondaryIsa)) {
+ final ApplicationInfo modified = new ApplicationInfo(info);
+ modified.nativeLibraryDir = modified.secondaryNativeLibraryDir;
+ return modified;
+ }
+ }
+
+ return info;
+ }
+
/**
* Create information about the system package.
* Must call {@link #installSystemApplicationInfo} later.
@@ -164,6 +191,7 @@
mBaseClassLoader = null;
mSecurityViolation = false;
mIncludeCode = true;
+ mRegisterPackage = false;
mClassLoader = ClassLoader.getSystemClassLoader();
mResources = Resources.getSystem();
}
@@ -228,9 +256,32 @@
}
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())) {
+ final String isa = VMRuntime.getRuntime().vmInstructionSet();
+ try {
+ // TODO: We can probably do away with the isa argument since
+ // the AM and PM have enough information to figure this out
+ // themselves. If we do need it, we should match it against the
+ // list of devices ISAs before sending it down to installd.
+ ActivityThread.getPackageManager().performDexOptIfNeeded(mPackageName, isa);
+ } catch (RemoteException re) {
+ // Ignored.
+ }
+ }
+
final ArrayList<String> zipPaths = new ArrayList<>();
final ArrayList<String> libPaths = new ArrayList<>();
+ if (mRegisterPackage) {
+ try {
+ ActivityManagerNative.getDefault().addPackageDependency(mPackageName);
+ } catch (RemoteException e) {
+ }
+ }
+
zipPaths.add(mAppDir);
if (mSplitAppDirs != null) {
Collections.addAll(zipPaths, mSplitAppDirs);
diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java
index 7117111..1b2504e 100644
--- a/core/java/android/app/PackageInstallObserver.java
+++ b/core/java/android/app/PackageInstallObserver.java
@@ -25,7 +25,7 @@
@Override
public void packageInstalled(String basePackageName, Bundle extras, int returnCode,
String msg) {
- PackageInstallObserver.this.packageInstalled(basePackageName, extras, returnCode);
+ PackageInstallObserver.this.packageInstalled(basePackageName, extras, returnCode, msg);
}
};
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index ac74ca1..ff2a174 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
+import android.os.Build;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
@@ -28,8 +29,6 @@
import com.android.internal.R;
-import static android.os.Build.VERSION_CODES.L;
-
/**
* A dialog that prompts the user for the time of day using a {@link TimePicker}.
*
@@ -64,6 +63,8 @@
int mInitialMinute;
boolean mIs24HourView;
+ private boolean mIsCanceled;
+
/**
* @param context Parent.
* @param callBack How parent is notified.
@@ -100,34 +101,37 @@
OnTimeSetListener callBack,
int hourOfDay, int minute, boolean is24HourView) {
super(context, resolveDialogTheme(context, theme));
+
mTimeSetCallback = callBack;
mInitialHourOfDay = hourOfDay;
mInitialMinute = minute;
mIs24HourView = is24HourView;
- Context themeContext = getContext();
+ final Context themeContext = getContext();
- final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
- if (targetSdkVersion < L) {
+ final int targetSdkVersion = themeContext.getApplicationInfo().targetSdkVersion;
+ if (targetSdkVersion < Build.VERSION_CODES.L) {
setIcon(0);
setTitle(R.string.time_picker_dialog_title);
setButton(BUTTON_POSITIVE, themeContext.getText(R.string.date_time_done), this);
}
- LayoutInflater inflater =
- (LayoutInflater) themeContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.time_picker_dialog, null);
+ final LayoutInflater inflater = LayoutInflater.from(themeContext);
+ final View view = inflater.inflate(R.layout.time_picker_dialog, null);
setView(view);
- mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
+ mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
mTimePicker.setShowDoneButton(true);
mTimePicker.setDismissCallback(new TimePicker.TimePickerDismissCallback() {
@Override
public void dismiss(TimePicker view, boolean isCancel, int hourOfDay, int minute) {
+ mIsCanceled = isCancel;
if (!isCancel) {
mTimeSetCallback.onTimeSet(view, hourOfDay, minute);
+ TimePickerDialog.this.dismiss();
+ } else {
+ TimePickerDialog.this.cancel();
}
- TimePickerDialog.this.dismiss();
}
});
mTimePicker.setIs24HourView(mIs24HourView);
@@ -150,7 +154,7 @@
}
private void tryNotifyTimeSet() {
- if (mTimeSetCallback != null) {
+ if (mTimeSetCallback != null && !mIsCanceled) {
mTimePicker.clearFocus();
mTimeSetCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
mTimePicker.getCurrentMinute());
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7790640..4e7dac0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2243,7 +2243,7 @@
* application running in the managed profile.
*
* <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be
- * {@link Boolean}, {@link String}, or {@link String}[]. The recommended format for key strings
+ * boolean, int, String, or String[]. The recommended format for keys
* is "com.example.packagename/example-setting" to avoid naming conflicts with library
* components such as {@link android.webkit.WebView}.
*
@@ -2524,6 +2524,45 @@
}
/**
+ * Called by profile or device owner to re-enable a system app that was disabled by default
+ * when the managed profile was created. This can only be called from a profile or device
+ * owner running within a managed profile.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageName The package to be re-enabled in the current profile.
+ */
+ public void enableSystemApp(ComponentName admin, String packageName) {
+ if (mService != null) {
+ try {
+ mService.enableSystemApp(admin, packageName);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to install package: " + packageName);
+ }
+ }
+ }
+
+ /**
+ * Called by profile or device owner to re-enable system apps by intent that were disabled
+ * by default when the managed profile was created. This can only be called from a profile
+ * or device owner running within a managed profile.
+ *
+ * @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 current profile.
+ * @return int The number of activities that matched the intent and were installed.
+ */
+ public int enableSystemApp(ComponentName admin, Intent intent) {
+ if (mService != null) {
+ try {
+ return mService.enableSystemAppWithIntent(admin, intent);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to install packages matching filter: " + intent);
+ }
+ }
+ return 0;
+ }
+
+ /**
* Called by a profile owner to disable account management for a specific type of account.
*
* <p>The calling device admin must be a profile owner. If it is not, a
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c27d1cc..d36497e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -141,6 +141,9 @@
boolean removeUser(in ComponentName who, in UserHandle userHandle);
boolean switchUser(in ComponentName who, in UserHandle userHandle);
+ void enableSystemApp(in ComponentName admin, in String packageName);
+ int enableSystemAppWithIntent(in ComponentName admin, in Intent intent);
+
void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled);
String[] getAccountTypesWithManagementDisabled();
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 886f1a6..e2a86e8 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -247,12 +247,40 @@
throws IOException;
/**
- * The default implementation backs up the entirety of the application's "owned"
- * file system trees to the output.
+ * The application is having its entire file system contents backed up. {@code data}
+ * points to the backup destination, and the app has the opportunity to choose which
+ * files are to be stored. To commit a file as part of the backup, call the
+ * {@link #fullBackupFile(File, FullBackupDataOutput)} helper method. After all file
+ * data is written to the output, the agent returns from this method and the backup
+ * operation concludes.
+ *
+ * <p>Certain parts of the app's data are never backed up even if the app explicitly
+ * sends them to the output:
+ *
+ * <ul>
+ * <li>The contents of the {@link #getCacheDir()} directory</li>
+ * <li>The contents of the {@link #getNoBackupFilesDir()} directory</li>
+ * <li>The contents of the app's shared library directory</li>
+ * </ul>
+ *
+ * <p>The default implementation of this method backs up the entirety of the
+ * application's "owned" file system trees to the output other than the few exceptions
+ * listed above. Apps only need to override this method if they need to impose special
+ * limitations on which files are being stored beyond the control that
+ * {@link #getNoBackupFilesDir()} offers.
+ *
+ * @param data A structured wrapper pointing to the backup destination.
+ * @throws IOException
+ *
+ * @see Context#getNoBackupFilesDir()
+ * @see #fullBackupFile(File, FullBackupDataOutput)
+ * @see #onRestoreFile(ParcelFileDescriptor, long, File, int, long, long)
*/
public void onFullBackup(FullBackupDataOutput data) throws IOException {
ApplicationInfo appInfo = getApplicationInfo();
+ // Note that we don't need to think about the no_backup dir because it's outside
+ // all of the ones we will be traversing
String rootDir = new File(appInfo.dataDir).getCanonicalPath();
String filesDir = getFilesDir().getCanonicalPath();
String databaseDir = getDatabasePath("foo").getParentFile().getCanonicalPath();
@@ -311,6 +339,10 @@
* to place it with the proper location and permissions on the device where the
* data is restored.
*
+ * <p class="note">It is safe to explicitly back up files underneath your application's
+ * {@link #getNoBackupFilesDir()} directory, and they will be restored to that
+ * location correctly.
+ *
* @param file The file to be backed up. The file must exist and be readable by
* the caller.
* @param output The destination to which the backed-up file data will be sent.
@@ -319,6 +351,7 @@
// Look up where all of our various well-defined dir trees live on this device
String mainDir;
String filesDir;
+ String nbFilesDir;
String dbDir;
String spDir;
String cacheDir;
@@ -331,6 +364,7 @@
try {
mainDir = new File(appInfo.dataDir).getCanonicalPath();
filesDir = getFilesDir().getCanonicalPath();
+ nbFilesDir = getNoBackupFilesDir().getCanonicalPath();
dbDir = getDatabasePath("foo").getParentFile().getCanonicalPath();
spDir = getSharedPrefsFile("foo").getParentFile().getCanonicalPath();
cacheDir = getCacheDir().getCanonicalPath();
@@ -354,8 +388,10 @@
return;
}
- if (filePath.startsWith(cacheDir) || filePath.startsWith(libDir)) {
- Log.w(TAG, "lib and cache files are not backed up");
+ if (filePath.startsWith(cacheDir)
+ || filePath.startsWith(libDir)
+ || filePath.startsWith(nbFilesDir)) {
+ Log.w(TAG, "lib, cache, and no_backup files are not backed up");
return;
}
@@ -508,6 +544,8 @@
mode = -1; // < 0 is a token to skip attempting a chmod()
}
}
+ } else if (domain.equals(FullBackup.NO_BACKUP_TREE_TOKEN)) {
+ basePath = getNoBackupFilesDir().getCanonicalPath();
} else {
// Not a supported location
Log.i(TAG, "Unrecognized domain " + domain);
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index ba2930b..28108a0 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -331,6 +331,10 @@
* its datastore, if appropriate, and close the socket that had been provided in
* {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}.
*
+ * <p class="note">If the transport returns TRANSPORT_OK from this method, then the
+ * OS will always provide a matching call to {@link #finishBackup()} even if sending
+ * data via {@link #sendBackupData(int)} failed at some point.
+ *
* @param targetPackage The package whose data is to follow.
* @param socket The socket file descriptor through which the data will be provided.
* If the transport returns {@link #TRANSPORT_PACKAGE_REJECTED} here, it must still
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index 6ebb6c4..e5b47c6 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -40,6 +40,7 @@
public static final String OBB_TREE_TOKEN = "obb";
public static final String ROOT_TREE_TOKEN = "r";
public static final String DATA_TREE_TOKEN = "f";
+ public static final String NO_BACKUP_TREE_TOKEN = "nb";
public static final String DATABASE_TREE_TOKEN = "db";
public static final String SHAREDPREFS_TREE_TOKEN = "sp";
public static final String MANAGED_EXTERNAL_TREE_TOKEN = "ef";
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 97e3fc5..faf8645 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -219,22 +219,6 @@
"android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
/**
- * Broadcast Action: Indicate BLE Advertising is started.
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BLUETOOTH_ADVERTISING_STARTED =
- "android.bluetooth.adapter.action.ADVERTISING_STARTED";
-
- /**
- * Broadcast Action: Indicated BLE Advertising is stopped.
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_BLUETOOTH_ADVERTISING_STOPPED =
- "android.bluetooth.adapter.action.ADVERTISING_STOPPED";
-
- /**
* Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
* intents to request the current scan mode. Possible values are:
* {@link #SCAN_MODE_NONE},
@@ -403,8 +387,6 @@
private IBluetooth mService;
private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients;
- private BluetoothAdvScanData mBluetoothAdvScanData = null;
- private GattCallbackWrapper mAdvertisingGattCallback;
private final Handler mHandler; // Handler to post the advertise callback to run on main thread.
private final Object mLock = new Object();
@@ -481,29 +463,6 @@
}
/**
- * Returns a {@link BluetoothAdvScanData} object representing advertising data.
- * Data will be reset when bluetooth service is turned off.
- * @hide
- */
- public BluetoothAdvScanData getAdvScanData() {
- try {
- IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
- if (iGatt == null) {
- // BLE is not supported
- Log.e(TAG, "failed to start, iGatt null");
- return null;
- }
- if (mBluetoothAdvScanData == null) {
- mBluetoothAdvScanData = new BluetoothAdvScanData(iGatt, BluetoothAdvScanData.AD);
- }
- return mBluetoothAdvScanData;
- } catch (RemoteException e) {
- Log.e(TAG, "failed to get advScanData, error: " + e);
- return null;
- }
- }
-
- /**
* Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
*/
public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
@@ -520,106 +479,6 @@
}
/**
- * Interface for BLE advertising callback.
- *
- * @hide
- */
- public interface AdvertiseCallback {
- /**
- * Callback when advertise starts.
- * @param status - {@link #ADVERTISE_CALLBACK_SUCCESS} for success, others for failure.
- */
- void onAdvertiseStart(int status);
- /**
- * Callback when advertise stops.
- * @param status - {@link #ADVERTISE_CALLBACK_SUCCESS} for success, others for failure.
- */
- void onAdvertiseStop(int status);
- }
-
- /**
- * Start BLE advertising using current {@link BluetoothAdvScanData}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
- *
- * @param callback - {@link AdvertiseCallback}
- * @return true if BLE advertising succeeds, false otherwise.
- * @hide
- */
- public boolean startAdvertising(final AdvertiseCallback callback) {
- if (getState() != STATE_ON) return false;
- try {
- IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
- if (iGatt == null) {
- // BLE is not supported.
- return false;
- }
- // Restart/reset advertising packets if advertising is in progress.
- if (isAdvertising()) {
- // Invalid advertising callback.
- if (mAdvertisingGattCallback == null || mAdvertisingGattCallback.mLeHandle == -1) {
- Log.e(TAG, "failed to restart advertising, invalid callback");
- return false;
- }
- iGatt.startAdvertising(mAdvertisingGattCallback.mLeHandle);
- // Run the callback from main thread.
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- // callback with status success.
- callback.onAdvertiseStart(ADVERTISE_CALLBACK_SUCCESS);
- }
- });
- return true;
- }
- UUID uuid = UUID.randomUUID();
- GattCallbackWrapper wrapper =
- new GattCallbackWrapper(this, null, null, callback);
- iGatt.registerClient(new ParcelUuid(uuid), wrapper);
- if (!wrapper.advertiseStarted()) {
- return false;
- }
- synchronized (mLock) {
- mAdvertisingGattCallback = wrapper;
- }
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
- }
-
- /**
- * Stop BLE advertising. The callback has to be the same one used for start advertising.
- *
- * @param callback - {@link AdvertiseCallback}
- * @return true if BLE advertising stops, false otherwise.
- * @hide
- */
- public boolean stopAdvertising(AdvertiseCallback callback) {
- try {
- IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
- if (iGatt == null) {
- // BLE is not supported
- return false;
- }
- if (mAdvertisingGattCallback == null) {
- // no callback.
- return false;
- }
- // Make sure same callback is used for start and stop advertising.
- if (callback != mAdvertisingGattCallback.mAdvertiseCallback) {
- Log.e(TAG, "must use the same callback for star/stop advertising");
- return false;
- }
- mAdvertisingGattCallback.stopAdvertising();
- return true;
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- return false;
- }
- }
-
- /**
* Return true if Bluetooth is currently enabled and ready for use.
* <p>Equivalent to:
* <code>getBluetoothState() == STATE_ON</code>
@@ -1076,23 +935,6 @@
}
/**
- * Returns whether BLE is currently advertising.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
- *
- * @hide
- */
- public boolean isAdvertising() {
- if (getState() != STATE_ON) return false;
- try {
- IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
- return iGatt.isAdvertising();
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- }
- return false;
- }
-
- /**
* Return the set of {@link BluetoothDevice} objects that are bonded
* (paired) to the local adapter.
* <p>If Bluetooth state is not {@link #STATE_ON}, this API
@@ -1537,8 +1379,6 @@
if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
synchronized (mManagerCallback) {
mService = null;
- // Reset bluetooth adv scan data when Gatt service is down.
- mBluetoothAdvScanData = null;
for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
try {
if (cb != null) {
@@ -1822,7 +1662,6 @@
private static final int LE_CALLBACK_REG_TIMEOUT = 2000;
private static final int LE_CALLBACK_REG_WAIT_COUNT = 5;
- private final AdvertiseCallback mAdvertiseCallback;
private final LeScanCallback mLeScanCb;
// mLeHandle 0: not registered
@@ -1838,27 +1677,12 @@
mLeScanCb = leScanCb;
mScanFilter = uuid;
mLeHandle = 0;
- mAdvertiseCallback = null;
- }
-
- public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb,
- UUID[] uuid, AdvertiseCallback callback) {
- mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter);
- mLeScanCb = leScanCb;
- mScanFilter = uuid;
- mLeHandle = 0;
- mAdvertiseCallback = callback;
}
public boolean scanStarted() {
return waitForRegisteration(LE_CALLBACK_REG_WAIT_COUNT);
}
- public boolean advertiseStarted() {
- // Wait for registeration callback.
- return waitForRegisteration(1);
- }
-
private boolean waitForRegisteration(int maxWaitCount) {
boolean started = false;
synchronized(this) {
@@ -1878,27 +1702,6 @@
return started;
}
- public void stopAdvertising() {
- synchronized (this) {
- if (mLeHandle <= 0) {
- Log.e(TAG, "Error state, mLeHandle: " + mLeHandle);
- return;
- }
- BluetoothAdapter adapter = mBluetoothAdapter.get();
- if (adapter != null) {
- try {
- IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt();
- iGatt.stopAdvertising();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to stop advertising" + e);
- }
- } else {
- Log.e(TAG, "stopAdvertising, BluetoothAdapter is null");
- }
- notifyAll();
- }
- }
-
public void stopLeScan() {
synchronized(this) {
if (mLeHandle <= 0) {
@@ -1940,18 +1743,14 @@
BluetoothAdapter adapter = mBluetoothAdapter.get();
if (adapter != null) {
iGatt = adapter.getBluetoothManager().getBluetoothGatt();
- if (mAdvertiseCallback != null) {
- iGatt.startAdvertising(mLeHandle);
+ if (mScanFilter == null) {
+ iGatt.startScan(mLeHandle, false);
} else {
- if (mScanFilter == null) {
- iGatt.startScan(mLeHandle, false);
- } else {
- ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(mScanFilter[i]);
- }
- iGatt.startScanWithUuids(mLeHandle, false, uuids);
- }
+ ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
+ for(int i = 0; i != uuids.length; ++i) {
+ uuids[i] = new ParcelUuid(mScanFilter[i]);
+ }
+ iGatt.startScanWithUuids(mLeHandle, false, uuids);
}
} else {
Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
@@ -2080,44 +1879,6 @@
}
public void onAdvertiseStateChange(int advertiseState, int status) {
- Log.d(TAG, "on advertise call back, state: " + advertiseState + " status: " + status);
- if (advertiseState == STATE_ADVERTISE_STARTED) {
- if (status == ADVERTISE_CALLBACK_SUCCESS) {
- mAdvertiseCallback.onAdvertiseStart(status);
- } else {
- // If status is unsuccessful and advertise state is started, it means stop
- // advertising fails.
- mAdvertiseCallback.onAdvertiseStop(status);
- }
- } else {
- synchronized (this) {
- if (status == ADVERTISE_CALLBACK_SUCCESS) {
- BluetoothAdapter adapter = mBluetoothAdapter.get();
- if (adapter != null) {
- try {
- IBluetoothGatt iGatt =
- adapter.getBluetoothManager().getBluetoothGatt();
- Log.d(TAG, "unregistering client " + mLeHandle);
- iGatt.unregisterClient(mLeHandle);
- // Reset advertise app handle.
- mLeHandle = -1;
- adapter.mAdvertisingGattCallback = null;
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to unregister client" + e);
- }
- } else {
- Log.e(TAG, "cannot unregister client, BluetoothAdapter is null");
- }
- }
- }
- if (status == ADVERTISE_CALLBACK_SUCCESS) {
- mAdvertiseCallback.onAdvertiseStop(status);
- } else{
- // If status is unsuccesful and advertise state is stopped, it means start
- // advertising fails.
- mAdvertiseCallback.onAdvertiseStart(status);
- }
- }
}
@Override
diff --git a/core/java/android/bluetooth/BluetoothAdvScanData.java b/core/java/android/bluetooth/BluetoothAdvScanData.java
deleted file mode 100644
index df2c256..0000000
--- a/core/java/android/bluetooth/BluetoothAdvScanData.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2013 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.os.ParcelUuid;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.Collections;
-import java.util.List;
-
-
-/**
- * This class provides the public APIs to set advertising and scan response data when BLE device
- * operates in peripheral mode. <br>
- * The exact format is defined in Bluetooth 4.0 specification, Volume 3, Part C, Section 11
- * @hide
- */
-public final class BluetoothAdvScanData {
-
- /**
- * Available data types of {@link BluetoothAdvScanData}.
- */
- public static final int AD = 0; // Advertising Data
- public static final int SCAN_RESPONSE = 1; // Scan Response
- public static final int EIR = 2; // Extended Inquiry Response
-
- private static final String TAG = "BluetoothAdvScanData";
-
- /**
- * Data type of BluetoothAdvScanData.
- */
- private final int mDataType;
- /**
- * Bluetooth Gatt Service.
- */
- private IBluetoothGatt mBluetoothGatt;
-
- /**
- * @param mBluetoothGatt
- * @param dataType
- */
- public BluetoothAdvScanData(IBluetoothGatt mBluetoothGatt, int dataType) {
- this.mBluetoothGatt = mBluetoothGatt;
- this.mDataType = dataType;
- }
-
- /**
- * @return advertising data type.
- */
- public int getDataType() {
- return mDataType;
- }
-
- /**
- * Set manufactureCode and manufactureData.
- * Returns true if manufacturer data is set, false if there is no enough room to set
- * manufacturer data or the data is already set.
- * @param manufacturerCode - unique identifier for the manufacturer
- * @param manufacturerData - data associated with the specific manufacturer.
- */
- public boolean setManufacturerData(int manufacturerCode, byte[] manufacturerData) {
- if (mDataType != AD) return false;
- try {
- return mBluetoothGatt.setAdvManufacturerCodeAndData(manufacturerCode, manufacturerData);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to set manufacturer id and data.", e);
- return false;
- }
- }
-
- /**
- * Set service data. Note the service data can only be set when the data type is {@code AD};
- * @param serviceData
- */
- public boolean setServiceData(byte[] serviceData) {
-
- if (mDataType != AD) return false;
- if (serviceData == null) return false;
- try {
- return mBluetoothGatt.setAdvServiceData(serviceData);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to set service data.", e);
- return false;
- }
- }
-
- /**
- * Returns an immutable list of service uuids that will be advertised.
- */
- public List<ParcelUuid> getServiceUuids() {
- try {
- return Collections.unmodifiableList(mBluetoothGatt.getAdvServiceUuids());
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to get service uuids.", e);
- return null;
- }
- }
-
- /**
- * Returns manufacturer data.
- */
- public byte[] getManufacturerData() {
- if (mBluetoothGatt == null) return null;
- try {
- return mBluetoothGatt.getAdvManufacturerData();
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to get manufacturer data.", e);
- return null;
- }
- }
-
- /**
- * Returns service data.
- */
- public byte[] getServiceData() {
- if (mBluetoothGatt == null) return null;
- try {
- return mBluetoothGatt.getAdvServiceData();
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to get service data.", e);
- return null;
- }
- }
-
- /**
- * Remove manufacturer data based on given manufacturer code.
- * @param manufacturerCode
- */
- public void removeManufacturerCodeAndData(int manufacturerCode) {
- if (mBluetoothGatt != null) {
- try {
- mBluetoothGatt.removeAdvManufacturerCodeAndData(manufacturerCode);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to remove manufacturer : " + manufacturerCode, e);
- }
- }
- }
-}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 0f0eee6..6d4b9cd 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -48,15 +48,6 @@
void unregisterClient(in int clientIf);
void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport);
void clientDisconnect(in int clientIf, in String address);
- void startAdvertising(in int appIf);
- void stopAdvertising();
- boolean setAdvServiceData(in byte[] serviceData);
- byte[] getAdvServiceData();
- boolean setAdvManufacturerCodeAndData(int manufactureCode, in byte[] manufacturerData);
- byte[] getAdvManufacturerData();
- List<ParcelUuid> getAdvServiceUuids();
- void removeAdvManufacturerCodeAndData(int manufacturerCode);
- boolean isAdvertising();
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
void readCharacteristic(in int clientIf, in String address, in int srvcType,
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index af218eb..18e3f54 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -64,7 +64,6 @@
in int charInstId, in ParcelUuid charUuid,
in byte[] value);
void onReadRemoteRssi(in String address, in int rssi, in int status);
- void onAdvertiseStateChange(in int advertiseState, in int status);
void onMultiAdvertiseCallback(in int status);
void onConfigureMTU(in String address, in int mtu, in int status);
void onConnectionCongested(in String address, in boolean congested);
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index e232512..af79fcc 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -332,11 +332,6 @@
}
@Override
- public void onAdvertiseStateChange(int advertiseState, int status) {
- // no op
- }
-
- @Override
public void onMultiAdvertiseCallback(int status) {
// TODO: This logic needs to be re-visited to account
// for whether the scan has actually been started
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 7e87edc..220aa77 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -409,11 +409,6 @@
}
@Override
- public void onAdvertiseStateChange(int advertiseState, int status) {
- // no op
- }
-
- @Override
public void onMultiAdvertiseCallback(int status) {
// no op
}
diff --git a/core/java/android/content/AbstractRestrictionsProvider.java b/core/java/android/content/AbstractRestrictionsProvider.java
index 1119478..3272970 100644
--- a/core/java/android/content/AbstractRestrictionsProvider.java
+++ b/core/java/android/content/AbstractRestrictionsProvider.java
@@ -16,78 +16,65 @@
package android.content;
-import android.app.Service;
import android.app.admin.DevicePolicyManager;
import android.os.Bundle;
import android.os.IBinder;
/**
- * Abstract implementation of a Restrictions Provider Service. To implement a Restrictions Provider,
- * extend from this class and implement the abstract methods. Export this service in the
- * manifest. A profile owner device admin can then register this component as a Restrictions
- * Provider using {@link DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)}.
+ * Abstract implementation of a Restrictions Provider BroadcastReceiver. To implement a
+ * Restrictions Provider, extend from this class and implement the abstract methods.
+ * Export this receiver in the manifest. A profile owner device admin can then register this
+ * component as a Restrictions Provider using
+ * {@link DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)}.
* <p>
* The function of a Restrictions Provider is to transport permission requests from apps on this
* device to an administrator (most likely on a remote device or computer) and deliver back
* responses. The response should be sent back to the app via
* {@link RestrictionsManager#notifyPermissionResponse(String, Bundle)}.
- * <p>
- * Apps can also query previously received responses using
- * {@link #getPermissionResponse(String, String)}. The period for which previously received
- * responses are available is left to the implementation of the Restrictions Provider.
+ *
+ * @see RestrictionsManager
*/
-public abstract class AbstractRestrictionsProvider extends Service {
+public abstract class AbstractRestrictionsProvider extends BroadcastReceiver {
private static final String TAG = "AbstractRestrictionsProvider";
- @Override
- public final IBinder onBind(Intent intent) {
- return new RestrictionsProviderWrapper().asBinder();
- }
-
- /**
- * Checks to see if there is a response for a prior request and returns the response bundle if
- * it exists. If there is no response yet or if the request is not known, the returned bundle
- * should contain the response code in {@link RestrictionsManager#RESPONSE_KEY_RESULT}.
- *
- * @param packageName the application that is requesting a permission response.
- * @param requestId the id of the request for which the response is needed.
- * @return a bundle containing at a minimum the result of the request. It could contain other
- * optional information such as error codes and cookies.
- *
- * @see RestrictionsManager#RESPONSE_KEY_RESULT
- */
- public abstract Bundle getPermissionResponse(String packageName, String requestId);
-
/**
* An asynchronous permission request made by an application for an operation that requires
* authorization by a local or remote administrator other than the user. The Restrictions
- * Provider must transfer the request to the administrator and deliver back a response, when
+ * Provider should transfer the request to the administrator and deliver back a response, when
* available. The calling application is aware that the response could take an indefinite
* amount of time.
+ * <p>
+ * If the request bundle contains the key {@link RestrictionsManager#REQUEST_KEY_NEW_REQUEST},
+ * then a new request must be sent. Otherwise the provider can look up any previous response
+ * to the same requestId and return the cached response.
*
* @param packageName the application requesting permission.
* @param requestType the type of request, which determines the content and presentation of
* the request data.
* @param request the request data bundle containing at a minimum a request id.
*
- * @see RestrictionsManager#REQUEST_TYPE_QUESTION
+ * @see RestrictionsManager#REQUEST_TYPE_APPROVAL
* @see RestrictionsManager#REQUEST_TYPE_LOCAL_APPROVAL
* @see RestrictionsManager#REQUEST_KEY_ID
*/
- public abstract void requestPermission(String packageName, String requestType, Bundle request);
+ public abstract void requestPermission(Context context,
+ String packageName, String requestType, Bundle request);
- private class RestrictionsProviderWrapper extends IRestrictionsProvider.Stub {
+ /**
+ * Intercept standard Restrictions Provider broadcasts. Implementations
+ * should not override this method; it is better to implement the
+ * convenience callbacks for each action.
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
- @Override
- public Bundle getPermissionResponse(String packageName, String requestId) {
- return AbstractRestrictionsProvider.this
- .getPermissionResponse(packageName, requestId);
- }
-
- @Override
- public void requestPermission(String packageName, String templateId, Bundle request) {
- AbstractRestrictionsProvider.this.requestPermission(packageName, templateId, request);
+ if (RestrictionsManager.ACTION_REQUEST_PERMISSION.equals(action)) {
+ String packageName = intent.getStringExtra(RestrictionsManager.EXTRA_PACKAGE_NAME);
+ String requestType = intent.getStringExtra(RestrictionsManager.EXTRA_REQUEST_TYPE);
+ Bundle request = intent.getBundleExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE);
+ requestPermission(context, packageName, requestType, request);
}
}
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 535aaa1..1dd018f 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -647,6 +647,26 @@
public abstract File getFilesDir();
/**
+ * Returns the absolute path to the directory on the filesystem similar to
+ * {@link #getFilesDir()}. The difference is that files placed under this
+ * directory will be excluded from automatic backup to remote storage. See
+ * {@link android.app.backup.BackupAgent BackupAgent} for a full discussion
+ * of the automatic backup mechanism in Android.
+ *
+ * <p>No permissions are required to read or write to the returned path, since this
+ * path is internal storage.
+ *
+ * @return The path of the directory holding application files that will not be
+ * automatically backed up to remote storage.
+ *
+ * @see #openFileOutput
+ * @see #getFileStreamPath
+ * @see #getDir
+ * @see android.app.backup.BackupAgent
+ */
+ public abstract File getNoBackupFilesDir();
+
+ /**
* Returns the absolute path to the directory on the primary external filesystem
* (that is somewhere on {@link android.os.Environment#getExternalStorageDirectory()
* Environment.getExternalStorageDirectory()}) where the application can
@@ -847,6 +867,22 @@
public abstract File getCacheDir();
/**
+ * Returns the absolute path to the application specific cache directory on
+ * the filesystem designed for storing cached code. The system will delete
+ * any files stored in this location both when your specific application is
+ * upgraded, and when the entire platform is upgraded.
+ * <p>
+ * This location is optimal for storing compiled or optimized code generated
+ * by your application at runtime.
+ * <p>
+ * Apps require no extra permissions to read or write to the returned path,
+ * since this path lives in their private storage.
+ *
+ * @return The path of the directory holding application code cache files.
+ */
+ public abstract File getCodeCacheDir();
+
+ /**
* Returns the absolute path to the directory on the primary external filesystem
* (that is somewhere on {@link android.os.Environment#getExternalStorageDirectory()
* Environment.getExternalStorageDirectory()} where the application can
@@ -2031,6 +2067,7 @@
WIFI_P2P_SERVICE,
WIFI_SCANNING_SERVICE,
//@hide: ETHERNET_SERVICE,
+ WIFI_RTT_SERVICE,
NSD_SERVICE,
AUDIO_SERVICE,
MEDIA_ROUTER_SERVICE,
@@ -2427,11 +2464,22 @@
/**
* Use with {@link #getSystemService} to retrieve a {@link
- * android.net.ethernet.EthernetManager} for handling management of
+ * android.net.wifi.RttManager} for ranging devices with wifi
+ *
+ * @see #getSystemService
+ * @see android.net.wifi.RttManager
+ * @hide
+ */
+ @SystemApi
+ public static final String WIFI_RTT_SERVICE = "rttmanager";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a {@link
+ * android.net.EthernetManager} for handling management of
* Ethernet access.
*
* @see #getSystemService
- * @see android.net.ethernet.EthernetManager
+ * @see android.net.EthernetManager
*
* @hide
*/
@@ -2503,7 +2551,6 @@
*
* @see #getSystemService
* @see android.telecomm.TelecommManager
- * @hide
*/
public static final String TELECOMM_SERVICE = "telecomm";
@@ -3204,6 +3251,12 @@
public static final int CONTEXT_RESTRICTED = 0x00000004;
/**
+ * @hide Used to indicate we should tell the activity manager about the process
+ * loading this code.
+ */
+ public static final int CONTEXT_REGISTER_PACKAGE = 0x40000000;
+
+ /**
* Return a new Context object for the given application name. This
* Context is the same as what the named application gets when it is
* launched, containing the same resources and class loader. Each call to
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index dbf9122..4e1c4a7 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -200,7 +200,12 @@
public File getFilesDir() {
return mBase.getFilesDir();
}
-
+
+ @Override
+ public File getNoBackupFilesDir() {
+ return mBase.getNoBackupFilesDir();
+ }
+
@Override
public File getExternalFilesDir(String type) {
return mBase.getExternalFilesDir(type);
@@ -227,6 +232,11 @@
}
@Override
+ public File getCodeCacheDir() {
+ return mBase.getCodeCacheDir();
+ }
+
+ @Override
public File getExternalCacheDir() {
return mBase.getExternalCacheDir();
}
diff --git a/core/java/android/content/IPermissionResponseCallback.aidl b/core/java/android/content/IPermissionResponseCallback.aidl
deleted file mode 100644
index 8309768..0000000
--- a/core/java/android/content/IPermissionResponseCallback.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-** Copyright 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.
-*/
-
-package android.content;
-
-import android.os.Bundle;
-
-/**
- * Callback for permission response queries.
- *
- * @hide
- */
- interface IPermissionResponseCallback {
-
- void onResponse(in Bundle response);
-
-}
diff --git a/core/java/android/content/IRestrictionsManager.aidl b/core/java/android/content/IRestrictionsManager.aidl
index 49eb65b..b1c0a3a 100644
--- a/core/java/android/content/IRestrictionsManager.aidl
+++ b/core/java/android/content/IRestrictionsManager.aidl
@@ -17,7 +17,6 @@
package android.content;
import android.os.Bundle;
-import android.content.IPermissionResponseCallback;
/**
* Interface used by the RestrictionsManager
@@ -28,6 +27,4 @@
boolean hasRestrictionsProvider();
void requestPermission(in String packageName, in String requestTemplate, in Bundle requestData);
void notifyPermissionResponse(in String packageName, in Bundle response);
- void getPermissionResponse(in String packageName, in String requestId,
- in IPermissionResponseCallback callback);
}
diff --git a/core/java/android/content/IRestrictionsProvider.aidl b/core/java/android/content/IRestrictionsProvider.aidl
deleted file mode 100644
index 4506b72..0000000
--- a/core/java/android/content/IRestrictionsProvider.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-** Copyright 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.
-*/
-
-package android.content;
-
-import android.os.Bundle;
-
-/**
- * Interface to a restrictions provider service component.
- *
- * @hide
- */
- interface IRestrictionsProvider {
-
- void requestPermission(in String packageName, in String requestType, in Bundle requestBundle);
- Bundle getPermissionResponse(in String packageName, in String requestId);
-
-}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 4153a02..5bf8a97 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3809,17 +3809,6 @@
* {@link android.R.styleable#AndroidManifestActivity_autoRemoveFromRecents}.
*/
public static final int FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS = 0x00002000;
- /**
- * If set along with FLAG_ACTIVITY_NEW_DOCUMENT then the task being launched will not be
- * presented to the user but will instead be only available through the recents task list.
- * In addition, the new task wil be affiliated with the launching activity's task.
- * Affiliated tasks are grouped together in the recents task list.
- *
- * <p>This behavior is not supported for activities with {@link
- * android.R.styleable#AndroidManifestActivity_launchMode launchMode} values of
- * <code>singleInstance</code> or <code>singleTask</code>.
- */
- public static final int FLAG_ACTIVITY_LAUNCH_BEHIND = 0x00001000;
/**
* If set, when sending a broadcast only registered receivers will be
diff --git a/core/java/android/content/RestrictionEntry.java b/core/java/android/content/RestrictionEntry.java
index 62f88a9..5341ea8 100644
--- a/core/java/android/content/RestrictionEntry.java
+++ b/core/java/android/content/RestrictionEntry.java
@@ -79,6 +79,13 @@
*/
public static final int TYPE_INTEGER = 5;
+ /**
+ * A type of restriction. Use this for storing a string value.
+ * @see #setSelectedString
+ * @see #getSelectedString
+ */
+ public static final int TYPE_STRING = 6;
+
/** The type of restriction. */
private int mType;
@@ -107,6 +114,17 @@
private String[] mCurrentValues;
/**
+ * Constructor for specifying the type and key, with no initial value;
+ *
+ * @param type the restriction type.
+ * @param key the unique key for this restriction
+ */
+ public RestrictionEntry(int type, String key) {
+ mType = type;
+ mKey = key;
+ }
+
+ /**
* Constructor for {@link #TYPE_CHOICE} type.
* @param key the unique key for this restriction
* @param selectedString the current value
diff --git a/core/java/android/content/RestrictionsManager.java b/core/java/android/content/RestrictionsManager.java
index 5ef2dbc..5ae10cfc 100644
--- a/core/java/android/content/RestrictionsManager.java
+++ b/core/java/android/content/RestrictionsManager.java
@@ -17,11 +17,24 @@
package android.content;
import android.app.admin.DevicePolicyManager;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.os.RemoteException;
+import android.util.AttributeSet;
import android.util.Log;
+import android.util.Xml;
-import java.util.Collections;
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -32,50 +45,77 @@
* <p>
* Apps can expose a set of restrictions via an XML file specified in the manifest.
* <p>
- * If the user has an active restrictions provider, dynamic requests can be made in
+ * If the user has an active Restrictions Provider, dynamic requests can be made in
* addition to the statically imposed restrictions. Dynamic requests are app-specific
* and can be expressed via a predefined set of request types.
* <p>
* The RestrictionsManager forwards the dynamic requests to the active
- * restrictions provider. The restrictions provider can respond back to requests by calling
+ * Restrictions Provider. The Restrictions Provider can respond back to requests by calling
* {@link #notifyPermissionResponse(String, Bundle)}, when
* a response is received from the administrator of the device or user.
* The response is relayed back to the application via a protected broadcast,
* {@link #ACTION_PERMISSION_RESPONSE_RECEIVED}.
* <p>
- * Prior responses to requests can also be queried through calls to
- * {@link #getPermissionResponse(String, PermissionResponseCallback)}, if the provider
- * saves old responses.
- * <p>
* Static restrictions are specified by an XML file referenced by a meta-data attribute
* in the manifest. This enables applications as well as any web administration consoles
* to be able to read the list of available restrictions from the apk.
* <p>
* The syntax of the XML format is as follows:
* <pre>
- * <restrictions>
+ * <?xml version="1.0" encoding="utf-8"?>
+ * <restrictions xmlns:android="http://schemas.android.com/apk/res/android" >
* <restriction
- * android:key="<key>"
- * android:restrictionType="boolean|string|integer|multi-select|null"
- * ... />
+ * android:key="string"
+ * android:title="string resource"
+ * android:restrictionType=["bool" | "string" | "integer"
+ * | "choice" | "multi-select" | "hidden"]
+ * android:description="string resource"
+ * android:entries="string-array resource"
+ * android:entryValues="string-array resource"
+ * android:defaultValue="reference"
+ * />
* <restriction ... />
+ * ...
* </restrictions>
* </pre>
* <p>
* The attributes for each restriction depend on the restriction type.
+ * <p>
+ * <ul>
+ * <li><code>key</code>, <code>title</code> and <code>restrictionType</code> are mandatory.</li>
+ * <li><code>entries</code> and <code>entryValues</code> are required if <code>restrictionType
+ * </code> is <code>choice</code> or <code>multi-select</code>.</li>
+ * <li><code>defaultValue</code> is optional and its type depends on the
+ * <code>restrictionType</code></li>
+ * <li><code>hidden</code> type must have a <code>defaultValue</code> and will
+ * not be shown to the administrator. It can be used to pass along data that cannot be modified,
+ * such as a version code.</li>
+ * <li><code>description</code> is meant to describe the restriction in more detail to the
+ * administrator controlling the values, if the title is not sufficient.</li>
+ * </ul>
+ * <p>
+ * In your manifest's <code>application</code> section, add the meta-data tag to point to
+ * the restrictions XML file as shown below:
+ * <pre>
+ * <application ... >
+ * <meta-data android:name="android.content.APP_RESTRICTIONS"
+ * android:resource="@xml/app_restrictions" />
+ * ...
+ * </application>
+ * </pre>
*
* @see RestrictionEntry
* @see AbstractRestrictionsProvider
+ * @see DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)
+ * @see DevicePolicyManager#setApplicationRestrictions(ComponentName, String, Bundle)
*/
public class RestrictionsManager {
private static final String TAG = "RestrictionsManager";
/**
- * Broadcast intent delivered when a response is received for a permission
- * request. The response is not available for later query, so the receiver
- * must persist and/or immediately act upon the response. The application
- * should not interrupt the user by coming to the foreground if it isn't
+ * Broadcast intent delivered when a response is received for a permission request. The
+ * application should not interrupt the user by coming to the foreground if it isn't
* currently in the foreground. It can either post a notification informing
* the user of the response or wait until the next time the user launches the app.
* <p>
@@ -89,9 +129,32 @@
"android.intent.action.PERMISSION_RESPONSE_RECEIVED";
/**
+ * Broadcast intent sent to the Restrictions Provider to handle a permission request from
+ * an app. It will have the following extras: {@link #EXTRA_PACKAGE_NAME},
+ * {@link #EXTRA_REQUEST_TYPE} and {@link #EXTRA_REQUEST_BUNDLE}. The Restrictions Provider
+ * will handle the request and respond back to the RestrictionsManager, when a response is
+ * available, by calling {@link #notifyPermissionResponse}.
+ * <p>
+ * The BroadcastReceiver must require the {@link android.Manifest.permission#BIND_DEVICE_ADMIN}
+ * permission to ensure that only the system can send the broadcast.
+ */
+ public static final String ACTION_REQUEST_PERMISSION =
+ "android.content.action.REQUEST_PERMISSION";
+
+ /**
* The package name of the application making the request.
*/
- public static final String EXTRA_PACKAGE_NAME = "package_name";
+ public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
+
+ /**
+ * The request type passed in the {@link #ACTION_REQUEST_PERMISSION} broadcast.
+ */
+ public static final String EXTRA_REQUEST_TYPE = "android.content.extra.REQUEST_TYPE";
+
+ /**
+ * The request bundle passed in the {@link #ACTION_REQUEST_PERMISSION} broadcast.
+ */
+ public static final String EXTRA_REQUEST_BUNDLE = "android.content.extra.REQUEST_BUNDLE";
/**
* Contains a response from the administrator for specific request.
@@ -101,7 +164,7 @@
* <li>{@link #RESPONSE_KEY_RESULT}: The response result.</li>
* </ul>
*/
- public static final String EXTRA_RESPONSE_BUNDLE = "response";
+ public static final String EXTRA_RESPONSE_BUNDLE = "android.content.extra.RESPONSE_BUNDLE";
/**
* Request type for a simple question, with a possible title and icon.
@@ -113,7 +176,7 @@
* {@link #REQUEST_KEY_DATA}, {@link #REQUEST_KEY_ICON}, {@link #REQUEST_KEY_TITLE},
* {@link #REQUEST_KEY_APPROVE_LABEL} and {@link #REQUEST_KEY_DENY_LABEL}.
*/
- public static final String REQUEST_TYPE_QUESTION = "android.request.type.question";
+ public static final String REQUEST_TYPE_APPROVAL = "android.request.type.approval";
/**
* Request type for a local password challenge. This is a way for an app to ask
@@ -204,26 +267,19 @@
public static final String REQUEST_KEY_DENY_LABEL = "android.request.deny_label";
/**
- * Key for requestor's name contained in the request bundle. This value is not specified by
- * the application. It is automatically inserted into the Bundle by the Restrictions Provider
- * before it is sent to the administrator.
+ * Key for issuing a new request, contained in the request bundle. If this is set to true,
+ * the Restrictions Provider must make a new request. If it is false or not specified, then
+ * the Restrictions Provider can return a cached response that has the same requestId, if
+ * available. If there's no cached response, it will issue a new one to the administrator.
* <p>
- * Type: String
+ * Type: boolean
*/
- public static final String REQUEST_KEY_REQUESTOR_NAME = "android.request.requestor";
+ public static final String REQUEST_KEY_NEW_REQUEST = "android.request.new_request";
/**
- * Key for requestor's device name contained in the request bundle. This value is not specified
- * by the application. It is automatically inserted into the Bundle by the Restrictions Provider
- * before it is sent to the administrator.
- * <p>
- * Type: String
- */
- public static final String REQUEST_KEY_DEVICE_NAME = "android.request.device";
-
- /**
- * Key for the response in the response bundle sent to the application, for a permission
- * request.
+ * Key for the response result in the response bundle sent to the application, for a permission
+ * request. It indicates the status of the request. In some cases an additional message might
+ * be available in {@link #RESPONSE_KEY_MESSAGE}, to be displayed to the user.
* <p>
* Type: int
* <p>
@@ -249,8 +305,8 @@
public static final int RESULT_NO_RESPONSE = 3;
/**
- * Response result value indicating that the request is unknown, when returned through a
- * call to #getPendingResponse
+ * Response result value indicating that the request is unknown, when it's not a new
+ * request.
*/
public static final int RESULT_UNKNOWN_REQUEST = 4;
@@ -258,7 +314,7 @@
* Response result value indicating an error condition. Additional error code might be available
* in the response bundle, for the key {@link #RESPONSE_KEY_ERROR_CODE}. There might also be
* an associated error message in the response bundle, for the key
- * {@link #RESPONSE_KEY_ERROR_MESSAGE}.
+ * {@link #RESPONSE_KEY_MESSAGE}.
*/
public static final int RESULT_ERROR = 5;
@@ -294,11 +350,11 @@
public static final String RESPONSE_KEY_ERROR_CODE = "android.response.errorcode";
/**
- * Key for the optional error message in the response bundle sent to the application.
+ * Key for the optional message in the response bundle sent to the application.
* <p>
* Type: String
*/
- public static final String RESPONSE_KEY_ERROR_MESSAGE = "android.response.errormsg";
+ public static final String RESPONSE_KEY_MESSAGE = "android.response.msg";
/**
* Key for the optional timestamp of when the administrator responded to the permission
@@ -308,23 +364,19 @@
*/
public static final String RESPONSE_KEY_RESPONSE_TIMESTAMP = "android.response.timestamp";
+ /**
+ * Name of the meta-data entry in the manifest that points to the XML file containing the
+ * application's available restrictions.
+ * @see #getManifestRestrictions(String)
+ */
+ public static final String META_DATA_APP_RESTRICTIONS = "android.content.APP_RESTRICTIONS";
+
+ private static final String TAG_RESTRICTION = "restriction";
+
private final Context mContext;
private final IRestrictionsManager mService;
/**
- * Callback object for returning a response for a request.
- *
- * @see #getPermissionResponse
- */
- public static abstract class PermissionResponseCallback {
- /**
- * Contains the response
- * @param response
- */
- public abstract void onResponse(Bundle response);
- }
-
- /**
* @hide
*/
public RestrictionsManager(Context context, IRestrictionsManager service) {
@@ -350,11 +402,10 @@
}
/**
- * Called by an application to check if there is an active restrictions provider. If
- * there isn't, {@link #getPermissionResponse(String, PermissionResponseCallback)}
- * and {@link #requestPermission(String, Bundle)} are not available.
+ * Called by an application to check if there is an active Restrictions Provider. If
+ * there isn't, {@link #requestPermission(String, Bundle)} is not available.
*
- * @return whether there is an active restrictions provider.
+ * @return whether there is an active Restrictions Provider.
*/
public boolean hasRestrictionsProvider() {
try {
@@ -374,13 +425,24 @@
*
* @param requestType The type of request. The type could be one of the
* predefined types specified here or a custom type that the specific
- * restrictions provider might understand. For custom types, the type name should be
+ * Restrictions Provider might understand. For custom types, the type name should be
* namespaced to avoid collisions with predefined types and types specified by
- * other restrictions providers.
+ * other Restrictions Providers.
* @param request A Bundle containing the data corresponding to the specified request
* type. The keys for the data in the bundle depend on the request type.
+ *
+ * @throws IllegalArgumentException if any of the required parameters are missing.
*/
public void requestPermission(String requestType, Bundle request) {
+ if (requestType == null) {
+ throw new NullPointerException("requestType cannot be null");
+ }
+ if (request == null) {
+ throw new NullPointerException("request cannot be null");
+ }
+ if (!request.containsKey(REQUEST_KEY_ID)) {
+ throw new IllegalArgumentException("REQUEST_KEY_ID must be specified");
+ }
try {
if (mService != null) {
mService.requestPermission(mContext.getPackageName(), requestType, request);
@@ -391,41 +453,27 @@
}
/**
- * Called by an application to query for any available response from the restrictions provider
- * for the given requestId. The call returns immediately and the response will be returned
- * via the provided callback. This does not initiate a new request and does not wait
- * for a response to be received. It merely returns any previously received response
- * or indicates if there was no available response. If there are multiple responses
- * available for the same request ID, the most recent one is returned.
+ * Called by the Restrictions Provider to deliver a response to an application.
*
- * @param requestId The ID of the original request made via
- * {@link #requestPermission(String, Bundle)}. It's possible to also query for responses
- * to requests made on a different device with the same requestId, if the Restrictions
- * Provider happens to sync responses across devices with the same account managed by the
- * restrictions provider.
- * @param callback The response is returned via the callback object. Cannot be null.
- */
- public void getPermissionResponse(String requestId, PermissionResponseCallback callback) {
- if (requestId == null || callback == null) {
- throw new NullPointerException("requestId or callback cannot be null");
- }
- try {
- if (mService != null) {
- mService.getPermissionResponse(mContext.getPackageName(), requestId,
- new PermissionResponseCallbackWrapper(callback));
- }
- } catch (RemoteException re) {
- Log.w(TAG, "Couldn't reach service");
- }
- }
-
- /**
- * Called by the restrictions provider to deliver a response to an application.
- *
- * @param packageName the application to deliver the response to.
+ * @param packageName the application to deliver the response to. Cannot be null.
* @param response the Bundle containing the response status, request ID and other information.
+ * Cannot be null.
+ *
+ * @throws IllegalArgumentException if any of the required parameters are missing.
*/
public void notifyPermissionResponse(String packageName, Bundle response) {
+ if (packageName == null) {
+ throw new NullPointerException("packageName cannot be null");
+ }
+ if (response == null) {
+ throw new NullPointerException("request cannot be null");
+ }
+ if (!response.containsKey(REQUEST_KEY_ID)) {
+ throw new IllegalArgumentException("REQUEST_KEY_ID must be specified");
+ }
+ if (!response.containsKey(RESPONSE_KEY_RESULT)) {
+ throw new IllegalArgumentException("RESPONSE_KEY_RESULT must be specified");
+ }
try {
if (mService != null) {
mService.notifyPermissionResponse(packageName, response);
@@ -444,22 +492,118 @@
* in the manifest, or null if none was specified.
*/
public List<RestrictionEntry> getManifestRestrictions(String packageName) {
- // TODO:
- return null;
+ ApplicationInfo appInfo = null;
+ try {
+ appInfo = mContext.getPackageManager().getApplicationInfo(packageName,
+ PackageManager.GET_META_DATA);
+ } catch (NameNotFoundException pnfe) {
+ throw new IllegalArgumentException("No such package " + packageName);
+ }
+ if (appInfo == null || !appInfo.metaData.containsKey(META_DATA_APP_RESTRICTIONS)) {
+ return null;
+ }
+
+ XmlResourceParser xml =
+ appInfo.loadXmlMetaData(mContext.getPackageManager(), META_DATA_APP_RESTRICTIONS);
+ List<RestrictionEntry> restrictions = loadManifestRestrictions(packageName, xml);
+
+ return restrictions;
}
- private static class PermissionResponseCallbackWrapper
- extends IPermissionResponseCallback.Stub {
+ private List<RestrictionEntry> loadManifestRestrictions(String packageName,
+ XmlResourceParser xml) {
+ Context appContext;
+ try {
+ appContext = mContext.createPackageContext(packageName, 0 /* flags */);
+ } catch (NameNotFoundException nnfe) {
+ return null;
+ }
+ ArrayList<RestrictionEntry> restrictions = new ArrayList<RestrictionEntry>();
+ RestrictionEntry restriction;
- private PermissionResponseCallback mCallback;
-
- PermissionResponseCallbackWrapper(PermissionResponseCallback callback) {
- mCallback = callback;
+ try {
+ int tagType = xml.next();
+ while (tagType != XmlPullParser.END_DOCUMENT) {
+ if (tagType == XmlPullParser.START_TAG) {
+ if (xml.getName().equals(TAG_RESTRICTION)) {
+ AttributeSet attrSet = Xml.asAttributeSet(xml);
+ if (attrSet != null) {
+ TypedArray a = appContext.obtainStyledAttributes(attrSet,
+ com.android.internal.R.styleable.RestrictionEntry);
+ restriction = loadRestriction(appContext, a);
+ if (restriction != null) {
+ restrictions.add(restriction);
+ }
+ }
+ }
+ }
+ tagType = xml.next();
+ }
+ } catch (XmlPullParserException e) {
+ Log.w(TAG, "Reading restriction metadata for " + packageName, e);
+ return null;
+ } catch (IOException e) {
+ Log.w(TAG, "Reading restriction metadata for " + packageName, e);
+ return null;
}
- @Override
- public void onResponse(Bundle response) {
- mCallback.onResponse(response);
+ return restrictions;
+ }
+
+ private RestrictionEntry loadRestriction(Context appContext, TypedArray a) {
+ String key = a.getString(R.styleable.RestrictionEntry_key);
+ int restrictionType = a.getInt(
+ R.styleable.RestrictionEntry_restrictionType, -1);
+ String title = a.getString(R.styleable.RestrictionEntry_title);
+ String description = a.getString(R.styleable.RestrictionEntry_description);
+ int entries = a.getResourceId(R.styleable.RestrictionEntry_entries, 0);
+ int entryValues = a.getResourceId(R.styleable.RestrictionEntry_entryValues, 0);
+
+ if (restrictionType == -1) {
+ Log.w(TAG, "restrictionType cannot be omitted");
+ return null;
}
+
+ if (key == null) {
+ Log.w(TAG, "key cannot be omitted");
+ return null;
+ }
+
+ RestrictionEntry restriction = new RestrictionEntry(restrictionType, key);
+ restriction.setTitle(title);
+ restriction.setDescription(description);
+ if (entries != 0) {
+ restriction.setChoiceEntries(appContext, entries);
+ }
+ if (entryValues != 0) {
+ restriction.setChoiceValues(appContext, entryValues);
+ }
+ // Extract the default value based on the type
+ switch (restrictionType) {
+ case RestrictionEntry.TYPE_NULL: // hidden
+ case RestrictionEntry.TYPE_STRING:
+ case RestrictionEntry.TYPE_CHOICE:
+ restriction.setSelectedString(
+ a.getString(R.styleable.RestrictionEntry_defaultValue));
+ break;
+ case RestrictionEntry.TYPE_INTEGER:
+ restriction.setIntValue(
+ a.getInt(R.styleable.RestrictionEntry_defaultValue, 0));
+ break;
+ case RestrictionEntry.TYPE_MULTI_SELECT:
+ int resId = a.getResourceId(R.styleable.RestrictionEntry_defaultValue, 0);
+ if (resId != 0) {
+ restriction.setAllSelectedStrings(
+ appContext.getResources().getStringArray(resId));
+ }
+ break;
+ case RestrictionEntry.TYPE_BOOLEAN:
+ restriction.setSelectedState(
+ a.getBoolean(R.styleable.RestrictionEntry_defaultValue, false));
+ break;
+ default:
+ Log.w(TAG, "Unknown restriction type " + restrictionType);
+ }
+ return restriction;
}
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index b93bbe0..95bd480 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -491,6 +491,23 @@
public String nativeLibraryDir;
/**
+ * Full path where unpacked native libraries for {@link #secondaryCpuAbi}
+ * are stored, if present.
+ *
+ * The main reason this exists is for bundled multi-arch apps, where
+ * it's not trivial to calculate the location of libs for the secondary abi
+ * given the location of the primary.
+ *
+ * TODO: Change the layout of bundled installs so that we can use
+ * nativeLibraryRootDir & nativeLibraryRootRequiresIsa there as well.
+ * (e.g {@code [ "/system/app-lib/Foo/arm", "/system/app-lib/Foo/arm64" ]}
+ * instead of {@code [ "/system/lib/Foo", "/system/lib64/Foo" ]}.
+ *
+ * @hide
+ */
+ public String secondaryNativeLibraryDir;
+
+ /**
* The root path where unpacked native libraries are stored.
* <p>
* When {@link #nativeLibraryRootRequiresIsa} is set, the libraries are
@@ -530,23 +547,6 @@
public String secondaryCpuAbi;
/**
- * The derived APK "root" for the given package. Will be non-null for bundled and
- * updated system apps. This will be a top level path under which apks and libraries
- * are installed, for eg. {@code /system}, {@code /oem} or {@code /vendor}. This is
- * used to calculate the location of native code for a given package, for e.g
- * {@code /vendor/lib} or {@code /vendor/lib64}.
- *
- * For app updates or fresh app installs, this will be {@code null} and we will use
- * {@code legacyNativeLibraryDir}
- *
- * NOTE: This can be removed if we have a unified layout for bundled and installed
- * apps.
- *
- * {@hide}
- */
- public String apkRoot;
-
- /**
* The kernel user-ID that has been assigned to this application;
* currently this is not a unique ID (multiple applications can have
* the same uid).
@@ -688,11 +688,11 @@
splitSourceDirs = orig.splitSourceDirs;
splitPublicSourceDirs = orig.splitPublicSourceDirs;
nativeLibraryDir = orig.nativeLibraryDir;
+ secondaryNativeLibraryDir = orig.secondaryNativeLibraryDir;
nativeLibraryRootDir = orig.nativeLibraryRootDir;
nativeLibraryRootRequiresIsa = orig.nativeLibraryRootRequiresIsa;
primaryCpuAbi = orig.primaryCpuAbi;
secondaryCpuAbi = orig.secondaryCpuAbi;
- apkRoot = orig.apkRoot;
resourceDirs = orig.resourceDirs;
seinfo = orig.seinfo;
sharedLibraryFiles = orig.sharedLibraryFiles;
@@ -736,11 +736,11 @@
dest.writeStringArray(splitSourceDirs);
dest.writeStringArray(splitPublicSourceDirs);
dest.writeString(nativeLibraryDir);
+ dest.writeString(secondaryNativeLibraryDir);
dest.writeString(nativeLibraryRootDir);
dest.writeInt(nativeLibraryRootRequiresIsa ? 1 : 0);
dest.writeString(primaryCpuAbi);
dest.writeString(secondaryCpuAbi);
- dest.writeString(apkRoot);
dest.writeStringArray(resourceDirs);
dest.writeString(seinfo);
dest.writeStringArray(sharedLibraryFiles);
@@ -783,11 +783,11 @@
splitSourceDirs = source.readStringArray();
splitPublicSourceDirs = source.readStringArray();
nativeLibraryDir = source.readString();
+ secondaryNativeLibraryDir = source.readString();
nativeLibraryRootDir = source.readString();
nativeLibraryRootRequiresIsa = source.readInt() != 0;
primaryCpuAbi = source.readString();
secondaryCpuAbi = source.readString();
- apkRoot = source.readString();
resourceDirs = source.readStringArray();
seinfo = source.readString();
sharedLibraryFiles = source.readStringArray();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 58d3526..eb46cf0 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -384,10 +384,16 @@
/**
* Ask the package manager to perform dex-opt (if needed) on the given
- * package, if it already hasn't done mode. Only does this if running
- * in the special development "no pre-dexopt" mode.
+ * package and for the given instruction set if it already hasn't done
+ * so.
+ *
+ * If the supplied instructionSet is null, the package manager will use
+ * the packages default instruction set.
+ *
+ * In most cases, apps are dexopted in advance and this function will
+ * be a no-op.
*/
- boolean performDexOpt(String packageName);
+ boolean performDexOptIfNeeded(String packageName, String instructionSet);
/**
* Update status of external media on the package manager to scan and
@@ -429,4 +435,9 @@
boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId);
boolean getBlockUninstallForUser(String packageName, int userId);
+
+ IBinder getKeySetByAlias(String packageName, String alias);
+ IBinder getSigningKeySet(String packageName);
+ boolean isPackageSignedByKeySet(String packageName, IBinder ks);
+ boolean isPackageSignedByKeySetExactly(String packageName, IBinder ks);
}
diff --git a/core/java/android/content/pm/InstallSessionInfo.java b/core/java/android/content/pm/InstallSessionInfo.java
index 45606d1..3336727 100644
--- a/core/java/android/content/pm/InstallSessionInfo.java
+++ b/core/java/android/content/pm/InstallSessionInfo.java
@@ -20,15 +20,25 @@
import android.os.Parcel;
import android.os.Parcelable;
-/** {@hide} */
+/**
+ * Details for an active install session.
+ */
public class InstallSessionInfo implements Parcelable {
+
+ /** {@hide} */
public int sessionId;
+ /** {@hide} */
public String installerPackageName;
+ /** {@hide} */
public int progress;
- public boolean fullInstall;
+ /** {@hide} */
+ public int mode;
+ /** {@hide} */
public String packageName;
+ /** {@hide} */
public Bitmap icon;
+ /** {@hide} */
public CharSequence title;
/** {@hide} */
@@ -41,12 +51,62 @@
installerPackageName = source.readString();
progress = source.readInt();
- fullInstall = source.readInt() != 0;
+ mode = source.readInt();
packageName = source.readString();
icon = source.readParcelable(null);
title = source.readString();
}
+ /**
+ * Return the ID for this session.
+ */
+ public int getSessionId() {
+ return sessionId;
+ }
+
+ /**
+ * Return the package name of the app that owns this session.
+ */
+ public String getInstallerPackageName() {
+ return installerPackageName;
+ }
+
+ /**
+ * Return current overall progress of this session, between 0 and 100.
+ * <p>
+ * Note that this progress may not directly correspond to the value reported
+ * by {@link PackageInstaller.Session#setProgress(int)}, as the system may
+ * carve out a portion of the overall progress to represent its own internal
+ * installation work.
+ */
+ public int getProgress() {
+ return progress;
+ }
+
+ /**
+ * Return the package name this session is working with. May be {@code null}
+ * if unknown.
+ */
+ public String getPackageName() {
+ return packageName;
+ }
+
+ /**
+ * Return an icon representing the app being installed. May be {@code null}
+ * if unavailable.
+ */
+ public Bitmap getIcon() {
+ return icon;
+ }
+
+ /**
+ * Return a title representing the app being installed. May be {@code null}
+ * if unavailable.
+ */
+ public CharSequence getTitle() {
+ return title;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -58,7 +118,7 @@
dest.writeString(installerPackageName);
dest.writeInt(progress);
- dest.writeInt(fullInstall ? 1 : 0);
+ dest.writeInt(mode);
dest.writeString(packageName);
dest.writeParcelable(icon, flags);
dest.writeString(title != null ? title.toString() : null);
diff --git a/core/java/android/content/pm/InstallSessionParams.java b/core/java/android/content/pm/InstallSessionParams.java
index 43e3314..e039699 100644
--- a/core/java/android/content/pm/InstallSessionParams.java
+++ b/core/java/android/content/pm/InstallSessionParams.java
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Parcel;
@@ -23,13 +24,22 @@
import com.android.internal.util.IndentingPrintWriter;
-/** {@hide} */
+/**
+ * Parameters for creating a new {@link PackageInstaller.Session}.
+ */
public class InstallSessionParams implements Parcelable {
// TODO: extend to support remaining VerificationParams
/** {@hide} */
- public boolean fullInstall;
+ public static final int MODE_INVALID = 0;
+ /** {@hide} */
+ public static final int MODE_FULL_INSTALL = 1;
+ /** {@hide} */
+ public static final int MODE_INHERIT_EXISTING = 2;
+
+ /** {@hide} */
+ public int mode = MODE_INVALID;
/** {@hide} */
public int installFlags;
/** {@hide} */
@@ -58,7 +68,7 @@
/** {@hide} */
public InstallSessionParams(Parcel source) {
- fullInstall = source.readInt() != 0;
+ mode = source.readInt();
installFlags = source.readInt();
installLocation = source.readInt();
signatures = (Signature[]) source.readParcelableArray(null);
@@ -72,53 +82,108 @@
abiOverride = source.readString();
}
- public void setFullInstall(boolean fullInstall) {
- this.fullInstall = fullInstall;
+ /**
+ * Set session mode indicating that it should fully replace any existing
+ * APKs for this application.
+ */
+ public void setModeFullInstall() {
+ this.mode = MODE_FULL_INSTALL;
}
- public void setInstallFlags(int installFlags) {
- this.installFlags = installFlags;
+ /**
+ * Set session mode indicating that it should inherit any existing APKs for
+ * this application, unless they are explicitly overridden (by split name)
+ * in the session.
+ */
+ public void setModeInheritExisting() {
+ this.mode = MODE_INHERIT_EXISTING;
}
+ /**
+ * Provide value of {@link PackageInfo#installLocation}, which may be used
+ * to determine where the app will be staged. Defaults to
+ * {@link PackageInfo#INSTALL_LOCATION_INTERNAL_ONLY}.
+ */
public void setInstallLocation(int installLocation) {
this.installLocation = installLocation;
}
+ /**
+ * Optionally provide the required value of {@link PackageInfo#signatures}.
+ * This can be used to assert that all staged APKs have been signed with
+ * this set of specific certificates. Regardless of this value, all APKs in
+ * the application must have the same signing certificates.
+ */
public void setSignatures(Signature[] signatures) {
this.signatures = signatures;
}
+ /**
+ * Indicate the expected growth in disk usage resulting from this session.
+ * This may be used to ensure enough disk space exists before proceeding, or
+ * to estimate container size for installations living on external storage.
+ * <p>
+ * This value should only reflect APK sizes.
+ */
public void setDeltaSize(long deltaSize) {
this.deltaSize = deltaSize;
}
+ /**
+ * Set the maximum progress for this session, used for normalization
+ * purposes.
+ *
+ * @see PackageInstaller.Session#setProgress(int)
+ */
public void setProgressMax(int progressMax) {
this.progressMax = progressMax;
}
+ /**
+ * Optionally set the package name this session will be working with. It's
+ * strongly recommended that you provide this value when known.
+ */
public void setPackageName(String packageName) {
this.packageName = packageName;
}
+ /**
+ * Optionally set an icon representing the app being installed.
+ */
public void setIcon(Bitmap icon) {
this.icon = icon;
}
+ /**
+ * Optionally set a title representing the app being installed.
+ */
public void setTitle(CharSequence title) {
this.title = title;
}
+ /**
+ * Optionally set the URI where this package was downloaded from. Used for
+ * verification purposes.
+ *
+ * @see Intent#EXTRA_ORIGINATING_URI
+ */
public void setOriginatingUri(Uri originatingUri) {
this.originatingUri = originatingUri;
}
+ /**
+ * Optionally set the URI that referred you to install this package. Used
+ * for verification purposes.
+ *
+ * @see Intent#EXTRA_REFERRER
+ */
public void setReferrerUri(Uri referrerUri) {
this.referrerUri = referrerUri;
}
/** {@hide} */
public void dump(IndentingPrintWriter pw) {
- pw.printPair("fullInstall", fullInstall);
+ pw.printPair("mode", mode);
pw.printHexPair("installFlags", installFlags);
pw.printPair("installLocation", installLocation);
pw.printPair("signatures", (signatures != null));
@@ -140,7 +205,7 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(fullInstall ? 1 : 0);
+ dest.writeInt(mode);
dest.writeInt(installFlags);
dest.writeInt(installLocation);
dest.writeParcelableArray(signatures, flags);
diff --git a/core/java/android/content/pm/KeySet.java b/core/java/android/content/pm/KeySet.java
index 0ef09a4..fcdaa18 100644
--- a/core/java/android/content/pm/KeySet.java
+++ b/core/java/android/content/pm/KeySet.java
@@ -16,19 +16,36 @@
package android.content.pm;
-import android.os.Binder;
+import android.os.IBinder;
-/** @hide */
+/**
+ * Represents a {@code KeySet} that has been declared in the AndroidManifest.xml
+ * file for the application. A {@code KeySet} can be used explicitly to
+ * represent a trust relationship with other applications on the device.
+ */
public class KeySet {
- private Binder token;
+ private IBinder token;
/** @hide */
- public KeySet(Binder token) {
+ public KeySet(IBinder token) {
+ if (token == null) {
+ throw new NullPointerException("null value for KeySet IBinder token");
+ }
this.token = token;
}
- Binder getToken() {
+ /** @hide */
+ public IBinder getToken() {
return token;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof KeySet) {
+ KeySet ks = (KeySet) o;
+ return token == ks.token;
+ }
+ return false;
+ }
}
\ No newline at end of file
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index ef0c4d5..49ffef2 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -31,6 +31,11 @@
public String packageName;
/**
+ * The names of any installed split APKs for this package.
+ */
+ public String[] splitNames;
+
+ /**
* The version number of this package, as specified by the <manifest>
* tag's {@link android.R.styleable#AndroidManifest_versionCode versionCode}
* attribute.
@@ -180,7 +185,9 @@
public ConfigurationInfo[] configPreferences;
/**
- * The features that this application has said it requires.
+ * Features that this application has requested.
+ *
+ * @see FeatureInfo#FLAG_REQUIRED
*/
public FeatureInfo[] reqFeatures;
@@ -190,24 +197,25 @@
* @hide
*/
public static final int INSTALL_LOCATION_UNSPECIFIED = -1;
+
/**
- * Constant corresponding to <code>auto</code> in
- * the {@link android.R.attr#installLocation} attribute.
- * @hide
+ * Constant corresponding to <code>auto</code> in the
+ * {@link android.R.attr#installLocation} attribute.
*/
public static final int INSTALL_LOCATION_AUTO = 0;
+
/**
- * Constant corresponding to <code>internalOnly</code> in
- * the {@link android.R.attr#installLocation} attribute.
- * @hide
+ * Constant corresponding to <code>internalOnly</code> in the
+ * {@link android.R.attr#installLocation} attribute.
*/
public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1;
+
/**
- * Constant corresponding to <code>preferExternal</code> in
- * the {@link android.R.attr#installLocation} attribute.
- * @hide
+ * Constant corresponding to <code>preferExternal</code> in the
+ * {@link android.R.attr#installLocation} attribute.
*/
public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2;
+
/**
* Flag for {@link #requiredForProfile}
* The application will always be installed for a restricted profile.
@@ -222,12 +230,10 @@
public static final int MANAGED_PROFILE = 2;
/**
- * The install location requested by the activity. From the
+ * The install location requested by the package. From the
* {@link android.R.attr#installLocation} attribute, one of
- * {@link #INSTALL_LOCATION_AUTO},
- * {@link #INSTALL_LOCATION_INTERNAL_ONLY},
+ * {@link #INSTALL_LOCATION_AUTO}, {@link #INSTALL_LOCATION_INTERNAL_ONLY},
* {@link #INSTALL_LOCATION_PREFER_EXTERNAL}
- * @hide
*/
public int installLocation = INSTALL_LOCATION_INTERNAL_ONLY;
@@ -269,6 +275,7 @@
public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeString(packageName);
+ dest.writeStringArray(splitNames);
dest.writeInt(versionCode);
dest.writeString(versionName);
dest.writeString(sharedUserId);
@@ -314,6 +321,7 @@
private PackageInfo(Parcel source) {
packageName = source.readString();
+ splitNames = source.readStringArray();
versionCode = source.readInt();
versionName = source.readString();
sharedUserId = source.readString();
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index 50a0483..e336c5f 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -73,6 +73,7 @@
dest.writeInt(versionCode);
dest.writeInt(recommendedInstallLocation);
dest.writeInt(installLocation);
+ dest.writeInt(multiArch ? 1 : 0);
if (verifiers == null || verifiers.length == 0) {
dest.writeInt(0);
@@ -98,6 +99,7 @@
versionCode = source.readInt();
recommendedInstallLocation = source.readInt();
installLocation = source.readInt();
+ multiArch = (source.readInt() != 0);
final int verifiersLength = source.readInt();
if (verifiersLength == 0) {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 401be06..df82d26 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -30,7 +30,31 @@
import java.io.OutputStream;
import java.util.List;
-/** {@hide} */
+/**
+ * Offers the ability to install, upgrade, and remove applications on the
+ * device. This includes support for apps packaged either as a single
+ * "monolithic" APK, or apps packaged as multiple "split" APKs.
+ * <p>
+ * An app is delivered for installation through a
+ * {@link PackageInstaller.Session}, which any app can create. Once the session
+ * is created, the installer can stream one or more APKs into place until it
+ * decides to either commit or destroy the session. Committing may require user
+ * intervention to complete the installation.
+ * <p>
+ * Sessions can install brand new apps, upgrade existing apps, or add new splits
+ * into an existing app.
+ * <p>
+ * Apps packaged as multiple split APKs always consist of a single "base" APK
+ * (with a {@code null} split name) and zero or more "split" APKs (with unique
+ * split names). Any subset of these APKs can be installed together, as long as
+ * the following constraints are met:
+ * <ul>
+ * <li>All APKs must have the exact same package name, version code, and signing
+ * certificates.
+ * <li>All APKs must have unique split names.
+ * <li>All installations must contain a single base APK.
+ * </ul>
+ */
public class PackageInstaller {
private final PackageManager mPm;
private final IPackageInstaller mInstaller;
@@ -46,16 +70,18 @@
mUserId = userId;
}
+ /**
+ * Quickly test if the given package is already available on the device.
+ * This is typically used in multi-user scenarios where another user on the
+ * device has already installed the package.
+ *
+ * @hide
+ */
public boolean isPackageAvailable(String packageName) {
- try {
- final ApplicationInfo info = mPm.getApplicationInfo(packageName,
- PackageManager.GET_UNINSTALLED_PACKAGES);
- return ((info.flags & ApplicationInfo.FLAG_INSTALLED) != 0);
- } catch (NameNotFoundException e) {
- return false;
- }
+ return mPm.isPackageAvailable(packageName);
}
+ /** {@hide} */
public void installAvailablePackage(String packageName, PackageInstallObserver observer) {
int returnCode;
try {
@@ -66,6 +92,18 @@
observer.packageInstalled(packageName, null, returnCode);
}
+ /**
+ * Create a new session using the given parameters, returning a unique ID
+ * that represents the session. Once created, the session can be opened
+ * multiple times across multiple device boots.
+ * <p>
+ * The system may automatically destroy sessions that have not been
+ * finalized (either committed or abandoned) within a reasonable period of
+ * time, typically on the order of a day.
+ *
+ * @throws IOException if parameters were unsatisfiable, such as lack of
+ * disk space or unavailable media.
+ */
public int createSession(InstallSessionParams params) throws IOException {
try {
return mInstaller.createSession(mInstallerPackageName, params, mUserId);
@@ -77,6 +115,9 @@
}
}
+ /**
+ * Open an existing session to actively perform work.
+ */
public Session openSession(int sessionId) {
try {
return new Session(mInstaller.openSession(sessionId));
@@ -85,7 +126,10 @@
}
}
- public List<InstallSessionInfo> getSessions() {
+ /**
+ * Return list of all active install sessions on the device.
+ */
+ public List<InstallSessionInfo> getActiveSessions() {
// TODO: filter based on caller
// TODO: let launcher app see all active sessions
try {
@@ -95,6 +139,11 @@
}
}
+ /**
+ * Uninstall the given package, removing it completely from the device. This
+ * method is only available to the current "installer of record" for the
+ * package.
+ */
public void uninstall(String packageName, UninstallResultCallback callback) {
try {
mInstaller.uninstall(packageName, 0,
@@ -104,6 +153,11 @@
}
}
+ /**
+ * Uninstall only a specific split from the given package.
+ *
+ * @hide
+ */
public void uninstall(String packageName, String splitName, UninstallResultCallback callback) {
try {
mInstaller.uninstallSplit(packageName, splitName, 0,
@@ -113,6 +167,9 @@
}
}
+ /**
+ * Events for observing session lifecycle.
+ */
public static abstract class SessionObserver {
private final IPackageInstallerObserver.Stub mBinder = new IPackageInstallerObserver.Stub() {
@Override
@@ -127,7 +184,7 @@
@Override
public void onSessionFinished(int sessionId, boolean success) {
- SessionObserver.this.onFinished(sessionId, success);
+ SessionObserver.this.onFinalized(sessionId, success);
}
};
@@ -136,11 +193,30 @@
return mBinder;
}
+ /**
+ * New session has been created.
+ */
public abstract void onCreated(InstallSessionInfo info);
+
+ /**
+ * Progress for given session has been updated.
+ * <p>
+ * Note that this progress may not directly correspond to the value
+ * reported by {@link PackageInstaller.Session#setProgress(int)}, as the
+ * system may carve out a portion of the overall progress to represent
+ * its own internal installation work.
+ */
public abstract void onProgress(int sessionId, int progress);
- public abstract void onFinished(int sessionId, boolean success);
+
+ /**
+ * Session has been finalized, either with success or failure.
+ */
+ public abstract void onFinalized(int sessionId, boolean success);
}
+ /**
+ * Register to watch for session lifecycle events.
+ */
public void registerSessionObserver(SessionObserver observer) {
try {
mInstaller.registerObserver(observer.getBinder(), mUserId);
@@ -149,6 +225,9 @@
}
}
+ /**
+ * Unregister an existing observer.
+ */
public void unregisterSessionObserver(SessionObserver observer) {
try {
mInstaller.unregisterObserver(observer.getBinder(), mUserId);
@@ -177,6 +256,10 @@
mSession = session;
}
+ /**
+ * Set current progress. Valid values are anywhere between 0 and
+ * {@link InstallSessionParams#setProgressMax(int)}.
+ */
public void setProgress(int progress) {
try {
mSession.setClientProgress(progress);
@@ -197,7 +280,7 @@
/**
* Open an APK file for writing, starting at the given offset. You can
* then stream data into the file, periodically calling
- * {@link OutputStream#flush()} to ensure bytes have been written to
+ * {@link #fsync(OutputStream)} to ensure bytes have been written to
* disk.
*/
public OutputStream openWrite(String splitName, long offsetBytes, long lengthBytes)
@@ -214,6 +297,11 @@
}
}
+ /**
+ * Ensure that any outstanding data for given stream has been committed
+ * to disk. This is only valid for streams returned from
+ * {@link #openWrite(String, long, long)}.
+ */
public void fsync(OutputStream out) throws IOException {
if (out instanceof FileBridge.FileBridgeOutputStream) {
((FileBridge.FileBridgeOutputStream) out).fsync();
@@ -222,6 +310,15 @@
}
}
+ /**
+ * Attempt to commit everything staged in this session. This may require
+ * user intervention, and so it may not happen immediately. The final
+ * result of the commit will be reported through the given callback.
+ * <p>
+ * Once this method is called, no additional mutations may be performed
+ * on the session. If the device reboots before the session has been
+ * finalized, you may commit the session again.
+ */
public void commit(CommitResultCallback callback) {
try {
mSession.install(new CommitResultCallbackDelegate(callback).getBinder());
@@ -230,11 +327,18 @@
}
}
+ /**
+ * Release this session object. You can open the session again if it
+ * hasn't been finalized.
+ */
@Override
public void close() {
// No resources to release at the moment
}
+ /**
+ * Completely destroy this session, rendering it invalid.
+ */
public void destroy() {
try {
mSession.destroy();
@@ -244,11 +348,15 @@
}
}
+ /**
+ * Final result of an uninstall request.
+ */
public static abstract class UninstallResultCallback {
public abstract void onSuccess();
public abstract void onFailure(String msg);
}
+ /** {@hide} */
private static class UninstallResultCallbackDelegate extends PackageUninstallObserver {
private final UninstallResultCallback target;
@@ -271,8 +379,18 @@
}
}
+ /**
+ * Final result of a session commit request.
+ */
public static abstract class CommitResultCallback {
public abstract void onSuccess();
+
+ /**
+ * Generic failure occurred. You can override methods (such as
+ * {@link #onFailureInvalid(String)}) to handle more specific categories
+ * of failure. By default, those specific categories all flow into this
+ * generic failure.
+ */
public abstract void onFailure(String msg);
/**
@@ -286,12 +404,16 @@
}
/**
- * This install session conflicts (or is inconsistent with) with
- * another package already installed on the device. For example, an
- * existing permission, incompatible certificates, etc. The user may
- * be able to uninstall another app to fix the issue.
+ * This install session conflicts (or is inconsistent with) with another
+ * package already installed on the device. For example, an existing
+ * permission, incompatible certificates, etc. The user may be able to
+ * uninstall another app to fix the issue.
+ *
+ * @param otherPackageName if one specific package was identified as the
+ * cause of the conflict, it's named here. If unknown, or
+ * multiple packages, this may be {@code null}.
*/
- public void onFailureConflict(String msg, String packageName) {
+ public void onFailureConflict(String msg, String otherPackageName) {
onFailure(msg);
}
@@ -317,6 +439,7 @@
}
}
+ /** {@hide} */
private static class CommitResultCallbackDelegate extends PackageInstallObserver {
private final CommitResultCallback target;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 03d4701..37df29a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1167,6 +1167,22 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device includes a relative humidity sensor.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_SENSOR_RELATIVE_HUMIDITY =
+ "android.hardware.sensor.relative_humidity";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: The device includes an ambient temperature sensor.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_SENSOR_AMBIENT_TEMPERATURE =
+ "android.hardware.sensor.ambient_temperature";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has a telephony radio with data
* communication support.
*/
@@ -1623,21 +1639,19 @@
public abstract String[] canonicalToCurrentPackageNames(String[] names);
/**
- * Return a "good" intent to launch a front-door activity in a package,
- * for use for example to implement an "open" button when browsing through
- * packages. The current implementation will look first for a main
- * activity in the category {@link Intent#CATEGORY_INFO}, next for a
- * main activity in the category {@link Intent#CATEGORY_LAUNCHER}, or return
- * null if neither are found.
- *
- * <p>Throws {@link NameNotFoundException} if a package with the given
- * name cannot be found on the system.
+ * Returns a "good" intent to launch a front-door activity in a package.
+ * This is used, for example, to implement an "open" button when browsing
+ * through packages. The current implementation looks first for a main
+ * activity in the category {@link Intent#CATEGORY_INFO}, and next for a
+ * main activity in the category {@link Intent#CATEGORY_LAUNCHER}. Returns
+ * <code>null</code> if neither are found.
*
* @param packageName The name of the package to inspect.
*
- * @return Returns either a fully-qualified Intent that can be used to
- * launch the main activity in the package, or null if the package does
- * not contain such an activity.
+ * @return A fully-qualified {@link Intent} that can be used to launch the
+ * main activity in the package. Returns <code>null</code> if the package
+ * does not contain such an activity, or if <em>packageName</em> is not
+ * recognized.
*/
public abstract Intent getLaunchIntentForPackage(String packageName);
@@ -3602,6 +3616,33 @@
public abstract boolean isSafeMode();
/**
+ * Return the {@link KeySet} associated with the String alias for this
+ * application.
+ *
+ * @param alias The alias for a given {@link KeySet} as defined in the
+ * application's AndroidManifest.xml.
+ */
+ public abstract KeySet getKeySetByAlias(String packageName, String alias);
+
+ /** Return the signing {@link KeySet} for this application. */
+ public abstract KeySet getSigningKeySet(String packageName);
+
+ /**
+ * Return whether the package denoted by packageName has been signed by all
+ * of the keys specified by the {@link KeySet} ks. This will return true if
+ * the package has been signed by additional keys (a superset) as well.
+ * Compare to {@link #isSignedByExactly(String packageName, KeySet ks)}.
+ */
+ public abstract boolean isSignedBy(String packageName, KeySet ks);
+
+ /**
+ * Return whether the package denoted by packageName has been signed by all
+ * of, and only, the keys specified by the {@link KeySet} ks. Compare to
+ * {@link #isSignedBy(String packageName, KeySet ks)}.
+ */
+ public abstract boolean isSignedByExactly(String packageName, KeySet ks);
+
+ /**
* Attempts to move package resources from internal to external media or vice versa.
* Since this may take a little while, the result will
* be posted back to the given observer. This call may fail if the calling context
@@ -3629,8 +3670,11 @@
*/
public abstract VerifierDeviceIdentity getVerifierDeviceIdentity();
- /** {@hide} */
- public abstract PackageInstaller getPackageInstaller();
+ /**
+ * Return interface that offers the ability to install, upgrade, and remove
+ * applications on the device.
+ */
+ public abstract PackageInstaller getInstaller();
/**
* Returns the data directory for a particular user and package, given the uid of the package.
@@ -3676,4 +3720,7 @@
* @hide
*/
public abstract Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo);
+
+ /** {@hide} */
+ public abstract boolean isPackageAvailable(String packageName);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d92a90d..ab33d75 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -82,9 +82,22 @@
import java.util.zip.ZipEntry;
/**
- * Package archive parsing
+ * Parser for package files (APKs) on disk. This supports apps packaged either
+ * as a single "monolithic" APK, or apps packaged as a "cluster" of multiple
+ * APKs in a single directory.
+ * <p>
+ * Apps packaged as multiple APKs always consist of a single "base" APK (with a
+ * {@code null} split name) and zero or more "split" APKs (with unique split
+ * names). Any subset of those split APKs are a valid install, as long as the
+ * following constraints are met:
+ * <ul>
+ * <li>All APKs must have the exact same package name, version code, and signing
+ * certificates.
+ * <li>All APKs must have unique split names.
+ * <li>All installations must contain a single base APK.
+ * </ul>
*
- * {@hide}
+ * @hide
*/
public class PackageParser {
private static final boolean DEBUG_JAR = false;
@@ -92,6 +105,7 @@
private static final boolean DEBUG_BACKUP = false;
// TODO: switch outError users to PackageParserException
+ // TODO: refactor "codePath" to "apkPath"
/** File name in an APK for the Android manifest. */
private static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
@@ -247,6 +261,7 @@
/** Paths of any split APKs, ordered by parsed splitName */
public final String[] splitCodePaths;
+ public final boolean coreApp;
public final boolean multiArch;
private PackageLite(String codePath, ApkLite baseApk, String[] splitNames,
@@ -259,6 +274,7 @@
this.codePath = codePath;
this.baseCodePath = baseApk.codePath;
this.splitCodePaths = splitCodePaths;
+ this.coreApp = baseApk.coreApp;
this.multiArch = baseApk.multiArch;
}
@@ -283,11 +299,12 @@
public final int installLocation;
public final VerifierInfo[] verifiers;
public final Signature[] signatures;
+ public final boolean coreApp;
public final boolean multiArch;
public ApkLite(String codePath, String packageName, String splitName, int versionCode,
int installLocation, List<VerifierInfo> verifiers, Signature[] signatures,
- boolean multiArch) {
+ boolean coreApp, boolean multiArch) {
this.codePath = codePath;
this.packageName = packageName;
this.splitName = splitName;
@@ -295,6 +312,7 @@
this.installLocation = installLocation;
this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
this.signatures = signatures;
+ this.coreApp = coreApp;
this.multiArch = multiArch;
}
}
@@ -322,6 +340,11 @@
mSeparateProcesses = procs;
}
+ /**
+ * Flag indicating this parser should only consider apps with
+ * {@code coreApp} manifest attribute to be valid apps. This is useful when
+ * creating a minimalist boot environment.
+ */
public void setOnlyCoreApps(boolean onlyCoreApps) {
mOnlyCoreApps = onlyCoreApps;
}
@@ -380,6 +403,7 @@
}
PackageInfo pi = new PackageInfo();
pi.packageName = p.packageName;
+ pi.splitNames = p.splitNames;
pi.versionCode = p.mVersionCode;
pi.versionName = p.mVersionName;
pi.sharedUserId = p.mSharedUserId;
@@ -400,7 +424,7 @@
pi.gids = gids;
}
if ((flags&PackageManager.GET_CONFIGURATIONS) != 0) {
- int N = p.configPreferences.size();
+ int N = p.configPreferences != null ? p.configPreferences.size() : 0;
if (N > 0) {
pi.configPreferences = new ConfigurationInfo[N];
p.configPreferences.toArray(pi.configPreferences);
@@ -590,6 +614,17 @@
}
}
+ /**
+ * Parse only lightweight details about the package at the given location.
+ * Automatically detects if the package is a monolithic style (single APK
+ * file) or cluster style (directory of APKs).
+ * <p>
+ * This performs sanity checking on cluster style packages, such as
+ * requiring identical package name and version codes, a single base APK,
+ * and unique split names.
+ *
+ * @see PackageParser#parsePackage(File, int)
+ */
public static PackageLite parsePackageLite(File packageFile, int flags)
throws PackageParserException {
if (packageFile.isDirectory()) {
@@ -676,6 +711,20 @@
return new PackageLite(codePath, baseApk, splitNames, splitCodePaths);
}
+ /**
+ * Parse the package at the given location. Automatically detects if the
+ * package is a monolithic style (single APK file) or cluster style
+ * (directory of APKs).
+ * <p>
+ * This performs sanity checking on cluster style packages, such as
+ * requiring identical package name and version codes, a single base APK,
+ * and unique split names.
+ * <p>
+ * Note that this <em>does not</em> perform signature verification; that
+ * must be done separately in {@link #collectCertificates(Package, int)}.
+ *
+ * @see #parsePackageLite(File, int)
+ */
public Package parsePackage(File packageFile, int flags) throws PackageParserException {
if (packageFile.isDirectory()) {
return parseClusterPackage(packageFile, flags);
@@ -696,6 +745,11 @@
private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
final PackageLite lite = parseClusterPackageLite(packageDir, 0);
+ if (mOnlyCoreApps && !lite.coreApp) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+ "Not a coreApp: " + packageDir);
+ }
+
final File baseApk = new File(lite.baseCodePath);
final Package pkg = parseBaseApk(baseApk, flags);
if (pkg == null) {
@@ -704,12 +758,13 @@
}
if (!ArrayUtils.isEmpty(lite.splitNames)) {
+ final int num = lite.splitNames.length;
pkg.splitNames = lite.splitNames;
pkg.splitCodePaths = lite.splitCodePaths;
+ pkg.splitFlags = new int[num];
- for (String splitCodePath : lite.splitCodePaths) {
- final File splitApk = new File(splitCodePath);
- parseSplitApk(pkg, splitApk, flags);
+ for (int i = 0; i < num; i++) {
+ parseSplitApk(pkg, i, flags);
}
}
@@ -729,115 +784,195 @@
*/
@Deprecated
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
- final Package pkg = parseBaseApk(apkFile, flags);
- if (pkg == null) {
- throw new PackageParserException(mParseError, "Failed to parse " + apkFile);
+ if (mOnlyCoreApps) {
+ final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
+ if (!lite.coreApp) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+ "Not a coreApp: " + apkFile);
+ }
}
+ final Package pkg = parseBaseApk(apkFile, flags);
pkg.codePath = apkFile.getAbsolutePath();
return pkg;
}
- private Package parseBaseApk(File apkFile, int flags) {
- final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;
+ private Package parseBaseApk(File apkFile, int flags) throws PackageParserException {
+ final String apkPath = apkFile.getAbsolutePath();
mParseError = PackageManager.INSTALL_SUCCEEDED;
-
- final String apkPath = apkFile.getAbsolutePath();
mArchiveSourcePath = apkFile.getAbsolutePath();
- if (!apkFile.isFile()) {
- Slog.w(TAG, "Skipping dir: " + apkPath);
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
- return null;
- }
- if (!isApkFile(apkFile) && (flags & PARSE_MUST_BE_APK) != 0) {
- if ((flags&PARSE_IS_SYSTEM) == 0) {
- // We expect to have non-.apk files in the system dir,
- // so don't warn about them.
- Slog.w(TAG, "Skipping non-package file: " + apkPath);
- }
- mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
- return null;
+
+ if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkFile(apkFile)) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+ "Invalid package file: " + apkPath);
}
- if (DEBUG_JAR)
- Slog.d(TAG, "Scanning package: " + apkPath);
+ if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
- XmlResourceParser parser = null;
- AssetManager assmgr = null;
+ AssetManager assets = null;
Resources res = null;
- boolean assetError = true;
+ XmlResourceParser parser = null;
try {
- assmgr = new AssetManager();
- int cookie = assmgr.addAssetPath(apkPath);
- if (cookie != 0) {
- res = new Resources(assmgr, mMetrics, null);
- assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- Build.VERSION.RESOURCES_SDK_INT);
- parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
- assetError = false;
- } else {
- Slog.w(TAG, "Failed adding asset path:" + apkPath);
+ assets = new AssetManager();
+ int cookie = assets.addAssetPath(apkPath);
+ if (cookie == 0) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
+ "Failed adding asset path: " + apkPath);
}
- } catch (Exception e) {
- Slog.w(TAG, "Unable to read AndroidManifest.xml of " + apkPath, e);
- }
- if (assetError) {
- if (assmgr != null) assmgr.close();
- mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
- return null;
- }
- String[] errorText = new String[1];
- Package pkg = null;
- Exception errorException = null;
- try {
- // XXXX todo: need to figure out correct configuration.
- pkg = parseBaseApk(res, parser, flags, trustedOverlay, errorText);
- } catch (Exception e) {
- errorException = e;
- mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
- }
- if (pkg == null) {
- // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED
- // just means to skip this app so don't make a fuss about it.
- if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) {
- if (errorException != null) {
- Slog.w(TAG, apkPath, errorException);
- } else {
- Slog.w(TAG, apkPath + " (at "
- + parser.getPositionDescription()
- + "): " + errorText[0]);
- }
- if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
- mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
- }
+ res = new Resources(assets, mMetrics, null);
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Build.VERSION.RESOURCES_SDK_INT);
+ parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
+
+ final String[] outError = new String[1];
+ final Package pkg = parseBaseApk(res, parser, flags, outError);
+ if (pkg == null) {
+ throw new PackageParserException(mParseError,
+ apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
}
- parser.close();
- assmgr.close();
- return null;
+
+ pkg.baseCodePath = apkPath;
+ pkg.mSignatures = null;
+
+ // TODO: Remove this when the WebView can load resources dynamically. b/11505352
+ pkg.usesOptionalLibraries = ArrayUtils.add(pkg.usesOptionalLibraries,
+ "com.android.webview");
+
+ return pkg;
+
+ } catch (PackageParserException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
+ "Failed to read manifest from " + apkPath, e);
+ } finally {
+ IoUtils.closeQuietly(parser);
+ IoUtils.closeQuietly(assets);
}
-
- parser.close();
- assmgr.close();
-
- pkg.baseCodePath = apkPath;
- pkg.mSignatures = null;
-
- // TODO: Remove this when the WebView can load resources dynamically. b/11505352
- if (pkg.usesOptionalLibraries == null) {
- pkg.usesOptionalLibraries = new ArrayList<String>();
- }
- pkg.usesOptionalLibraries.add("com.android.webview");
-
- return pkg;
}
- private void parseSplitApk(Package pkg, File apkFile, int flags) throws PackageParserException {
- final String splitCodePath = apkFile.getAbsolutePath();
- mArchiveSourcePath = apkFile.getAbsolutePath();
+ private void parseSplitApk(Package pkg, int splitIndex, int flags)
+ throws PackageParserException {
+ final String apkPath = pkg.splitCodePaths[splitIndex];
+ final File apkFile = new File(apkPath);
- // TODO: expand split APK parsing
+ mParseError = PackageManager.INSTALL_SUCCEEDED;
+ mArchiveSourcePath = apkPath;
+
+ if ((flags & PARSE_MUST_BE_APK) != 0 && !isApkFile(apkFile)) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
+ "Invalid package file: " + apkPath);
+ }
+
+ if (DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
+
+ AssetManager assets = null;
+ Resources res = null;
+ XmlResourceParser parser = null;
+ try {
+ assets = new AssetManager();
+ int cookie = assets.addAssetPath(apkPath);
+ if (cookie == 0) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
+ "Failed adding asset path: " + apkPath);
+ }
+
+ res = new Resources(assets, mMetrics, null);
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Build.VERSION.RESOURCES_SDK_INT);
+ parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
+
+ final String[] outError = new String[1];
+ pkg = parseSplitApk(pkg, res, parser, flags, splitIndex, outError);
+ if (pkg == null) {
+ throw new PackageParserException(mParseError,
+ apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
+ }
+
+ } catch (PackageParserException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
+ "Failed to read manifest from " + apkPath, e);
+ } finally {
+ IoUtils.closeQuietly(parser);
+ IoUtils.closeQuietly(assets);
+ }
+ }
+
+ /**
+ * Parse the manifest of a <em>split APK</em>.
+ * <p>
+ * Note that split APKs have many more restrictions on what they're capable
+ * of doing, so many valid features of a base APK have been carefully
+ * omitted here.
+ */
+ private Package parseSplitApk(Package pkg, Resources res, XmlResourceParser parser, int flags,
+ int splitIndex, String[] outError) throws XmlPullParserException, IOException,
+ PackageParserException {
+ AttributeSet attrs = parser;
+
+ // We parsed manifest tag earlier; just skip past it
+ parsePackageSplitNames(parser, attrs, flags);
+
+ mParseInstrumentationArgs = null;
+ mParseActivityArgs = null;
+ mParseServiceArgs = null;
+ mParseProviderArgs = null;
+
+ int type;
+
+ boolean foundApp = false;
+
+ int outerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals("application")) {
+ if (foundApp) {
+ if (RIGID_PARSER) {
+ outError[0] = "<manifest> has more than one <application>";
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return null;
+ } else {
+ Slog.w(TAG, "<manifest> has more than one <application>");
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ }
+
+ foundApp = true;
+ if (!parseSplitApplication(pkg, res, parser, attrs, flags, splitIndex, outError)) {
+ return null;
+ }
+
+ } else if (RIGID_PARSER) {
+ outError[0] = "Bad element under <manifest>: "
+ + parser.getName();
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return null;
+
+ } else {
+ Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
+ + " at " + mArchiveSourcePath + " "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ }
+
+ if (!foundApp) {
+ outError[0] = "<manifest> does not contain an <application>";
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
+ }
+
+ return pkg;
}
/**
@@ -1000,14 +1135,14 @@
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
- AssetManager assmgr = null;
+ AssetManager assets = null;
XmlResourceParser parser = null;
try {
- assmgr = new AssetManager();
- assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assets = new AssetManager();
+ assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
- int cookie = assmgr.addAssetPath(apkPath);
+ int cookie = assets.addAssetPath(apkPath);
if (cookie == 0) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
"Failed to parse " + apkPath);
@@ -1016,8 +1151,8 @@
final DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
- final Resources res = new Resources(assmgr, metrics, null);
- parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
+ final Resources res = new Resources(assets, metrics, null);
+ parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
// Only collect certificates on the manifest; does not validate
// signatures across remainder of package.
@@ -1035,8 +1170,8 @@
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to parse " + apkPath, e);
} finally {
- if (parser != null) parser.close();
- if (assmgr != null) assmgr.close();
+ IoUtils.closeQuietly(parser);
+ IoUtils.closeQuietly(assets);
}
}
@@ -1117,8 +1252,10 @@
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
int versionCode = 0;
- int numFound = 0;
+ boolean coreApp = false;
boolean multiArch = false;
+
+ int numFound = 0;
for (int i = 0; i < attrs.getAttributeCount(); i++) {
String attr = attrs.getAttributeName(i);
if (attr.equals("installLocation")) {
@@ -1128,8 +1265,8 @@
} else if (attr.equals("versionCode")) {
versionCode = attrs.getAttributeIntValue(i, 0);
numFound++;
- } else if (attr.equals("multiArch")) {
- multiArch = attrs.getAttributeBooleanValue(i, false);
+ } else if (attr.equals("coreApp")) {
+ coreApp = attrs.getAttributeBooleanValue(i, false);
numFound++;
}
if (numFound >= 3) {
@@ -1154,10 +1291,20 @@
verifiers.add(verifier);
}
}
+
+ if (parser.getDepth() == searchDepth && "application".equals(parser.getName())) {
+ for (int i = 0; i < attrs.getAttributeCount(); ++i) {
+ final String attr = attrs.getAttributeName(i);
+ if ("multiArch".equals(attr)) {
+ multiArch = attrs.getAttributeBooleanValue(i, false);
+ break;
+ }
+ }
+ }
}
return new ApkLite(codePath, packageSplit.first, packageSplit.second, versionCode,
- installLocation, verifiers, signatures, multiArch);
+ installLocation, verifiers, signatures, coreApp, multiArch);
}
/**
@@ -1172,8 +1319,16 @@
return new Signature(sig);
}
+ /**
+ * Parse the manifest of a <em>base APK</em>.
+ * <p>
+ * When adding new features, carefully consider if they should also be
+ * supported by split APKs.
+ */
private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
- boolean trustedOverlay, String[] outError) throws XmlPullParserException, IOException {
+ String[] outError) throws XmlPullParserException, IOException {
+ final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;
+
AttributeSet attrs = parser;
mParseInstrumentationArgs = null;
@@ -1194,14 +1349,6 @@
int type;
- if (mOnlyCoreApps) {
- boolean core = attrs.getAttributeBooleanValue(null, "coreApp", false);
- if (!core) {
- mParseError = PackageManager.INSTALL_SUCCEEDED;
- return null;
- }
- }
-
if (!TextUtils.isEmpty(splitName)) {
outError[0] = "Expected base APK, but found split " + splitName;
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
@@ -1282,7 +1429,7 @@
}
foundApp = true;
- if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
+ if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {
return null;
}
} else if (tagName.equals("overlay")) {
@@ -1354,7 +1501,7 @@
cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
}
sa.recycle();
- pkg.configPreferences.add(cPref);
+ pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
XmlUtils.skipCurrentTag(parser);
@@ -1377,15 +1524,12 @@
fi.flags |= FeatureInfo.FLAG_REQUIRED;
}
sa.recycle();
- if (pkg.reqFeatures == null) {
- pkg.reqFeatures = new ArrayList<FeatureInfo>();
- }
- pkg.reqFeatures.add(fi);
-
+ pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);
+
if (fi.name == null) {
ConfigurationInfo cPref = new ConfigurationInfo();
cPref.reqGlEsVersion = fi.reqGlEsVersion;
- pkg.configPreferences.add(cPref);
+ pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
}
XmlUtils.skipCurrentTag(parser);
@@ -2196,7 +2340,14 @@
return a;
}
- private boolean parseApplication(Package owner, Resources res,
+ /**
+ * Parse the {@code application} XML tree at the current parse location in a
+ * <em>base APK</em> manifest.
+ * <p>
+ * When adding new features, carefully consider if they should also be
+ * supported by split APKs.
+ */
+ private boolean parseBaseApplication(Package owner, Resources res,
XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
throws XmlPullParserException, IOException {
final ApplicationInfo ai = owner.applicationInfo;
@@ -2316,7 +2467,7 @@
ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
}
- boolean hardwareAccelerated = sa.getBoolean(
+ owner.baseHardwareAccelerated = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
@@ -2441,7 +2592,7 @@
String tagName = parser.getName();
if (tagName.equals("activity")) {
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
- hardwareAccelerated);
+ owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
@@ -2507,11 +2658,9 @@
sa.recycle();
if (lname != null) {
- if (owner.libraryNames == null) {
- owner.libraryNames = new ArrayList<String>();
- }
- if (!owner.libraryNames.contains(lname)) {
- owner.libraryNames.add(lname.intern());
+ lname = lname.intern();
+ if (!ArrayUtils.contains(owner.libraryNames, lname)) {
+ owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);
}
}
@@ -2532,19 +2681,150 @@
sa.recycle();
if (lname != null) {
+ lname = lname.intern();
if (req) {
- if (owner.usesLibraries == null) {
- owner.usesLibraries = new ArrayList<String>();
- }
- if (!owner.usesLibraries.contains(lname)) {
- owner.usesLibraries.add(lname.intern());
- }
+ owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
} else {
- if (owner.usesOptionalLibraries == null) {
- owner.usesOptionalLibraries = new ArrayList<String>();
- }
- if (!owner.usesOptionalLibraries.contains(lname)) {
- owner.usesOptionalLibraries.add(lname.intern());
+ owner.usesOptionalLibraries = ArrayUtils.add(
+ owner.usesOptionalLibraries, lname);
+ }
+ }
+
+ XmlUtils.skipCurrentTag(parser);
+
+ } else if (tagName.equals("uses-package")) {
+ // Dependencies for app installers; we don't currently try to
+ // enforce this.
+ XmlUtils.skipCurrentTag(parser);
+
+ } else {
+ if (!RIGID_PARSER) {
+ Slog.w(TAG, "Unknown element under <application>: " + tagName
+ + " at " + mArchiveSourcePath + " "
+ + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ } else {
+ outError[0] = "Bad element under <application>: " + tagName;
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Parse the {@code application} XML tree at the current parse location in a
+ * <em>split APK</em> manifest.
+ * <p>
+ * Note that split APKs have many more restrictions on what they're capable
+ * of doing, so many valid features of a base APK have been carefully
+ * omitted here.
+ */
+ private boolean parseSplitApplication(Package owner, Resources res, XmlPullParser parser,
+ AttributeSet attrs, int flags, int splitIndex, String[] outError)
+ throws XmlPullParserException, IOException {
+ TypedArray sa = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.AndroidManifestApplication);
+
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestApplication_hasCode, true)) {
+ owner.splitFlags[splitIndex] |= ApplicationInfo.FLAG_HAS_CODE;
+ }
+
+ final int innerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals("activity")) {
+ Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
+ owner.baseHardwareAccelerated);
+ if (a == null) {
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return false;
+ }
+
+ owner.activities.add(a);
+
+ } else if (tagName.equals("receiver")) {
+ Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
+ if (a == null) {
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return false;
+ }
+
+ owner.receivers.add(a);
+
+ } else if (tagName.equals("service")) {
+ Service s = parseService(owner, res, parser, attrs, flags, outError);
+ if (s == null) {
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return false;
+ }
+
+ owner.services.add(s);
+
+ } else if (tagName.equals("provider")) {
+ Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
+ if (p == null) {
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return false;
+ }
+
+ owner.providers.add(p);
+
+ } else if (tagName.equals("activity-alias")) {
+ Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
+ if (a == null) {
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return false;
+ }
+
+ owner.activities.add(a);
+
+ } else if (parser.getName().equals("meta-data")) {
+ // note: application meta-data is stored off to the side, so it can
+ // remain null in the primary copy (we like to avoid extra copies because
+ // it can be large)
+ if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,
+ outError)) == null) {
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return false;
+ }
+
+ } else if (tagName.equals("uses-library")) {
+ sa = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.AndroidManifestUsesLibrary);
+
+ // Note: don't allow this value to be a reference to a resource
+ // that may change.
+ String lname = sa.getNonResourceString(
+ com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);
+ boolean req = sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,
+ true);
+
+ sa.recycle();
+
+ if (lname != null) {
+ lname = lname.intern();
+ if (req) {
+ // Upgrade to treat as stronger constraint
+ owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);
+ owner.usesOptionalLibraries = ArrayUtils.remove(
+ owner.usesOptionalLibraries, lname);
+ } else {
+ // Ignore if someone already defined as required
+ if (!ArrayUtils.contains(owner.usesLibraries, lname)) {
+ owner.usesOptionalLibraries = ArrayUtils.add(
+ owner.usesOptionalLibraries, lname);
}
}
}
@@ -3865,6 +4145,11 @@
/** Paths of any split APKs, ordered by parsed splitName */
public String[] splitCodePaths;
+ /** Flags of any split APKs; ordered by parsed splitName */
+ public int[] splitFlags;
+
+ public boolean baseHardwareAccelerated;
+
// For now we only support one application per package.
public final ApplicationInfo applicationInfo = new ApplicationInfo();
@@ -3916,7 +4201,7 @@
public int mPreferredOrder = 0;
// For use by package manager to keep track of where it needs to do dexopt.
- public boolean mDexOptNeeded = true;
+ public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
// For use by package manager to keep track of when a package was last used.
public long mLastPackageUsageTimeInMills;
@@ -3933,15 +4218,10 @@
// Whether an operation is currently pending on this package
public boolean mOperationPending;
- /*
- * Applications hardware preferences
- */
- public final ArrayList<ConfigurationInfo> configPreferences =
- new ArrayList<ConfigurationInfo>();
+ // Applications hardware preferences
+ public ArrayList<ConfigurationInfo> configPreferences = null;
- /*
- * Applications requested features
- */
+ // Applications requested features
public ArrayList<FeatureInfo> reqFeatures = null;
public int installLocation;
@@ -3990,6 +4270,25 @@
return paths;
}
+ /**
+ * Filtered set of {@link #getAllCodePaths()} that excludes
+ * resource-only APKs.
+ */
+ public List<String> getAllCodePathsExcludingResourceOnly() {
+ ArrayList<String> paths = new ArrayList<>();
+ if ((applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
+ paths.add(baseCodePath);
+ }
+ if (!ArrayUtils.isEmpty(splitCodePaths)) {
+ for (int i = 0; i < splitCodePaths.length; i++) {
+ if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
+ paths.add(splitCodePaths[i]);
+ }
+ }
+ }
+ return paths;
+ }
+
public void setPackageName(String newName) {
packageName = newName;
applicationInfo.packageName = newName;
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 0c04401..3a30123 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -33,7 +33,7 @@
* files that have been bundled with the application as a simple stream of
* bytes.
*/
-public final class AssetManager {
+public final class AssetManager implements AutoCloseable {
/* modes used when opening an asset */
/**
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 9625578..38ddede 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1711,7 +1711,7 @@
String locale = null;
if (mConfiguration.locale != null) {
- locale = adjustLanguageTag(localeToLanguageTag(mConfiguration.locale));
+ locale = adjustLanguageTag(mConfiguration.locale.toLanguageTag());
}
int width, height;
if (mMetrics.widthPixels >= mMetrics.heightPixels) {
@@ -1800,12 +1800,6 @@
}
}
- // Locale.toLanguageTag() is not available in Java6. LayoutLib overrides
- // this method to enable users to use Java6.
- private String localeToLanguageTag(Locale locale) {
- return locale.toLanguageTag();
- }
-
/**
* {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
* language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index cf462cd..eadfa73 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -133,7 +133,11 @@
* <p>For more information about using cameras, read the
* <a href="{@docRoot}guide/topics/media/camera.html">Camera</a> developer guide.</p>
* </div>
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+@Deprecated
public class Camera {
private static final String TAG = "Camera";
@@ -247,7 +251,11 @@
/**
* Information about a camera
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public static class CameraInfo {
/**
* The facing of the camera is opposite to that of the screen.
@@ -675,7 +683,11 @@
* @see #setOneShotPreviewCallback(Camera.PreviewCallback)
* @see #setPreviewCallbackWithBuffer(Camera.PreviewCallback)
* @see #startPreview()
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public interface PreviewCallback
{
/**
@@ -1175,7 +1187,10 @@
* manifest element.</p>
*
* @see #autoFocus(AutoFocusCallback)
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public interface AutoFocusCallback
{
/**
@@ -1286,7 +1301,11 @@
* Parameters#FOCUS_MODE_CONTINUOUS_VIDEO} and {@link
* Parameters#FOCUS_MODE_CONTINUOUS_PICTURE}. Applications can show
* autofocus animation based on this.</p>
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public interface AutoFocusMoveCallback
{
/**
@@ -1314,7 +1333,11 @@
* Callback interface used to signal the moment of actual image capture.
*
* @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback)
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public interface ShutterCallback
{
/**
@@ -1331,7 +1354,11 @@
* Callback interface used to supply image data from a photo capture.
*
* @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback)
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public interface PictureCallback {
/**
* Called when image data is available after a picture is taken.
@@ -1538,7 +1565,11 @@
*
* @see #setZoomChangeListener(OnZoomChangeListener)
* @see #startSmoothZoom(int)
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public interface OnZoomChangeListener
{
/**
@@ -1568,7 +1599,10 @@
/**
* Callback interface for face detected in the preview frame.
*
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public interface FaceDetectionListener
{
/**
@@ -1652,7 +1686,10 @@
* list of face objects for use in focusing and metering.</p>
*
* @see FaceDetectionListener
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public static class Face {
/**
* Create an empty face.
@@ -1766,7 +1803,11 @@
* Callback interface for camera error notification.
*
* @see #setErrorCallback(ErrorCallback)
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public interface ErrorCallback
{
/**
@@ -1864,7 +1905,10 @@
/**
* Image size (width and height dimensions).
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public class Size {
/**
* Sets the dimensions for pictures.
@@ -1931,7 +1975,11 @@
* @see Parameters#setMeteringAreas(List)
* @see Parameters#getMeteringAreas()
* @see Parameters#getMaxNumMeteringAreas()
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public static class Area {
/**
* Create an area with specified rectangle and weight.
@@ -2005,7 +2053,11 @@
* calling {@link Camera.Parameters#setColorEffect(String)}. If the
* camera does not support color effects,
* {@link Camera.Parameters#getSupportedColorEffects()} will return null.
+ *
+ * @deprecated We recommend using the new {@link android.hardware.camera2} API for new
+ * applications.
*/
+ @Deprecated
public class Parameters {
// Parameter keys to communicate with the camera driver.
private static final String KEY_PREVIEW_SIZE = "preview-size";
@@ -2371,6 +2423,19 @@
return Camera.this;
}
+
+ /**
+ * Value equality check.
+ *
+ * @hide
+ */
+ public boolean same(Parameters other) {
+ if (this == other) {
+ return true;
+ }
+ return other != null && Parameters.this.mMap.equals(other.mMap);
+ }
+
/**
* Writes the current Parameters to the log.
* @hide
@@ -2960,7 +3025,6 @@
case ImageFormat.YV12: return PIXEL_FORMAT_YUV420P;
case ImageFormat.RGB_565: return PIXEL_FORMAT_RGB565;
case ImageFormat.JPEG: return PIXEL_FORMAT_JPEG;
- case ImageFormat.BAYER_RGGB: return PIXEL_FORMAT_BAYER_RGGB;
default: return null;
}
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 4b1659f..4976a48 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -131,6 +131,7 @@
}
private final CameraMetadataNative mProperties;
+ private List<CameraCharacteristics.Key<?>> mKeys;
private List<CaptureRequest.Key<?>> mAvailableRequestKeys;
private List<CaptureResult.Key<?>> mAvailableResultKeys;
@@ -194,8 +195,20 @@
*/
@Override
public List<Key<?>> getKeys() {
- // Force the javadoc for this function to show up on the CameraCharacteristics page
- return super.getKeys();
+ // List of keys is immutable; cache the results after we calculate them
+ if (mKeys != null) {
+ return mKeys;
+ }
+
+ int[] filterTags = get(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+ if (filterTags == null) {
+ throw new AssertionError("android.request.availableCharacteristicsKeys must be non-null"
+ + " in the characteristics");
+ }
+
+ mKeys = Collections.unmodifiableList(
+ getKeysStatic(getClass(), getKeyClass(), this, filterTags));
+ return mKeys;
}
/**
@@ -218,8 +231,13 @@
Object crKey = CaptureRequest.Key.class;
Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>)crKey;
- mAvailableRequestKeys = Collections.unmodifiableList(
- getAvailableKeyList(CaptureRequest.class, crKeyTyped));
+ int[] filterTags = get(REQUEST_AVAILABLE_REQUEST_KEYS);
+ if (filterTags == null) {
+ throw new AssertionError("android.request.availableRequestKeys must be non-null "
+ + "in the characteristics");
+ }
+ mAvailableRequestKeys =
+ getAvailableKeyList(CaptureRequest.class, crKeyTyped, filterTags);
}
return mAvailableRequestKeys;
}
@@ -244,8 +262,12 @@
Object crKey = CaptureResult.Key.class;
Class<CaptureResult.Key<?>> crKeyTyped = (Class<CaptureResult.Key<?>>)crKey;
- mAvailableResultKeys = Collections.unmodifiableList(
- getAvailableKeyList(CaptureResult.class, crKeyTyped));
+ int[] filterTags = get(REQUEST_AVAILABLE_RESULT_KEYS);
+ if (filterTags == null) {
+ throw new AssertionError("android.request.availableResultKeys must be non-null "
+ + "in the characteristics");
+ }
+ mAvailableResultKeys = getAvailableKeyList(CaptureResult.class, crKeyTyped, filterTags);
}
return mAvailableResultKeys;
}
@@ -266,7 +288,7 @@
* @throws IllegalArgumentException if metadataClass is not a subclass of CameraMetadata
*/
private <TKey> List<TKey>
- getAvailableKeyList(Class<?> metadataClass, Class<TKey> keyClass) {
+ getAvailableKeyList(Class<?> metadataClass, Class<TKey> keyClass, int[] filterTags) {
if (metadataClass.equals(CameraMetadata.class)) {
throw new AssertionError(
@@ -277,7 +299,7 @@
}
List<TKey> staticKeyList = CameraCharacteristics.<TKey>getKeysStatic(
- metadataClass, keyClass, /*instance*/null);
+ metadataClass, keyClass, /*instance*/null, filterTags);
return Collections.unmodifiableList(staticKeyList);
}
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index fa35f44..36b1089 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -16,11 +16,13 @@
package android.hardware.camera2;
+import android.hardware.camera2.impl.CameraMetadataNative;
import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@@ -101,7 +103,8 @@
@SuppressWarnings("unchecked")
public List<TKey> getKeys() {
Class<CameraMetadata<TKey>> thisClass = (Class<CameraMetadata<TKey>>) getClass();
- return Collections.unmodifiableList(getKeysStatic(thisClass, getKeyClass(), this));
+ return Collections.unmodifiableList(
+ getKeysStatic(thisClass, getKeyClass(), this, /*filterTags*/null));
}
/**
@@ -111,14 +114,25 @@
* <p>
* Optionally, if {@code instance} is not null, then filter out any keys with null values.
* </p>
+ *
+ * <p>
+ * Optionally, if {@code filterTags} is not {@code null}, then filter out any keys
+ * whose native {@code tag} is not in {@code filterTags}. The {@code filterTags} array will be
+ * sorted as a side effect.
+ * </p>
*/
/*package*/ @SuppressWarnings("unchecked")
static <TKey> ArrayList<TKey> getKeysStatic(
Class<?> type, Class<TKey> keyClass,
- CameraMetadata<TKey> instance) {
+ CameraMetadata<TKey> instance,
+ int[] filterTags) {
if (VERBOSE) Log.v(TAG, "getKeysStatic for " + type);
+ if (filterTags != null) {
+ Arrays.sort(filterTags);
+ }
+
ArrayList<TKey> keyList = new ArrayList<TKey>();
Field[] fields = type.getDeclaredFields();
@@ -137,7 +151,15 @@
}
if (instance == null || instance.getProtected(key) != null) {
- keyList.add(key);
+ if (shouldKeyBeAdded(key, filterTags)) {
+ keyList.add(key);
+
+ if (VERBOSE) {
+ Log.v(TAG, "getKeysStatic - key was added - " + key);
+ }
+ } else if (VERBOSE) {
+ Log.v(TAG, "getKeysStatic - key was filtered - " + key);
+ }
}
}
}
@@ -145,6 +167,39 @@
return keyList;
}
+ @SuppressWarnings("rawtypes")
+ private static <TKey> boolean shouldKeyBeAdded(TKey key, int[] filterTags) {
+ if (key == null) {
+ throw new NullPointerException("key must not be null");
+ }
+
+ CameraMetadataNative.Key nativeKey;
+
+ /*
+ * Get the native key from the public api key
+ */
+ if (key instanceof CameraCharacteristics.Key) {
+ nativeKey = ((CameraCharacteristics.Key)key).getNativeKey();
+ } else if (key instanceof CaptureResult.Key) {
+ nativeKey = ((CaptureResult.Key)key).getNativeKey();
+ } else if (key instanceof CaptureRequest.Key) {
+ nativeKey = ((CaptureRequest.Key)key).getNativeKey();
+ } else {
+ // Reject fields that aren't a key
+ throw new IllegalArgumentException("key type must be that of a metadata key");
+ }
+
+ // No filtering necessary
+ if (filterTags == null) {
+ return true;
+ }
+
+ int keyTag = nativeKey.getTag();
+
+ // non-negative result is returned iff the value is in the array
+ return Arrays.binarySearch(filterTags, keyTag) >= 0;
+ }
+
/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* The enum values below this point are generated from metadata
* definitions in /system/media/camera/docs. Do not modify by hand or
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 6de5c25..ebab563 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -56,7 +56,6 @@
import android.os.Parcelable;
import android.os.Parcel;
import android.util.Log;
-import android.util.Pair;
import android.util.Size;
import com.android.internal.util.Preconditions;
@@ -79,7 +78,7 @@
private final Class<T> mType;
private final TypeReference<T> mTypeReference;
private final String mName;
-
+ private final int mHash;
/**
* Visible for testing only.
*
@@ -95,6 +94,7 @@
mName = name;
mType = type;
mTypeReference = TypeReference.createSpecializedTypeReference(type);
+ mHash = mName.hashCode() ^ mTypeReference.hashCode();
}
/**
@@ -113,6 +113,7 @@
mName = name;
mType = (Class<T>)typeReference.getRawType();
mTypeReference = typeReference;
+ mHash = mName.hashCode() ^ mTypeReference.hashCode();
}
/**
@@ -137,7 +138,7 @@
*/
@Override
public final int hashCode() {
- return mName.hashCode() ^ mTypeReference.hashCode();
+ return mHash;
}
/**
@@ -156,6 +157,10 @@
return true;
}
+ if (o == null || this.hashCode() != o.hashCode()) {
+ return false;
+ }
+
Key<?> lhs;
if (o instanceof CaptureResult.Key) {
@@ -337,11 +342,11 @@
public <T> T get(Key<T> key) {
Preconditions.checkNotNull(key, "key must not be null");
- Pair<T, Boolean> override = getOverride(key);
- if (override.second) {
- return override.first;
+ // Check if key has been overridden to use a wrapper class on the java side.
+ GetCommand g = sGetCommandMap.get(key);
+ if (g != null) {
+ return (T) g.getValue(this, key);
}
-
return getBase(key);
}
@@ -371,7 +376,9 @@
* type to the key.
*/
public <T> void set(Key<T> key, T value) {
- if (setOverride(key, value)) {
+ SetCommand s = sSetCommandMap.get(key);
+ if (s != null) {
+ s.setValue(this, value);
return;
}
@@ -449,44 +456,119 @@
ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder());
return marshaler.unmarshal(buffer);
}
- // Need overwrite some metadata that has different definitions between native
- // and managed sides.
- @SuppressWarnings("unchecked")
- private <T> Pair<T, Boolean> getOverride(Key<T> key) {
- T value = null;
- boolean override = true;
- if (key.equals(CameraCharacteristics.SCALER_AVAILABLE_FORMATS)) {
- value = (T) getAvailableFormats();
- } else if (key.equals(CaptureResult.STATISTICS_FACES)) {
- value = (T) getFaces();
- } else if (key.equals(CaptureResult.STATISTICS_FACE_RECTANGLES)) {
- value = (T) getFaceRectangles();
- } else if (key.equals(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)) {
- value = (T) getStreamConfigurationMap();
- } else if (key.equals(CameraCharacteristics.CONTROL_MAX_REGIONS_AE)) {
- value = (T) getMaxRegions(key);
- } else if (key.equals(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB)) {
- value = (T) getMaxRegions(key);
- } else if (key.equals(CameraCharacteristics.CONTROL_MAX_REGIONS_AF)) {
- value = (T) getMaxRegions(key);
- } else if (key.equals(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW)) {
- value = (T) getMaxNumOutputs(key);
- } else if (key.equals(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC)) {
- value = (T) getMaxNumOutputs(key);
- } else if (key.equals(CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING)) {
- value = (T) getMaxNumOutputs(key);
- } else if (key.equals(CaptureRequest.TONEMAP_CURVE)) {
- value = (T) getTonemapCurve();
- } else if (key.equals(CaptureResult.JPEG_GPS_LOCATION)) {
- value = (T) getGpsLocation();
- } else if (key.equals(CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP)) {
- value = (T) getLensShadingMap();
- } else {
- override = false;
- }
-
- return Pair.create(value, override);
+ // Use Command pattern here to avoid lots of expensive if/equals checks in get for overridden
+ // metadata.
+ private static final HashMap<Key<?>, GetCommand> sGetCommandMap =
+ new HashMap<Key<?>, GetCommand>();
+ static {
+ sGetCommandMap.put(
+ CameraCharacteristics.SCALER_AVAILABLE_FORMATS.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getAvailableFormats();
+ }
+ });
+ sGetCommandMap.put(
+ CaptureResult.STATISTICS_FACES.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getFaceRectangles();
+ }
+ });
+ sGetCommandMap.put(
+ CaptureResult.STATISTICS_FACE_RECTANGLES.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getFaces();
+ }
+ });
+ sGetCommandMap.put(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP.getNativeKey(),
+ new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getStreamConfigurationMap();
+ }
+ });
+ sGetCommandMap.put(
+ CameraCharacteristics.CONTROL_MAX_REGIONS_AE.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getMaxRegions(key);
+ }
+ });
+ sGetCommandMap.put(
+ CameraCharacteristics.CONTROL_MAX_REGIONS_AWB.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getMaxRegions(key);
+ }
+ });
+ sGetCommandMap.put(
+ CameraCharacteristics.CONTROL_MAX_REGIONS_AF.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getMaxRegions(key);
+ }
+ });
+ sGetCommandMap.put(
+ CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_RAW.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getMaxNumOutputs(key);
+ }
+ });
+ sGetCommandMap.put(
+ CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getMaxNumOutputs(key);
+ }
+ });
+ sGetCommandMap.put(
+ CameraCharacteristics.REQUEST_MAX_NUM_OUTPUT_PROC_STALLING.getNativeKey(),
+ new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getMaxNumOutputs(key);
+ }
+ });
+ sGetCommandMap.put(
+ CaptureRequest.TONEMAP_CURVE.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getTonemapCurve();
+ }
+ });
+ sGetCommandMap.put(
+ CaptureResult.JPEG_GPS_LOCATION.getNativeKey(), new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getGpsLocation();
+ }
+ });
+ sGetCommandMap.put(
+ CaptureResult.STATISTICS_LENS_SHADING_CORRECTION_MAP.getNativeKey(),
+ new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getLensShadingMap();
+ }
+ });
}
private int[] getAvailableFormats() {
@@ -759,19 +841,37 @@
writeValues(tag, values);
}
- // Set the camera metadata override.
- private <T> boolean setOverride(Key<T> key, T value) {
- if (key.equals(CameraCharacteristics.SCALER_AVAILABLE_FORMATS)) {
- return setAvailableFormats((int[]) value);
- } else if (key.equals(CaptureResult.STATISTICS_FACE_RECTANGLES)) {
- return setFaceRectangles((Rect[]) value);
- } else if (key.equals(CaptureRequest.TONEMAP_CURVE)) {
- return setTonemapCurve((TonemapCurve) value);
- } else if (key.equals(CaptureResult.JPEG_GPS_LOCATION)) {
- return setGpsLocation((Location) value);
- }
- // For other keys, set() falls back to setBase().
- return false;
+ // Use Command pattern here to avoid lots of expensive if/equals checks in get for overridden
+ // metadata.
+ private static final HashMap<Key<?>, SetCommand> sSetCommandMap =
+ new HashMap<Key<?>, SetCommand>();
+ static {
+ sSetCommandMap.put(CameraCharacteristics.SCALER_AVAILABLE_FORMATS.getNativeKey(),
+ new SetCommand() {
+ @Override
+ public <T> void setValue(CameraMetadataNative metadata, T value) {
+ metadata.setAvailableFormats((int[]) value);
+ }
+ });
+ sSetCommandMap.put(CaptureResult.STATISTICS_FACE_RECTANGLES.getNativeKey(),
+ new SetCommand() {
+ @Override
+ public <T> void setValue(CameraMetadataNative metadata, T value) {
+ metadata.setFaceRectangles((Rect[]) value);
+ }
+ });
+ sSetCommandMap.put(CaptureRequest.TONEMAP_CURVE.getNativeKey(), new SetCommand() {
+ @Override
+ public <T> void setValue(CameraMetadataNative metadata, T value) {
+ metadata.setTonemapCurve((TonemapCurve) value);
+ }
+ });
+ sSetCommandMap.put(CaptureResult.JPEG_GPS_LOCATION.getNativeKey(), new SetCommand() {
+ @Override
+ public <T> void setValue(CameraMetadataNative metadata, T value) {
+ metadata.setGpsLocation((Location) value);
+ }
+ });
}
private boolean setAvailableFormats(int[] value) {
diff --git a/core/java/android/hardware/camera2/impl/GetCommand.java b/core/java/android/hardware/camera2/impl/GetCommand.java
new file mode 100644
index 0000000..a3c677a
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/GetCommand.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera2.impl;
+
+/**
+ * Getter interface for use with Command pattern metadata value getters.
+ */
+public interface GetCommand {
+
+ /**
+ * Get the value from the given {@link CameraMetadataNative} object.
+ *
+ * @param metadata the {@link CameraMetadataNative} object to get the value from.
+ * @param key the {@link CameraMetadataNative.Key} to look up.
+ * @param <T> the type of the value.
+ * @return the value for a given {@link CameraMetadataNative.Key}.
+ */
+ public <T> T getValue(CameraMetadataNative metadata, CameraMetadataNative.Key<T> key);
+}
diff --git a/core/java/android/hardware/camera2/impl/SetCommand.java b/core/java/android/hardware/camera2/impl/SetCommand.java
new file mode 100644
index 0000000..82a01b2
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/SetCommand.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera2.impl;
+
+/**
+ * Setter interface for use with Command pattern metadata value setters.
+ */
+public interface SetCommand {
+
+ /**
+ * Set the value in the given metadata.
+ *
+ * @param metadata {@link CameraMetadataNative} to set value in.
+ * @param value value to set.
+ * @param <T> type of the value to set.
+ */
+ public <T> void setValue(/*inout*/CameraMetadataNative metadata,
+ T value);
+}
diff --git a/core/java/android/hardware/camera2/legacy/BurstHolder.java b/core/java/android/hardware/camera2/legacy/BurstHolder.java
index e35eb50..c141c51 100644
--- a/core/java/android/hardware/camera2/legacy/BurstHolder.java
+++ b/core/java/android/hardware/camera2/legacy/BurstHolder.java
@@ -17,6 +17,9 @@
package android.hardware.camera2.legacy;
import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.util.Log;
+import android.view.Surface;
import java.util.ArrayList;
import java.util.List;
@@ -25,8 +28,8 @@
* Immutable container for a burst of capture results.
*/
public class BurstHolder {
-
- private final ArrayList<CaptureRequest> mRequests;
+ private static final String TAG = "BurstHolder";
+ private final ArrayList<RequestHolder.Builder> mRequestBuilders;
private final boolean mRepeating;
private final int mRequestId;
@@ -38,7 +41,13 @@
* @param requests a {@link java.util.List} of {@link CaptureRequest}s in this burst.
*/
public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests) {
- mRequests = new ArrayList<CaptureRequest>(requests);
+ mRequestBuilders = new ArrayList<RequestHolder.Builder>();
+ int i = 0;
+ for (CaptureRequest r : requests) {
+ mRequestBuilders.add(new RequestHolder.Builder(requestId, /*subsequenceId*/i,
+ /*request*/r, repeating));
+ ++i;
+ }
mRepeating = repeating;
mRequestId = requestId;
}
@@ -61,7 +70,7 @@
* Return the number of requests in this burst sequence.
*/
public int getNumberOfRequests() {
- return mRequests.size();
+ return mRequestBuilders.size();
}
/**
@@ -73,8 +82,8 @@
public List<RequestHolder> produceRequestHolders(long frameNumber) {
ArrayList<RequestHolder> holders = new ArrayList<RequestHolder>();
int i = 0;
- for (CaptureRequest r : mRequests) {
- holders.add(new RequestHolder(mRequestId, i, r, mRepeating, frameNumber + i));
+ for (RequestHolder.Builder b : mRequestBuilders) {
+ holders.add(b.build(frameNumber + i));
++i;
}
return holders;
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index e9793c4..5f29e5c 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -17,6 +17,7 @@
package android.hardware.camera2.legacy;
import android.graphics.ImageFormat;
+import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
@@ -463,6 +464,24 @@
return ids.contains(id);
}
+ static void setSurfaceOrientation(Surface surface, int facing, int sensorOrientation)
+ throws BufferQueueAbandonedException {
+ checkNotNull(surface);
+ LegacyExceptionUtils.throwOnError(nativeSetSurfaceOrientation(surface, facing,
+ sensorOrientation));
+ }
+
+ static Size getTextureSize(SurfaceTexture surfaceTexture)
+ throws BufferQueueAbandonedException {
+ checkNotNull(surfaceTexture);
+
+ int[] dimens = new int[2];
+ LegacyExceptionUtils.throwOnError(nativeDetectTextureDimens(surfaceTexture,
+ /*out*/dimens));
+
+ return new Size(dimens[0], dimens[1]);
+ }
+
private static native int nativeDetectSurfaceType(Surface surface);
private static native int nativeDetectSurfaceDimens(Surface surface,
@@ -479,4 +498,11 @@
private static native int nativeSetSurfaceDimens(Surface surface, int width, int height);
private static native long nativeGetSurfaceId(Surface surface);
+
+ private static native int nativeSetSurfaceOrientation(Surface surface, int facing,
+ int sensorOrientation);
+
+ private static native int nativeDetectTextureDimens(SurfaceTexture surfaceTexture,
+ /*out*/int[/*2*/] dimens);
+
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
index a10a2af..88f95e1 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyResultMapper.java
@@ -28,15 +28,12 @@
import android.hardware.camera2.legacy.ParameterUtils.ZoomData;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.utils.ListUtils;
-import android.hardware.camera2.utils.ParamsUtils;
import android.util.Log;
-import android.util.Rational;
import android.util.Size;
import java.util.ArrayList;
import java.util.List;
-import static com.android.internal.util.Preconditions.*;
import static android.hardware.camera2.CaptureResult.*;
/**
@@ -46,6 +43,36 @@
private static final String TAG = "LegacyResultMapper";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+ private LegacyRequest mCachedRequest = null;
+ private CameraMetadataNative mCachedResult = null;
+
+ /**
+ * Generate capture result metadata from the legacy camera request.
+ *
+ * <p>This method caches and reuses the result from the previous call to this method if
+ * the {@code parameters} of the subsequent {@link LegacyRequest} passed to this method
+ * have not changed.</p>
+ *
+ * @param legacyRequest a non-{@code null} legacy request containing the latest parameters
+ * @param timestamp the timestamp to use for this result in nanoseconds.
+ *
+ * @return {@link CameraMetadataNative} object containing result metadata.
+ */
+ public CameraMetadataNative cachedConvertResultMetadata(
+ LegacyRequest legacyRequest, long timestamp) {
+ if (mCachedRequest != null && legacyRequest.parameters.same(mCachedRequest.parameters)) {
+ CameraMetadataNative newResult = new CameraMetadataNative(mCachedResult);
+
+ // sensor.timestamp
+ newResult.set(CaptureResult.SENSOR_TIMESTAMP, timestamp);
+ return newResult;
+ }
+
+ mCachedRequest = legacyRequest;
+ mCachedResult = convertResultMetadata(mCachedRequest, timestamp);
+ return mCachedResult;
+ }
+
/**
* Generate capture result metadata from the legacy camera request.
*
diff --git a/core/java/android/hardware/camera2/legacy/RequestHolder.java b/core/java/android/hardware/camera2/legacy/RequestHolder.java
index e674736..9f27093 100644
--- a/core/java/android/hardware/camera2/legacy/RequestHolder.java
+++ b/core/java/android/hardware/camera2/legacy/RequestHolder.java
@@ -23,6 +23,8 @@
import java.util.Collection;
+import static com.android.internal.util.Preconditions.*;
+
/**
* Immutable container for a single capture request and associated information.
*/
@@ -34,14 +36,131 @@
private final int mRequestId;
private final int mSubsequeceId;
private final long mFrameNumber;
+ private final boolean mHasJpegTargets;
+ private final boolean mHasPreviewTargets;
- RequestHolder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating,
- long frameNumber) {
+ /**
+ * Returns true if the given surface requires jpeg buffers.
+ *
+ * @param s a {@link android.view.Surface} to check.
+ * @return true if the surface requires a jpeg buffer.
+ */
+ public static boolean jpegType(Surface s)
+ throws LegacyExceptionUtils.BufferQueueAbandonedException {
+ return LegacyCameraDevice.detectSurfaceType(s) ==
+ CameraMetadataNative.NATIVE_JPEG_FORMAT;
+ }
+
+ /**
+ * Returns true if the given surface requires non-jpeg buffer types.
+ *
+ * <p>
+ * "Jpeg buffer" refers to the buffers returned in the jpeg
+ * {@link android.hardware.Camera.PictureCallback}. Non-jpeg buffers are created using a tee
+ * of the preview stream drawn to the surface
+ * set via {@link android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)} or
+ * equivalent methods.
+ * </p>
+ * @param s a {@link android.view.Surface} to check.
+ * @return true if the surface requires a non-jpeg buffer type.
+ */
+ public static boolean previewType(Surface s)
+ throws LegacyExceptionUtils.BufferQueueAbandonedException {
+ return LegacyCameraDevice.detectSurfaceType(s) !=
+ CameraMetadataNative.NATIVE_JPEG_FORMAT;
+ }
+
+ /**
+ * Returns true if any of the surfaces targeted by the contained request require jpeg buffers.
+ */
+ private static boolean requestContainsJpegTargets(CaptureRequest request) {
+ for (Surface s : request.getTargets()) {
+ try {
+ if (jpegType(s)) {
+ return true;
+ }
+ } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+ Log.w(TAG, "Surface abandoned, skipping...", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if any of the surfaces targeted by the contained request require a
+ * non-jpeg buffer type.
+ */
+ private static boolean requestContainsPreviewTargets(CaptureRequest request) {
+ for (Surface s : request.getTargets()) {
+ try {
+ if (previewType(s)) {
+ return true;
+ }
+ } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+ Log.w(TAG, "Surface abandoned, skipping...", e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A builder class for {@link RequestHolder} objects.
+ *
+ * <p>
+ * This allows per-request queries to be cached for repeating {@link CaptureRequest} objects.
+ * </p>
+ */
+ public final static class Builder {
+ private final int mRequestId;
+ private final int mSubsequenceId;
+ private final CaptureRequest mRequest;
+ private final boolean mRepeating;
+ private final boolean mHasJpegTargets;
+ private final boolean mHasPreviewTargets;
+
+ /**
+ * Construct a new {@link Builder} to generate {@link RequestHolder} objects.
+ *
+ * @param requestId the ID to set in {@link RequestHolder} objects.
+ * @param subsequenceId the sequence ID to set in {@link RequestHolder} objects.
+ * @param request the original {@link CaptureRequest} to set in {@link RequestHolder}
+ * objects.
+ * @param repeating {@code true} if the request is repeating.
+ */
+ public Builder(int requestId, int subsequenceId, CaptureRequest request,
+ boolean repeating) {
+ checkNotNull(request, "request must not be null");
+ mRequestId = requestId;
+ mSubsequenceId = subsequenceId;
+ mRequest = request;
+ mRepeating = repeating;
+ mHasJpegTargets = requestContainsJpegTargets(mRequest);
+ mHasPreviewTargets = requestContainsPreviewTargets(mRequest);
+ }
+
+ /**
+ * Build a new {@link RequestHolder} using with parameters generated from this
+ * {@link Builder}.
+ *
+ * @param frameNumber the {@code framenumber} to generate in the {@link RequestHolder}.
+ * @return a {@link RequestHolder} constructed with the {@link Builder}'s parameters.
+ */
+ public RequestHolder build(long frameNumber) {
+ return new RequestHolder(mRequestId, mSubsequenceId, mRequest, mRepeating, frameNumber,
+ mHasJpegTargets, mHasPreviewTargets);
+ }
+ }
+
+ private RequestHolder(int requestId, int subsequenceId, CaptureRequest request,
+ boolean repeating, long frameNumber, boolean hasJpegTargets,
+ boolean hasPreviewTargets) {
mRepeating = repeating;
mRequest = request;
mRequestId = requestId;
mSubsequeceId = subsequenceId;
mFrameNumber = frameNumber;
+ mHasJpegTargets = hasJpegTargets;
+ mHasPreviewTargets = hasPreviewTargets;
}
/**
@@ -90,86 +209,15 @@
* Returns true if any of the surfaces targeted by the contained request require jpeg buffers.
*/
public boolean hasJpegTargets() {
- for (Surface s : getHolderTargets()) {
- try {
- if (jpegType(s)) {
- return true;
- }
- } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
- Log.w(TAG, "Surface abandoned, skipping...", e);
- }
- }
- return false;
+ return mHasJpegTargets;
}
/**
* Returns true if any of the surfaces targeted by the contained request require a
* non-jpeg buffer type.
*/
- public boolean hasPreviewTargets() {
- for (Surface s : getHolderTargets()) {
- try {
- if (previewType(s)) {
- return true;
- }
- } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
- Log.w(TAG, "Surface abandoned, skipping...", e);
- }
- }
- return false;
+ public boolean hasPreviewTargets(){
+ return mHasPreviewTargets;
}
- /**
- * Return the first surface targeted by the contained request that requires a
- * non-jpeg buffer type.
- */
- public Surface getFirstPreviewTarget() {
- for (Surface s : getHolderTargets()) {
- try {
- if (previewType(s)) {
- return s;
- }
- } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
- Log.w(TAG, "Surface abandoned, skipping...", e);
- }
- }
- return null;
- }
-
- /**
- * Returns true if the given surface requires jpeg buffers.
- *
- * @param s a {@link Surface} to check.
- * @return true if the surface requires a jpeg buffer.
- */
- public static boolean jpegType(Surface s)
- throws LegacyExceptionUtils.BufferQueueAbandonedException {
- if (LegacyCameraDevice.detectSurfaceType(s) ==
- CameraMetadataNative.NATIVE_JPEG_FORMAT) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns true if the given surface requires non-jpeg buffer types.
- *
- * <p>
- * "Jpeg buffer" refers to the buffers returned in the jpeg
- * {@link android.hardware.Camera.PictureCallback}. Non-jpeg buffers are created using a tee
- * of the preview stream drawn to the surface
- * set via {@link android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)} or
- * equivalent methods.
- * </p>
- * @param s a {@link Surface} to check.
- * @return true if the surface requires a non-jpeg buffer type.
- */
- public static boolean previewType(Surface s)
- throws LegacyExceptionUtils.BufferQueueAbandonedException {
- if (LegacyCameraDevice.detectSurfaceType(s) !=
- CameraMetadataNative.NATIVE_JPEG_FORMAT) {
- return true;
- }
- return false;
- }
}
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index e6d84c5..cc7a90eb 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -207,15 +207,17 @@
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
RequestHolder holder = mInFlightPreview;
+
+ if (DEBUG) {
+ mPrevCounter.countAndLog();
+ }
+
if (holder == null) {
mGLThreadManager.queueNewFrame(null);
Log.w(TAG, "Dropping preview frame.");
return;
}
- if (DEBUG) {
- mPrevCounter.countAndLog();
- }
mInFlightPreview = null;
if (holder.hasPreviewTargets()) {
@@ -278,7 +280,6 @@
startPreview();
}
-
private void configureOutputs(Collection<Surface> outputs) throws IOException {
stopPreview();
if (mGLThreadManager != null) {
@@ -292,10 +293,13 @@
mInFlightPreview = null;
mInFlightJpeg = null;
+ int facing = mCharacteristics.get(CameraCharacteristics.LENS_FACING);
+ int orientation = mCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
if (outputs != null) {
for (Surface s : outputs) {
try {
int format = LegacyCameraDevice.detectSurfaceType(s);
+ LegacyCameraDevice.setSurfaceOrientation(s, facing, orientation);
switch (format) {
case CameraMetadataNative.NATIVE_JPEG_FORMAT:
mCallbackOutputs.add(s);
@@ -392,6 +396,7 @@
mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback);
}
+ mCamera.setParameters(mParams);
// TODO: configure the JPEG surface with some arbitrary size
// using LegacyCameraDevice.nativeConfigureSurface
}
@@ -527,6 +532,7 @@
private final Handler.Callback mRequestHandlerCb = new Handler.Callback() {
private boolean mCleanup = false;
+ private LegacyResultMapper mMapper = new LegacyResultMapper();
@Override
public boolean handleMessage(Message msg) {
@@ -537,6 +543,10 @@
if (DEBUG) {
Log.d(TAG, "Request thread handling message:" + msg.what);
}
+ long startTime = 0;
+ if (DEBUG) {
+ startTime = SystemClock.elapsedRealtimeNanos();
+ }
switch (msg.what) {
case MSG_CONFIGURE_OUTPUTS:
ConfigureHolder config = (ConfigureHolder) msg.obj;
@@ -550,6 +560,10 @@
throw new IOError(e);
}
config.condition.open();
+ if (DEBUG) {
+ long totalTime = SystemClock.elapsedRealtimeNanos() - startTime;
+ Log.d(TAG, "Configure took " + totalTime + " ns");
+ }
break;
case MSG_SUBMIT_CAPTURE_REQUEST:
Handler handler = RequestThreadManager.this.mRequestThread.getHandler();
@@ -570,6 +584,8 @@
nextBurst.first.produceRequestHolders(nextBurst.second);
for (RequestHolder holder : requests) {
CaptureRequest request = holder.getRequest();
+
+ boolean paramsChanged = false;
if (mLastRequest == null || mLastRequest.captureRequest != request) {
// The intermediate buffer is sometimes null, but we always need
@@ -584,9 +600,13 @@
// Parameters are mutated as a side-effect
LegacyMetadataMapper.convertRequestMetadata(/*inout*/legacyRequest);
- mParams = legacyRequest.parameters;
- mCamera.setParameters(mParams);
+ if (!mParams.same(legacyRequest.parameters)) {
+ mParams = legacyRequest.parameters;
+ mCamera.setParameters(mParams);
+ paramsChanged = true;
+ }
}
+
mDeviceState.setCaptureStart(holder);
long timestamp = 0;
try {
@@ -613,16 +633,29 @@
// TODO: err handling
throw new IOError(e);
}
+
if (timestamp == 0) {
timestamp = SystemClock.elapsedRealtimeNanos();
}
- // Update parameters to the latest that we think the camera is using
- mLastRequest.setParameters(mCamera.getParameters());
- CameraMetadataNative result =
- LegacyResultMapper.convertResultMetadata(mLastRequest, timestamp);
+
+ if (paramsChanged) {
+ if (DEBUG) {
+ Log.d(TAG, "Params changed -- getting new Parameters from HAL.");
+ }
+ mParams = mCamera.getParameters();
+
+ // Update parameters to the latest that we think the camera is using
+ mLastRequest.setParameters(mParams);
+ }
+
+
+ CameraMetadataNative result = mMapper.cachedConvertResultMetadata(
+ mLastRequest, timestamp);
mDeviceState.setCaptureResult(holder, result);
}
if (DEBUG) {
+ long totalTime = SystemClock.elapsedRealtimeNanos() - startTime;
+ Log.d(TAG, "Capture request took " + totalTime + " ns");
mRequestCounter.countAndLog();
}
break;
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
index daa64c0..fdf9ba0 100644
--- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -1,18 +1,18 @@
/*
-* 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.
-*/
+ * 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.
+ */
package android.hardware.camera2.legacy;
import android.graphics.ImageFormat;
@@ -98,14 +98,14 @@
*/
private static final String VERTEX_SHADER =
"uniform mat4 uMVPMatrix;\n" +
- "uniform mat4 uSTMatrix;\n" +
- "attribute vec4 aPosition;\n" +
- "attribute vec4 aTextureCoord;\n" +
- "varying vec2 vTextureCoord;\n" +
- "void main() {\n" +
- " gl_Position = uMVPMatrix * aPosition;\n" +
- " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
- "}\n";
+ "uniform mat4 uSTMatrix;\n" +
+ "attribute vec4 aPosition;\n" +
+ "attribute vec4 aTextureCoord;\n" +
+ "varying vec2 vTextureCoord;\n" +
+ "void main() {\n" +
+ " gl_Position = uMVPMatrix * aPosition;\n" +
+ " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
+ "}\n";
/**
* This fragment shader simply draws the color in the 2D texture at
@@ -113,12 +113,12 @@
*/
private static final String FRAGMENT_SHADER =
"#extension GL_OES_EGL_image_external : require\n" +
- "precision mediump float;\n" +
- "varying vec2 vTextureCoord;\n" +
- "uniform samplerExternalOES sTexture;\n" +
- "void main() {\n" +
- " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
- "}\n";
+ "precision mediump float;\n" +
+ "varying vec2 vTextureCoord;\n" +
+ "uniform samplerExternalOES sTexture;\n" +
+ "void main() {\n" +
+ " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
+ "}\n";
private float[] mMVPMatrix = new float[GL_MATRIX_SIZE];
private float[] mSTMatrix = new float[GL_MATRIX_SIZE];
@@ -189,12 +189,56 @@
return program;
}
- private void drawFrame(SurfaceTexture st) {
+ private void drawFrame(SurfaceTexture st, int width, int height) {
checkGlError("onDrawFrame start");
st.getTransformMatrix(mSTMatrix);
+ Size dimens;
+ try {
+ dimens = LegacyCameraDevice.getTextureSize(st);
+ } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
+ // Should never hit this.
+ throw new IllegalStateException("Surface abandoned, skipping drawFrame...", e);
+ }
+
+ Matrix.setIdentityM(mMVPMatrix, /*smOffset*/0);
+
+ float texWidth = dimens.getWidth();
+ float texHeight = dimens.getHeight();
+
+ if (texWidth <= 0 || texHeight <= 0) {
+ throw new IllegalStateException("Illegal intermediate texture with dimension of 0");
+ }
+
+ // Find largest scaling factor from the intermediate texture dimension to the
+ // output surface dimension. Scaling the intermediate texture by this allows
+ // us to letterbox/pillerbox the output surface into the intermediate texture.
+ float widthRatio = width / texWidth;
+ float heightRatio = height / texHeight;
+ float actual = (widthRatio < heightRatio) ? heightRatio : widthRatio;
+
if (DEBUG) {
- GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ Log.d(TAG, "Scaling factor " + actual + " used for " + width + "x" + height +
+ " surface, intermediate buffer size is " + texWidth + "x" + texHeight);
+ }
+
+ // Set the viewport height and width to be the scaled intermediate texture dimensions.
+ int viewportW = (int) (actual * texWidth);
+ int viewportH = (int) (actual * texHeight);
+
+ // Set the offset of the viewport so that the output surface is centered in the viewport.
+ float dx = (width - viewportW) / 2f;
+ float dy = (height - viewportH) / 2f;
+
+ if (DEBUG) {
+ Log.d(TAG, "Translation " + dx + "," + dy + " used for " + width + "x" + height +
+ " surface");
+ }
+
+ GLES20.glViewport((int) dx, (int) dy, viewportW, viewportH);
+
+ if (DEBUG) {
+ GLES20.glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
}
@@ -218,7 +262,6 @@
GLES20.glEnableVertexAttribArray(maTextureHandle);
checkGlError("glEnableVertexAttribArray maTextureHandle");
- Matrix.setIdentityM(mMVPMatrix, 0);
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, /*count*/ 1, /*transpose*/ false, mMVPMatrix,
/*offset*/ 0);
GLES20.glUniformMatrix4fv(muSTMatrixHandle, /*count*/ 1, /*transpose*/ false, mSTMatrix,
@@ -589,18 +632,19 @@
for (EGLSurfaceHolder holder : mSurfaces) {
if (LegacyCameraDevice.containsSurfaceId(holder.surface, targetSurfaceIds)) {
makeCurrent(holder.eglSurface);
- drawFrame(mSurfaceTexture);
+ drawFrame(mSurfaceTexture, holder.width, holder.height);
swapBuffers(holder.eglSurface);
}
}
for (EGLSurfaceHolder holder : mConversionSurfaces) {
if (LegacyCameraDevice.containsSurfaceId(holder.surface, targetSurfaceIds)) {
makeCurrent(holder.eglSurface);
- drawFrame(mSurfaceTexture);
+ drawFrame(mSurfaceTexture, holder.width, holder.height);
mPBufferPixels.clear();
- GLES20.glReadPixels(/*x*/ 0, /*y*/ 0, holder.width, holder.height, GLES20.GL_RGBA,
- GLES20.GL_UNSIGNED_BYTE, mPBufferPixels);
+ GLES20.glReadPixels(/*x*/ 0, /*y*/ 0, holder.width, holder.height,
+ GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, mPBufferPixels);
checkGlError("glReadPixels");
+
try {
int format = LegacyCameraDevice.detectSurfaceType(holder.surface);
LegacyCameraDevice.produceFrame(holder.surface, mPBufferPixels.array(),
diff --git a/core/java/android/hardware/camera2/marshal/MarshalRegistry.java b/core/java/android/hardware/camera2/marshal/MarshalRegistry.java
index 92d9057..ba821e4 100644
--- a/core/java/android/hardware/camera2/marshal/MarshalRegistry.java
+++ b/core/java/android/hardware/camera2/marshal/MarshalRegistry.java
@@ -81,17 +81,18 @@
break;
}
}
- }
- if (marshaler == null) {
- throw new UnsupportedOperationException(
- "Could not find marshaler that matches the requested " +
- "combination of type reference " +
- typeToken + " and native type " +
- MarshalHelpers.toStringNativeType(nativeType));
- }
+ if (marshaler == null) {
+ throw new UnsupportedOperationException(
+ "Could not find marshaler that matches the requested " +
+ "combination of type reference " +
+ typeToken + " and native type " +
+ MarshalHelpers.toStringNativeType(nativeType));
+ }
- sMarshalerMap.put(marshalToken, marshaler);
+ // Only put when no cached version exists to avoid +0.5ms lookup per call.
+ sMarshalerMap.put(marshalToken, marshaler);
+ }
return marshaler;
}
@@ -100,10 +101,12 @@
public MarshalToken(TypeReference<T> typeReference, int nativeType) {
this.typeReference = typeReference;
this.nativeType = nativeType;
+ this.hash = typeReference.hashCode() ^ nativeType;
}
final TypeReference<T> typeReference;
final int nativeType;
+ private final int hash;
@Override
public boolean equals(Object other) {
@@ -118,7 +121,7 @@
@Override
public int hashCode() {
- return typeReference.hashCode() ^ nativeType;
+ return hash;
}
}
diff --git a/core/java/android/hardware/camera2/package.html b/core/java/android/hardware/camera2/package.html
index ef0d7bd..719c2f6 100644
--- a/core/java/android/hardware/camera2/package.html
+++ b/core/java/android/hardware/camera2/package.html
@@ -58,16 +58,16 @@
<p>Generally, camera preview images are sent to {@link
android.view.SurfaceView} or {@link android.view.TextureView} (via its
{@link android.graphics.SurfaceTexture}). Capture of JPEG images or
-RAW buffers for {@link android.hardware.camera2.DngCreator} can be done
-with {@link android.media.ImageReader} with the
-{android.graphics.ImageFormat#JPEG} and
-{android.graphics.ImageFormat#RAW_SENSOR} formats. Application-driven
+RAW buffers for {@link android.hardware.camera2.DngCreator} can be
+done with {@link android.media.ImageReader} with the {@link
+android.graphics.ImageFormat#JPEG} and {@link
+android.graphics.ImageFormat#RAW_SENSOR} formats. Application-driven
processing of camera data in RenderScript, OpenGL ES, or directly in
managed or native code is best done through {@link
android.renderscript.Allocation} with a YUV {@link
android.renderscript.Type}, {@link android.graphics.SurfaceTexture},
-and {@link android.media.ImageReader} with a
-{android.graphics.ImageFormat#YUV_420_888} format, respectively.</p>
+and {@link android.media.ImageReader} with a {@link
+android.graphics.ImageFormat#YUV_420_888} format, respectively.</p>
<p>The application then needs to construct a {@link
android.hardware.camera2.CaptureRequest}, which defines all the
diff --git a/core/java/android/hardware/camera2/utils/CloseableLock.java b/core/java/android/hardware/camera2/utils/CloseableLock.java
index af55055..9ac89c8 100644
--- a/core/java/android/hardware/camera2/utils/CloseableLock.java
+++ b/core/java/android/hardware/camera2/utils/CloseableLock.java
@@ -110,7 +110,9 @@
@Override
public void close() {
if (mClosed) {
- log("close - already closed; ignoring");
+ if (VERBOSE) {
+ log("close - already closed; ignoring");
+ }
return;
}
@@ -139,7 +141,9 @@
mLock.unlock();
}
- log("close - completed");
+ if (VERBOSE) {
+ log("close - completed");
+ }
}
/**
@@ -169,7 +173,9 @@
// Lock is already closed, all further acquisitions will fail
if (mClosed) {
- log("acquire lock early aborted (already closed)");
+ if (VERBOSE) {
+ log("acquire lock early aborted (already closed)");
+ }
return null;
}
@@ -187,7 +193,9 @@
// Did another thread #close while we were waiting? Unblock immediately.
if (mClosed) {
- log("acquire lock unblocked aborted (already closed)");
+ if (VERBOSE) {
+ log("acquire lock unblocked aborted (already closed)");
+ }
return null;
}
}
@@ -200,7 +208,9 @@
mLock.unlock();
}
- log("acquired lock (local own count = " + ownedLocks + "");
+ if (VERBOSE) {
+ log("acquired lock (local own count = " + ownedLocks + ")");
+ }
return new ScopedLock();
}
@@ -231,7 +241,9 @@
// Lock is already closed, all further acquisitions will fail
if (mClosed) {
- log("acquire exclusive lock early aborted (already closed)");
+ if (VERBOSE) {
+ log("acquire exclusive lock early aborted (already closed)");
+ }
return null;
}
@@ -254,7 +266,9 @@
// Did another thread #close while we were waiting? Unblock immediately.
if (mClosed) {
- log("acquire exclusive lock unblocked aborted (already closed)");
+ if (VERBOSE) {
+ log("acquire exclusive lock unblocked aborted (already closed)");
+ }
return null;
}
}
@@ -267,7 +281,9 @@
mLock.unlock();
}
- log("acquired exclusive lock (local own count = " + ownedLocks + "");
+ if (VERBOSE) {
+ log("acquired exclusive lock (local own count = " + ownedLocks + ")");
+ }
return new ScopedLock();
}
@@ -318,13 +334,13 @@
mLock.unlock();
}
- log("released lock (local lock count " + ownedLocks + ")");
+ if (VERBOSE) {
+ log("released lock (local lock count " + ownedLocks + ")");
+ }
}
private void log(String what) {
- if (VERBOSE) {
- Log.v(TAG + "[" + mName + "]", what);
- }
+ Log.v(TAG + "[" + mName + "]", what);
}
}
diff --git a/core/java/android/hardware/camera2/utils/TypeReference.java b/core/java/android/hardware/camera2/utils/TypeReference.java
index d0c919c..24ce124 100644
--- a/core/java/android/hardware/camera2/utils/TypeReference.java
+++ b/core/java/android/hardware/camera2/utils/TypeReference.java
@@ -46,6 +46,7 @@
*/
public abstract class TypeReference<T> {
private final Type mType;
+ private final int mHash;
/**
* Create a new type reference for {@code T}.
@@ -73,6 +74,7 @@
throw new IllegalArgumentException(
"Including a type variable in a type reference is not allowed");
}
+ mHash = mType.hashCode();
}
/**
@@ -84,11 +86,11 @@
private TypeReference(Type type) {
mType = type;
-
if (containsTypeVariable(mType)) {
throw new IllegalArgumentException(
"Including a type variable in a type reference is not allowed");
}
+ mHash = mType.hashCode();
}
private static class SpecializedTypeReference<T> extends TypeReference<T> {
@@ -249,7 +251,7 @@
*/
@Override
public int hashCode() {
- return mType.hashCode();
+ return mHash;
}
/**
diff --git a/core/java/android/hardware/soundtrigger/Keyphrase.java b/core/java/android/hardware/soundtrigger/Keyphrase.java
index 42fd350..51311bb 100644
--- a/core/java/android/hardware/soundtrigger/Keyphrase.java
+++ b/core/java/android/hardware/soundtrigger/Keyphrase.java
@@ -30,7 +30,11 @@
/** A hint text to display corresponding to this keyphrase, e.g. "Hello There". */
public final String hintText;
/** The locale of interest when using this Keyphrase. */
- public String locale;
+ public final String locale;
+ /** The various recognition modes supported by this keyphrase */
+ public final int recognitionModeFlags;
+ /** The users associated with this keyphrase */
+ public final int[] users;
public static final Parcelable.Creator<Keyphrase> CREATOR
= new Parcelable.Creator<Keyphrase>() {
@@ -44,13 +48,26 @@
};
private static Keyphrase fromParcel(Parcel in) {
- return new Keyphrase(in.readInt(), in.readString(), in.readString());
+ int id = in.readInt();
+ String hintText = in.readString();
+ String locale = in.readString();
+ int recognitionModeFlags = in.readInt();
+ int numUsers = in.readInt();
+ int[] users = null;
+ if (numUsers > 0) {
+ users = new int[numUsers];
+ in.readIntArray(users);
+ }
+ return new Keyphrase(id, hintText, locale, recognitionModeFlags, users);
}
- public Keyphrase(int id, String hintText, String locale) {
+ public Keyphrase(int id, String hintText, String locale, int recognitionModeFlags,
+ int[] users) {
this.id = id;
this.hintText = hintText;
this.locale = locale;
+ this.recognitionModeFlags = recognitionModeFlags;
+ this.users = users;
}
@Override
@@ -58,6 +75,13 @@
dest.writeInt(id);
dest.writeString(hintText);
dest.writeString(locale);
+ dest.writeInt(recognitionModeFlags);
+ if (users != null) {
+ dest.writeInt(users.length);
+ dest.writeIntArray(users);
+ } else {
+ dest.writeInt(0);
+ }
}
@Override
@@ -98,4 +122,14 @@
return false;
return true;
}
+
+ @Override
+ public String toString() {
+ return "Keyphrase[id=" + id + ", text=" + hintText + ", locale=" + locale
+ + ", recognitionModes=" + recognitionModeFlags + "]";
+ }
+
+ protected SoundTrigger.Keyphrase convertToSoundTriggerKeyphrase() {
+ return new SoundTrigger.Keyphrase(id, recognitionModeFlags, locale, hintText, users);
+ }
}
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
index 2f5de6a..2e96487 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseEnrollmentInfo.java
@@ -156,6 +156,9 @@
if (searchKeyphraseId != -1) {
String searchKeyphrase = array.getString(com.android.internal.R.styleable
.VoiceEnrollmentApplication_searchKeyphrase);
+ if (searchKeyphrase == null) {
+ searchKeyphrase = "";
+ }
String searchKeyphraseSupportedLocales =
array.getString(com.android.internal.R.styleable
.VoiceEnrollmentApplication_searchKeyphraseSupportedLocales);
@@ -165,9 +168,11 @@
&& !searchKeyphraseSupportedLocales.isEmpty()) {
supportedLocales = searchKeyphraseSupportedLocales.split(",");
}
+ int recognitionModes = array.getInt(com.android.internal.R.styleable
+ .VoiceEnrollmentApplication_searchKeyphraseRecognitionFlags, 0);
mKeyphrases = new KeyphraseMetadata[1];
mKeyphrases[0] = new KeyphraseMetadata(
- searchKeyphraseId, searchKeyphrase, supportedLocales);
+ searchKeyphraseId, searchKeyphrase, supportedLocales, recognitionModes);
} else {
mParseError = "searchKeyphraseId not specified in meta-data";
return;
@@ -239,7 +244,8 @@
* @param keyphrase The keyphrase that the user needs to be enrolled to.
* @param locale The locale for which the enrollment needs to be performed.
* This is a Java locale, for example "en_US".
- * @return true, if an enrollment client supports the given keyphrase and the given locale.
+ * @return The metadata, if the enrollment client supports the given keyphrase
+ * and locale, null otherwise.
*/
public KeyphraseMetadata getKeyphraseMetadata(String keyphrase, String locale) {
if (mKeyphrases == null || mKeyphrases.length == 0) {
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
index 03a4939..38305f9 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseMetadata.java
@@ -27,34 +27,36 @@
public final int id;
public final String keyphrase;
public final ArraySet<String> supportedLocales;
+ public final int recognitionModeFlags;
- public KeyphraseMetadata(int id, String keyphrase, String[] supportedLocales) {
+ public KeyphraseMetadata(int id, String keyphrase, String[] supportedLocales,
+ int recognitionModeFlags) {
this.id = id;
this.keyphrase = keyphrase;
this.supportedLocales = new ArraySet<String>(supportedLocales.length);
for (String locale : supportedLocales) {
this.supportedLocales.add(locale);
}
+ this.recognitionModeFlags = recognitionModeFlags;
}
@Override
public String toString() {
- return "id=" + id + ", keyphrase=" + keyphrase + ", supported-locales=" + supportedLocales;
+ return "id=" + id + ", keyphrase=" + keyphrase + ", supported-locales=" + supportedLocales
+ + ", recognition-modes=" + recognitionModeFlags;
}
/**
* @return Indicates if we support the given phrase.
*/
public boolean supportsPhrase(String phrase) {
- // TODO(sansid): Come up with a scheme for custom keyphrases that should always match.
- return keyphrase.equalsIgnoreCase(phrase);
+ return keyphrase.isEmpty() || keyphrase.equalsIgnoreCase(phrase);
}
/**
* @return Indicates if we support the given locale.
*/
public boolean supportsLocale(String locale) {
- // TODO(sansid): Come up with a scheme for keyphrases that are available in all locales.
- return supportedLocales.contains(locale);
+ return supportedLocales.isEmpty() || supportedLocales.contains(locale);
}
}
diff --git a/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java b/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java
index 4ddba6a..a5ab0d2 100644
--- a/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java
+++ b/core/java/android/hardware/soundtrigger/KeyphraseSoundModel.java
@@ -65,4 +65,15 @@
}
dest.writeParcelableArray(keyphrases, 0);
}
+
+ public SoundTrigger.KeyphraseSoundModel convertToSoundTriggerKeyphraseSoundModel() {
+ SoundTrigger.Keyphrase[] stKeyphrases = null;
+ if (keyphrases != null) {
+ stKeyphrases = new SoundTrigger.Keyphrase[keyphrases.length];
+ for (int i = 0; i < keyphrases.length; i++) {
+ stKeyphrases[i] = keyphrases[i].convertToSoundTriggerKeyphrase();
+ }
+ }
+ return new SoundTrigger.KeyphraseSoundModel(uuid, data, stKeyphrases);
+ }
}
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java b/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java
index 0be068d..431d550 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerHelper.java
@@ -17,6 +17,7 @@
package android.hardware.soundtrigger;
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
import android.util.Slog;
import android.util.SparseArray;
@@ -56,7 +57,7 @@
private final ModuleProperties mModuleProperties;
private final SoundTriggerModule mModule;
- private final SparseArray<Listener> mListeners;
+ private final SparseArray<Listener> mActiveListeners;
private int mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
@@ -64,8 +65,12 @@
* The callback for sound trigger events.
*/
public interface Listener {
- /** Called when the given keyphrase is spoken. */
- void onKeyphraseSpoken();
+ /**
+ * Called when the given keyphrase is spoken.
+ *
+ * @param data The captured audio, may be null.
+ */
+ void onKeyphraseSpoken(byte[] data);
/**
* Called when the listening state for the given keyphrase changes.
@@ -77,9 +82,9 @@
public SoundTriggerHelper() {
ArrayList <ModuleProperties> modules = new ArrayList<>();
int status = SoundTrigger.listModules(modules);
- mListeners = new SparseArray<>(1);
+ mActiveListeners = new SparseArray<>(1);
if (status != SoundTrigger.STATUS_OK || modules.size() == 0) {
- // TODO: Figure out how to handle errors in listing the modules here.
+ Slog.w(TAG, "listModules status=" + status + ", # of modules=" + modules.size());
dspInfo = null;
mModuleProperties = null;
mModule = null;
@@ -94,29 +99,14 @@
}
/**
- * @return True, if the given {@link Keyphrase} is supported on DSP.
- */
- public boolean isKeyphraseSupported(Keyphrase keyphrase) {
- // TODO: We also need to look into a SoundTrigger API that let's us
- // query this. For now just return true.
- return true;
- }
-
- /**
- * @return True, if the given {@link Keyphrase} has been enrolled.
- */
- public boolean isKeyphraseEnrolled(Keyphrase keyphrase) {
- // TODO: Query VoiceInteractionManagerService
- // to list registered sound models.
- return false;
- }
-
- /**
* @return True, if a recognition for the given {@link Keyphrase} is active.
*/
- public boolean isKeyphraseActive(Keyphrase keyphrase) {
- // TODO: Check if the recognition for the keyphrase is currently active.
- return false;
+ public synchronized boolean isKeyphraseActive(Keyphrase keyphrase) {
+ if (keyphrase == null) {
+ Slog.w(TAG, "isKeyphraseActive requires a non-null keyphrase");
+ return false;
+ }
+ return mActiveListeners.get(keyphrase.id) != null;
}
/**
@@ -124,55 +114,98 @@
*
* @param keyphraseId The identifier of the keyphrase for which
* the recognition is to be started.
+ * @param soundModel The sound model to use for recognition.
* @param listener The listener for the recognition events related to the given keyphrase.
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- public int startRecognition(int keyphraseId, Listener listener) {
+ public synchronized int startRecognition(int keyphraseId,
+ SoundTrigger.KeyphraseSoundModel soundModel,
+ Listener listener, RecognitionConfig recognitionConfig) {
if (dspInfo == null || mModule == null) {
Slog.w(TAG, "Attempting startRecognition without the capability");
return STATUS_ERROR;
}
- if (mListeners.get(keyphraseId) != listener) {
+ Listener oldListener = mActiveListeners.get(keyphraseId);
+ if (oldListener != null && oldListener != listener) {
if (mCurrentSoundModelHandle != INVALID_SOUND_MODEL_HANDLE) {
Slog.w(TAG, "Canceling previous recognition");
// TODO: Inspect the return codes here.
mModule.unloadSoundModel(mCurrentSoundModelHandle);
}
- mListeners.get(keyphraseId).onListeningStateChanged(STATE_STOPPED);
+ mActiveListeners.get(keyphraseId).onListeningStateChanged(STATE_STOPPED);
+ mActiveListeners.remove(keyphraseId);
}
+ int[] handle = new int[] { INVALID_SOUND_MODEL_HANDLE };
+ int status = mModule.loadSoundModel(soundModel, handle);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "loadSoundModel call failed with " + status);
+ return STATUS_ERROR;
+ }
+ if (handle[0] == INVALID_SOUND_MODEL_HANDLE) {
+ Slog.w(TAG, "loadSoundModel call returned invalid sound model handle");
+ return STATUS_ERROR;
+ }
+
+ // Start the recognition.
+ status = mModule.startRecognition(handle[0], recognitionConfig);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "startRecognition failed with " + status);
+ return STATUS_ERROR;
+ }
+
+ // Everything went well!
+ mCurrentSoundModelHandle = handle[0];
// Register the new listener. This replaces the old one.
// There can only be a maximum of one active listener for a keyphrase
// at any given time.
- mListeners.put(keyphraseId, listener);
- // TODO: Get the sound model for the given keyphrase here.
- // mModule.loadSoundModel(model, soundModelHandle);
- // mModule.startRecognition(soundModelHandle, data);
- // mCurrentSoundModelHandle = soundModelHandle;
- return STATUS_ERROR;
+ mActiveListeners.put(keyphraseId, listener);
+ return STATUS_OK;
}
/**
* Stops recognition for the given {@link Keyphrase} if a recognition is currently active.
*
+ * @param keyphraseId The identifier of the keyphrase for which
+ * the recognition is to be stopped.
+ * @param listener The listener for the recognition events related to the given keyphrase.
+ *
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
*/
- public int stopRecognition(int id, Listener listener) {
+ public synchronized int stopRecognition(int keyphraseId, Listener listener) {
if (dspInfo == null || mModule == null) {
Slog.w(TAG, "Attempting stopRecognition without the capability");
return STATUS_ERROR;
}
- if (mListeners.get(id) != listener) {
+ Listener currentListener = mActiveListeners.get(keyphraseId);
+ if (currentListener == null) {
+ // startRecognition hasn't been called or it failed.
+ Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition");
+ return STATUS_ERROR;
+ } else if (currentListener != listener) {
+ // TODO: Figure out if this should match the listener that was passed in during
+ // startRecognition, or should we allow a different listener to stop the recognition,
+ // in which case we don't need to pass in a listener here.
Slog.w(TAG, "Attempting stopRecognition for another recognition");
return STATUS_ERROR;
} else {
// Stop recognition if it's the current one, ignore otherwise.
// TODO: Inspect the return codes here.
- mModule.stopRecognition(mCurrentSoundModelHandle);
- mModule.unloadSoundModel(mCurrentSoundModelHandle);
+ int status = mModule.stopRecognition(mCurrentSoundModelHandle);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "stopRecognition call failed with " + status);
+ return STATUS_ERROR;
+ }
+ status = mModule.unloadSoundModel(mCurrentSoundModelHandle);
+ if (status != SoundTrigger.STATUS_OK) {
+ Slog.w(TAG, "unloadSoundModel call failed with " + status);
+ return STATUS_ERROR;
+ }
+
mCurrentSoundModelHandle = INVALID_SOUND_MODEL_HANDLE;
+ mActiveListeners.remove(keyphraseId);
return STATUS_OK;
}
}
@@ -184,28 +217,27 @@
// TODO: Get the keyphrase out of the event and fire events on it.
// For now, as a nasty workaround, we fire all events to the listener for
// keyphrase with TEMP_KEYPHRASE_ID.
+ Listener listener = null;
+ synchronized(this) {
+ // TODO: The keyphrase should come from the recognition event
+ // as it may be for a different keyphrase than the current one.
+ listener = mActiveListeners.get(TEMP_KEYPHRASE_ID);
+ }
+ if (listener == null) {
+ Slog.w(TAG, "received onRecognition event without any listener for it");
+ return;
+ }
switch (event.status) {
case SoundTrigger.RECOGNITION_STATUS_SUCCESS:
- // TODO: The keyphrase should come from the recognition event
- // as it may be for a different keyphrase than the current one.
- if (mListeners.get(TEMP_KEYPHRASE_ID) != null) {
- mListeners.get(TEMP_KEYPHRASE_ID).onKeyphraseSpoken();
- }
+ // TODO: Pass the captured audio back.
+ listener.onKeyphraseSpoken(null);
break;
case SoundTrigger.RECOGNITION_STATUS_ABORT:
- // TODO: The keyphrase should come from the recognition event
- // as it may be for a different keyphrase than the current one.
- if (mListeners.get(TEMP_KEYPHRASE_ID) != null) {
- mListeners.get(TEMP_KEYPHRASE_ID).onListeningStateChanged(STATE_STOPPED);
- }
+ listener.onListeningStateChanged(STATE_STOPPED);
break;
case SoundTrigger.RECOGNITION_STATUS_FAILURE:
- // TODO: The keyphrase should come from the recognition event
- // as it may be for a different keyphrase than the current one.
- if (mListeners.get(TEMP_KEYPHRASE_ID) != null) {
- mListeners.get(TEMP_KEYPHRASE_ID).onListeningStateChanged(STATE_STOPPED);
- }
+ listener.onListeningStateChanged(STATE_STOPPED);
break;
}
}
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
index bc19658..ffbc401 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -26,6 +27,7 @@
*
* @hide
*/
+@SystemApi
// NOTE: Ideally, we would abstract away the details of what identifies a network of a specific
// type, so that all networks appear the same and can be scored without concern to the network type
// itself. However, because no such cross-type identifier currently exists in the Android framework,
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index c599dfc..b497c6e 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkScorerAppManager.NetworkScorerAppData;
@@ -52,6 +53,7 @@
*
* @hide
*/
+@SystemApi
public class NetworkScoreManager {
/**
* Activity action: ask the user to change the active network scorer. This will show a dialog
diff --git a/core/java/android/net/PSKKeyManager.java b/core/java/android/net/PSKKeyManager.java
index 92dd141..e868c4f 100644
--- a/core/java/android/net/PSKKeyManager.java
+++ b/core/java/android/net/PSKKeyManager.java
@@ -81,19 +81,16 @@
* TLS-PSK in {@code SSLSocket}, {@code SSLServerSocket} and {@code SSLEngine} instances obtained
* from it.
* <pre> {@code
- * PSKKeyManager myPskKeyManager = ...;
+ * PSKKeyManager myPskKeyManager = ...;
*
* SSLContext sslContext = SSLContext.getInstance("TLS");
* sslContext.init(
* new KeyManager[] {myPskKeyManager},
- * new TrustManager[0], // No TrustManagers needed in TLS-PSK
+ * new TrustManager[0], // No TrustManagers needed for TLS-PSK
* null // Use the default source of entropy
* );
*
* SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(...);
- * // Enable a TLS-PSK cipher suite (no TLS-PSK cipher suites are enabled by default)
- * sslSocket.setEnabledCipherSuites(new String[] {"TLS_PSK_WITH_AES_128_CBC_SHA"});
- * sslSocket.startHandshake();
* }</pre>
*/
public interface PSKKeyManager extends com.android.org.conscrypt.PSKKeyManager {
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
index dd744d3..f653f37 100644
--- a/core/java/android/net/RssiCurve.java
+++ b/core/java/android/net/RssiCurve.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -49,6 +50,7 @@
* @see ScoredNetwork
* @hide
*/
+@SystemApi
public class RssiCurve implements Parcelable {
/** The starting dBm of the curve. */
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 7902313..2dfb061 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -26,6 +27,7 @@
*
* @hide
*/
+@SystemApi
public class ScoredNetwork implements Parcelable {
/** A {@link NetworkKey} uniquely identifying this network. */
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
index 9e92e89..71df2f9 100644
--- a/core/java/android/net/WifiKey.java
+++ b/core/java/android/net/WifiKey.java
@@ -16,6 +16,7 @@
package android.net;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,6 +29,7 @@
*
* @hide
*/
+@SystemApi
public class WifiKey implements Parcelable {
// Patterns used for validation.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index c22c4b6..aab7b1f 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -120,6 +120,16 @@
public static final int PROCESS_STATE = 12;
/**
+ * A constant indicating a sync timer
+ */
+ public static final int SYNC = 13;
+
+ /**
+ * A constant indicating a job timer
+ */
+ public static final int JOB = 14;
+
+ /**
* Include all of the data in the stats, including previously saved data.
*/
public static final int STATS_SINCE_CHARGED = 0;
@@ -142,7 +152,7 @@
/**
* Bump the version on this if the checkin format changes.
*/
- private static final int BATTERY_STATS_CHECKIN_VERSION = 8;
+ private static final int BATTERY_STATS_CHECKIN_VERSION = 9;
private static final long BYTES_PER_KB = 1024;
private static final long BYTES_PER_MB = 1048576; // 1024^2
@@ -157,6 +167,8 @@
private static final String FOREGROUND_DATA = "fg";
private static final String STATE_TIME_DATA = "st";
private static final String WAKELOCK_DATA = "wl";
+ private static final String SYNC_DATA = "sy";
+ private static final String JOB_DATA = "jb";
private static final String KERNEL_WAKELOCK_DATA = "kwl";
private static final String WAKEUP_REASON_DATA = "wr";
private static final String NETWORK_DATA = "nt";
@@ -273,6 +285,20 @@
public abstract Map<String, ? extends Wakelock> getWakelockStats();
/**
+ * Returns a mapping containing sync statistics.
+ *
+ * @return a Map from Strings to Timer objects.
+ */
+ public abstract Map<String, ? extends Timer> getSyncStats();
+
+ /**
+ * Returns a mapping containing scheduled job statistics.
+ *
+ * @return a Map from Strings to Timer objects.
+ */
+ public abstract Map<String, ? extends Timer> getJobStats();
+
+ /**
* The statistics associated with a particular wake lock.
*/
public static abstract class Wakelock {
@@ -660,13 +686,19 @@
public static final int EVENT_FOREGROUND = 0x0002;
// Event is about an application package that is at the top of the screen.
public static final int EVENT_TOP = 0x0003;
- // Event is about an application package that is at the top of the screen.
+ // Event is about active sync operations.
public static final int EVENT_SYNC = 0x0004;
// Events for all additional wake locks aquired/release within a wake block.
// These are not generated by default.
public static final int EVENT_WAKE_LOCK = 0x0005;
+ // Event is about an application executing a scheduled job.
+ public static final int EVENT_JOB = 0x0006;
+ // Events for users running.
+ public static final int EVENT_USER_RUNNING = 0x0007;
+ // Events for foreground user.
+ public static final int EVENT_USER_FOREGROUND = 0x0008;
// Number of event types.
- public static final int EVENT_COUNT = 0x0006;
+ public static final int EVENT_COUNT = 0x0009;
// Mask to extract out only the type part of the event.
public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
@@ -680,6 +712,14 @@
public static final int EVENT_SYNC_FINISH = EVENT_SYNC | EVENT_FLAG_FINISH;
public static final int EVENT_WAKE_LOCK_START = EVENT_WAKE_LOCK | EVENT_FLAG_START;
public static final int EVENT_WAKE_LOCK_FINISH = EVENT_WAKE_LOCK | EVENT_FLAG_FINISH;
+ public static final int EVENT_JOB_START = EVENT_JOB | EVENT_FLAG_START;
+ public static final int EVENT_JOB_FINISH = EVENT_JOB | EVENT_FLAG_FINISH;
+ public static final int EVENT_USER_RUNNING_START = EVENT_USER_RUNNING | EVENT_FLAG_START;
+ public static final int EVENT_USER_RUNNING_FINISH = EVENT_USER_RUNNING | EVENT_FLAG_FINISH;
+ public static final int EVENT_USER_FOREGROUND_START =
+ EVENT_USER_FOREGROUND | EVENT_FLAG_START;
+ public static final int EVENT_USER_FOREGROUND_FINISH =
+ EVENT_USER_FOREGROUND | EVENT_FLAG_FINISH;
// For CMD_EVENT.
public int eventCode;
@@ -1269,11 +1309,11 @@
};
public static final String[] HISTORY_EVENT_NAMES = new String[] {
- "null", "proc", "fg", "top", "sync", "wake_lock_in"
+ "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg"
};
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
- "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl"
+ "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf"
};
/**
@@ -1857,9 +1897,9 @@
screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000,
wifiRunningTime / 1000, bluetoothOnTime / 1000,
mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
- fullWakeLockTimeTotal, partialWakeLockTimeTotal,
- 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which),
- getMobileRadioActiveAdjustedTime(which), interactiveTime / 1000,
+ fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000,
+ 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which) / 1000,
+ getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000,
lowPowerModeEnabledTime / 1000);
// Dump screen brightness stats
@@ -2080,10 +2120,9 @@
}
}
- Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
+ Map<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
if (wakelocks.size() > 0) {
- for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
- : wakelocks.entrySet()) {
+ for (Map.Entry<String, ? extends Uid.Wakelock> ent : wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
String linePrefix = "";
sb.setLength(0);
@@ -2105,6 +2144,32 @@
}
}
+ Map<String, ? extends Timer> syncs = u.getSyncStats();
+ if (syncs.size() > 0) {
+ for (Map.Entry<String, ? extends Timer> ent : syncs.entrySet()) {
+ Timer timer = ent.getValue();
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
+ if (totalTime != 0) {
+ dumpLine(pw, uid, category, SYNC_DATA, ent.getKey(), totalTime, count);
+ }
+ }
+ }
+
+ Map<String, ? extends Timer> jobs = u.getJobStats();
+ if (jobs.size() > 0) {
+ for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) {
+ Timer timer = ent.getValue();
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
+ if (totalTime != 0) {
+ dumpLine(pw, uid, category, JOB_DATA, ent.getKey(), totalTime, count);
+ }
+ }
+ }
+
SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
int NSE = sensors.size();
for (int ise=0; ise<NSE; ise++) {
@@ -2937,8 +3002,7 @@
if (wakelocks.size() > 0) {
long totalFull = 0, totalPartial = 0, totalWindow = 0;
int count = 0;
- for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> ent
- : wakelocks.entrySet()) {
+ for (Map.Entry<String, ? extends Uid.Wakelock> ent : wakelocks.entrySet()) {
Uid.Wakelock wl = ent.getValue();
String linePrefix = ": ";
sb.setLength(0);
@@ -2998,6 +3062,56 @@
}
}
+ Map<String, ? extends Timer> syncs = u.getSyncStats();
+ if (syncs.size() > 0) {
+ for (Map.Entry<String, ? extends Timer> ent : syncs.entrySet()) {
+ Timer timer = ent.getValue();
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Sync ");
+ sb.append(ent.getKey());
+ sb.append(": ");
+ if (totalTime != 0) {
+ formatTimeMs(sb, totalTime);
+ sb.append("realtime (");
+ sb.append(count);
+ sb.append(" times)");
+ } else {
+ sb.append("(not used)");
+ }
+ pw.println(sb.toString());
+ uidActivity = true;
+ }
+ }
+
+ Map<String, ? extends Timer> jobs = u.getJobStats();
+ if (syncs.size() > 0) {
+ for (Map.Entry<String, ? extends Timer> ent : jobs.entrySet()) {
+ Timer timer = ent.getValue();
+ // Convert from microseconds to milliseconds with rounding
+ long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ int count = timer.getCountLocked(which);
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Job ");
+ sb.append(ent.getKey());
+ sb.append(": ");
+ if (totalTime != 0) {
+ formatTimeMs(sb, totalTime);
+ sb.append("realtime (");
+ sb.append(count);
+ sb.append(" times)");
+ } else {
+ sb.append("(not used)");
+ }
+ pw.println(sb.toString());
+ uidActivity = true;
+ }
+ }
+
SparseArray<? extends BatteryStats.Uid.Sensor> sensors = u.getSensorStats();
int NSE = sensors.size();
for (int ise=0; ise<NSE; ise++) {
@@ -3260,7 +3374,6 @@
int oldTemp = -1;
int oldVolt = -1;
long lastTime = -1;
- long firstTime = -1;
void reset() {
oldState = oldState2 = 0;
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 1557ab0..c5aee7b 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -230,7 +230,7 @@
*
* @see #EXTRA_PRINT_JOB_INFO
*/
- public static final String EXTRA_PRINTER_INFO = "android.intent.extra.print.PRINTER_INFO";
+ public static final String EXTRA_PRINTER_INFO = "android.intent.extra.print.EXTRA_PRINTER_INFO";
private Handler mHandler;
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 93f834a..bfe90e6 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -247,57 +247,6 @@
}
/**
- * @hide
- */
- public static final class Preferences {
-
- /**
- * A key in the {@link android.provider.Settings android.provider.Settings} provider
- * that stores the preferred sorting order for contacts (by given name vs. by family name).
- *
- * @hide
- */
- public static final String SORT_ORDER = "android.contacts.SORT_ORDER";
-
- /**
- * The value for the SORT_ORDER key corresponding to sorting by given name first.
- *
- * @hide
- */
- public static final int SORT_ORDER_PRIMARY = 1;
-
- /**
- * The value for the SORT_ORDER key corresponding to sorting by family name first.
- *
- * @hide
- */
- public static final int SORT_ORDER_ALTERNATIVE = 2;
-
- /**
- * A key in the {@link android.provider.Settings android.provider.Settings} provider
- * that stores the preferred display order for contacts (given name first vs. family
- * name first).
- *
- * @hide
- */
- public static final String DISPLAY_ORDER = "android.contacts.DISPLAY_ORDER";
-
- /**
- * The value for the DISPLAY_ORDER key corresponding to showing the given name first.
- *
- * @hide
- */
- public static final int DISPLAY_ORDER_PRIMARY = 1;
-
- /**
- * The value for the DISPLAY_ORDER key corresponding to showing the family name first.
- *
- * @hide
- */
- public static final int DISPLAY_ORDER_ALTERNATIVE = 2;
- }
-
- /**
* A Directory represents a contacts corpus, e.g. Local contacts,
* Google Apps Global Address List or Corporate Global Address List.
* <p>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 07397973..bc069ca 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -266,6 +266,21 @@
"android.settings.WIFI_DISPLAY_SETTINGS";
/**
+ * Activity Action: Show settings to allow configuration of
+ * {@link android.media.routing.MediaRouteService media route providers}.
+ * <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_CAST_SETTINGS =
+ "android.settings.CAST_SETTINGS";
+
+ /**
* Activity Action: Show settings to allow configuration of date and time.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -809,6 +824,15 @@
public static final String ACTION_BATTERY_SAVER_SETTINGS
= "android.settings.BATTERY_SAVER_SETTINGS";
+ /**
+ * Activity Action: Show Home selection settings. If there are multiple activities
+ * that can satisfy the {@link Intent#CATEGORY_HOME} intent, this screen allows you
+ * to pick your preferred activity.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_HOME_SETTINGS
+ = "android.settings.HOME_SETTINGS";
+
// End of Intent actions for Settings
/**
@@ -2472,12 +2496,6 @@
public static final String POINTER_SPEED = "pointer_speed";
/**
- * Whether lock-to-app will be triggered by long-press on recents.
- * @hide
- */
- public static final String LOCK_TO_APP_ENABLED = "lock_to_app_enabled";
-
- /**
* Whether lock-to-app will lock the keyguard when exiting.
* @hide
*/
@@ -3660,6 +3678,14 @@
public static final String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
/**
+ * Whether to draw text with high contrast while in accessibility mode.
+ *
+ * @hide
+ */
+ public static final String ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED =
+ "high_text_contrast_enabled";
+
+ /**
* If injection of accessibility enhancing JavaScript screen-reader
* is enabled.
* <p>
@@ -4626,6 +4652,7 @@
TOUCH_EXPLORATION_ENABLED,
ACCESSIBILITY_ENABLED,
ACCESSIBILITY_SPEAK_PASSWORD,
+ ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
ACCESSIBILITY_CAPTIONING_ENABLED,
ACCESSIBILITY_CAPTIONING_LOCALE,
ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR,
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index 6787fd0..d71ad03 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -188,6 +188,12 @@
*/
public static final String MIME_TYPE = "mime_type";
/**
+ * The transcription of the voicemail entry. This will only be populated if the voicemail
+ * entry has a valid transcription.
+ * <P>Type: TEXT</P>
+ */
+ public static final String TRANSCRIPTION = "transcription";
+ /**
* Path to the media content file. Internal only field.
* @hide
*/
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 8fc3c5a..cc09653 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -76,6 +76,7 @@
private static final String EXIT_CONDITION_TAG = "exitCondition";
private static final String EXIT_CONDITION_ATT_ID = "id";
+ private static final String EXIT_CONDITION_ATT_COMPONENT = "component";
public boolean allowCalls;
public boolean allowMessages;
@@ -89,6 +90,7 @@
public ComponentName[] conditionComponents;
public Uri[] conditionIds;
public Uri exitConditionId;
+ public ComponentName exitConditionComponent;
public ZenModeConfig() { }
@@ -114,6 +116,7 @@
}
allowFrom = source.readInt();
exitConditionId = source.readParcelable(null);
+ exitConditionComponent = source.readParcelable(null);
}
@Override
@@ -144,6 +147,7 @@
}
dest.writeInt(allowFrom);
dest.writeParcelable(exitConditionId, 0);
+ dest.writeParcelable(exitConditionComponent, 0);
}
@Override
@@ -160,6 +164,7 @@
.append(",conditionIds=")
.append(conditionIds == null ? null : TextUtils.join(",", conditionIds))
.append(",exitConditionId=").append(exitConditionId)
+ .append(",exitConditionComponent=").append(exitConditionComponent)
.append(']').toString();
}
@@ -191,7 +196,8 @@
&& other.sleepEndMinute == sleepEndMinute
&& Objects.deepEquals(other.conditionComponents, conditionComponents)
&& Objects.deepEquals(other.conditionIds, conditionIds)
- && Objects.equals(other.exitConditionId, exitConditionId);
+ && Objects.equals(other.exitConditionId, exitConditionId)
+ && Objects.equals(other.exitConditionComponent, exitConditionComponent);
}
@Override
@@ -199,7 +205,7 @@
return Objects.hash(allowCalls, allowMessages, allowFrom, sleepMode,
sleepStartHour, sleepStartMinute, sleepEndHour, sleepEndMinute,
Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds),
- exitConditionId);
+ exitConditionId, exitConditionComponent);
}
public boolean isValid() {
@@ -289,6 +295,8 @@
}
} else if (EXIT_CONDITION_TAG.equals(tag)) {
rt.exitConditionId = safeUri(parser, EXIT_CONDITION_ATT_ID);
+ rt.exitConditionComponent =
+ safeComponentName(parser, EXIT_CONDITION_ATT_COMPONENT);
}
}
}
@@ -325,9 +333,11 @@
out.endTag(null, CONDITION_TAG);
}
}
- if (exitConditionId != null) {
+ if (exitConditionId != null && exitConditionComponent != null) {
out.startTag(null, EXIT_CONDITION_TAG);
out.attribute(null, EXIT_CONDITION_ATT_ID, exitConditionId.toString());
+ out.attribute(null, EXIT_CONDITION_ATT_COMPONENT,
+ exitConditionComponent.flattenToString());
out.endTag(null, EXIT_CONDITION_TAG);
}
out.endTag(null, ZEN_TAG);
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 67ce31e..048fda1 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -20,9 +20,19 @@
import android.hardware.soundtrigger.Keyphrase;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.KeyphraseMetadata;
+import android.hardware.soundtrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.SoundTrigger.ConfidenceLevel;
+import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
import android.hardware.soundtrigger.SoundTriggerHelper;
+import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
+import android.os.RemoteException;
import android.util.Slog;
+import com.android.internal.app.IVoiceInteractionManagerService;
+
+import java.util.List;
+
/**
* A class that lets a VoiceInteractionService implementation interact with
* always-on keyphrase detection APIs.
@@ -56,27 +66,62 @@
public static final int MANAGE_ACTION_UN_ENROLL = 2;
/**
- * Return codes for {@link #startRecognition()}, {@link #stopRecognition()}
+ * Return codes for {@link #startRecognition(int)}, {@link #stopRecognition()}
*/
public static final int STATUS_ERROR = Integer.MIN_VALUE;
public static final int STATUS_OK = 1;
//---- Keyphrase recognition status ----//
- // TODO: Figure out if they are exclusive or should be flags instead?
- public static final int RECOGNITION_NOT_AVAILABLE = -3;
- public static final int RECOGNITION_NOT_REQUESTED = -2;
- public static final int RECOGNITION_DISABLED_TEMPORARILY = -1;
- public static final int RECOGNITION_REQUESTED = 1;
- public static final int RECOGNITION_ACTIVE = 2;
+ /** Indicates that recognition is not available. */
+ public static final int RECOGNITION_STATUS_NOT_AVAILABLE = 0x01;
+ /** Indicates that recognition has not been requested. */
+ public static final int RECOGNITION_STATUS_NOT_REQUESTED = 0x02;
+ /** Indicates that recognition has been requested. */
+ public static final int RECOGNITION_STATUS_REQUESTED = 0x04;
+ /** Indicates that recognition has been temporarily disabled. */
+ public static final int RECOGNITION_STATUS_DISABLED_TEMPORARILY = 0x08;
+ /** Indicates that recognition is currently active . */
+ public static final int RECOGNITION_STATUS_ACTIVE = 0x10;
+
+ //-- Flags for startRecogntion ----//
+ /** Empty flag for {@link #startRecognition(int)}. */
+ public static final int RECOGNITION_FLAG_NONE = 0;
+ /**
+ * Recognition flag for {@link #startRecognition(int)} that indicates
+ * whether the trigger audio for hotword needs to be captured.
+ */
+ public static final int RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO = 0x1;
+
+ //---- Recognition mode flags ----//
+ // Must be kept in sync with the related attribute defined as searchKeyphraseRecognitionFlags.
+
+ /** Simple recognition of the key phrase. Returned by {@link #getRecognitionStatus()} */
+ public static final int RECOGNITION_MODE_VOICE_TRIGGER
+ = SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER;
+ /** Trigger only if one user is identified. Returned by {@link #getRecognitionStatus()} */
+ public static final int RECOGNITION_MODE_USER_IDENTIFICATION
+ = SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION;
+
static final String TAG = "AlwaysOnHotwordDetector";
private final String mText;
private final String mLocale;
- private final Keyphrase mKeyphrase;
+ /**
+ * The metadata of the Keyphrase, derived from the enrollment application.
+ * This may be null if this keyphrase isn't supported by the enrollment application.
+ */
+ private final KeyphraseMetadata mKeyphraseMetadata;
+ /**
+ * The sound model for the keyphrase, derived from the model management service
+ * (IVoiceInteractionManagerService). May be null if the keyphrase isn't enrolled yet.
+ */
+ private final KeyphraseSoundModel mEnrolledSoundModel;
private final KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
private final SoundTriggerHelper mSoundTriggerHelper;
private final SoundTriggerHelper.Listener mListener;
private final int mAvailability;
+ private final IVoiceInteractionService mVoiceInteractionService;
+ private final IVoiceInteractionManagerService mModelManagementService;
private int mRecognitionState;
@@ -86,9 +131,11 @@
public interface Callback {
/**
* Called when the keyphrase is spoken.
- * TODO: Add more data to the callback.
+ *
+ * @param data Optional trigger audio data, if it was requested during
+ * {@link AlwaysOnHotwordDetector#startRecognition(int)}.
*/
- void onDetected();
+ void onDetected(byte[] data);
/**
* Called when the detection for the associated keyphrase starts.
*/
@@ -103,25 +150,30 @@
* @param text The keyphrase text to get the detector for.
* @param locale The java locale for the detector.
* @param callback A non-null Callback for receiving the recognition events.
+ * @param voiceInteractionService The current voice interaction service.
+ * @param modelManagementService A service that allows management of sound models.
*
* @hide
*/
public AlwaysOnHotwordDetector(String text, String locale, Callback callback,
KeyphraseEnrollmentInfo keyphraseEnrollmentInfo,
- SoundTriggerHelper soundTriggerHelper) {
+ SoundTriggerHelper soundTriggerHelper,
+ IVoiceInteractionService voiceInteractionService,
+ IVoiceInteractionManagerService modelManagementService) {
mText = text;
mLocale = locale;
mKeyphraseEnrollmentInfo = keyphraseEnrollmentInfo;
- KeyphraseMetadata keyphraseMetadata =
- mKeyphraseEnrollmentInfo.getKeyphraseMetadata(text, locale);
- if (keyphraseMetadata != null) {
- mKeyphrase = new Keyphrase(keyphraseMetadata.id, text, locale);
- } else {
- mKeyphrase = null;
- }
+ mKeyphraseMetadata = mKeyphraseEnrollmentInfo.getKeyphraseMetadata(text, locale);
mListener = new SoundTriggerListener(callback);
mSoundTriggerHelper = soundTriggerHelper;
- mAvailability = getAvailabilityInternal();
+ mVoiceInteractionService = voiceInteractionService;
+ mModelManagementService = modelManagementService;
+ if (mKeyphraseMetadata != null) {
+ mEnrolledSoundModel = internalGetKeyphraseSoundModel(mKeyphraseMetadata.id);
+ } else {
+ mEnrolledSoundModel = null;
+ }
+ mAvailability = internalGetAvailability();
}
/**
@@ -140,38 +192,63 @@
}
/**
- * Gets the status of the recognition.
- * @return One of {@link #RECOGNITION_NOT_AVAILABLE}, {@link #RECOGNITION_NOT_REQUESTED},
- * {@link #RECOGNITION_DISABLED_TEMPORARILY} or {@link #RECOGNITION_ACTIVE}.
- * @throws UnsupportedOperationException if the recognition isn't supported.
+ * Gets the recognition modes supported by the associated keyphrase.
+ *
+ * @throws UnsupportedOperationException if the keyphrase itself isn't supported.
* Callers should check the availability by calling {@link #getAvailability()}
* before calling this method to avoid this exception.
*/
- public int getRecognitionStatus() {
- if (mAvailability != KEYPHRASE_ENROLLED) {
+ public int getSupportedRecognitionModes() {
+ if (mAvailability == KEYPHRASE_HARDWARE_UNAVAILABLE
+ || mAvailability == KEYPHRASE_UNSUPPORTED) {
throw new UnsupportedOperationException(
- "Recognition for the given keyphrase is not supported");
+ "Getting supported recognition modes for the keyphrase is not supported");
}
+ return mKeyphraseMetadata.recognitionModeFlags;
+ }
+
+ /**
+ * Gets the status of the recognition.
+ * @return A flag comprised of {@link #RECOGNITION_STATUS_NOT_AVAILABLE},
+ * {@link #RECOGNITION_STATUS_NOT_REQUESTED}, {@link #RECOGNITION_STATUS_REQUESTED},
+ * {@link #RECOGNITION_STATUS_DISABLED_TEMPORARILY} and
+ * {@link #RECOGNITION_STATUS_ACTIVE}.
+ */
+ public int getRecognitionStatus() {
return mRecognitionState;
}
/**
* Starts recognition for the associated keyphrase.
*
+ * @param recognitionFlags The flags to control the recognition properties.
+ * The allowed flags are {@link #RECOGNITION_FLAG_NONE} and
+ * {@link #RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO}.
* @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
* @throws UnsupportedOperationException if the recognition isn't supported.
* Callers should check the availability by calling {@link #getAvailability()}
* before calling this method to avoid this exception.
*/
- public int startRecognition() {
- if (mAvailability != KEYPHRASE_ENROLLED) {
+ public int startRecognition(int recognitionFlags) {
+ if (mAvailability != KEYPHRASE_ENROLLED
+ || (mRecognitionState&RECOGNITION_STATUS_NOT_AVAILABLE) != 0) {
throw new UnsupportedOperationException(
"Recognition for the given keyphrase is not supported");
}
- mRecognitionState = RECOGNITION_REQUESTED;
- int code = mSoundTriggerHelper.startRecognition(mKeyphrase.id, mListener);
+ mRecognitionState &= RECOGNITION_STATUS_REQUESTED;
+ KeyphraseRecognitionExtra[] recognitionExtra = new KeyphraseRecognitionExtra[1];
+ // TODO: Do we need to do something about the confidence level here?
+ // TODO: Take in captureTriggerAudio as a method param here.
+ recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.id,
+ mKeyphraseMetadata.recognitionModeFlags, new ConfidenceLevel[0]);
+ boolean captureTriggerAudio =
+ (recognitionFlags & RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0;
+ int code = mSoundTriggerHelper.startRecognition(mKeyphraseMetadata.id,
+ mEnrolledSoundModel.convertToSoundTriggerKeyphraseSoundModel(), mListener,
+ new RecognitionConfig(
+ captureTriggerAudio, recognitionExtra,null /* additional data */));
if (code != SoundTriggerHelper.STATUS_OK) {
Slog.w(TAG, "startRecognition() failed with error code " + code);
return STATUS_ERROR;
@@ -194,8 +271,9 @@
"Recognition for the given keyphrase is not supported");
}
- mRecognitionState = RECOGNITION_NOT_REQUESTED;
- int code = mSoundTriggerHelper.stopRecognition(mKeyphrase.id, mListener);
+ mRecognitionState &= ~RECOGNITION_STATUS_NOT_REQUESTED;
+ int code = mSoundTriggerHelper.stopRecognition(mKeyphraseMetadata.id, mListener);
+
if (code != SoundTriggerHelper.STATUS_OK) {
Slog.w(TAG, "stopRecognition() failed with error code " + code);
return STATUS_ERROR;
@@ -230,19 +308,56 @@
return mKeyphraseEnrollmentInfo.getManageKeyphraseIntent(action, mText, mLocale);
}
- private int getAvailabilityInternal() {
+ private int internalGetAvailability() {
+ // No DSP available
if (mSoundTriggerHelper.dspInfo == null) {
+ mRecognitionState = RECOGNITION_STATUS_NOT_AVAILABLE;
return KEYPHRASE_HARDWARE_UNAVAILABLE;
}
- if (mKeyphrase == null || !mSoundTriggerHelper.isKeyphraseSupported(mKeyphrase)) {
+ // No enrollment application supports this keyphrase/locale
+ if (mKeyphraseMetadata == null) {
+ mRecognitionState = RECOGNITION_STATUS_NOT_AVAILABLE;
return KEYPHRASE_UNSUPPORTED;
}
- if (!mSoundTriggerHelper.isKeyphraseEnrolled(mKeyphrase)) {
+ // This keyphrase hasn't been enrolled.
+ if (mEnrolledSoundModel == null) {
+ mRecognitionState = RECOGNITION_STATUS_NOT_AVAILABLE;
return KEYPHRASE_UNENROLLED;
}
+ // Mark recognition as available
+ mRecognitionState &= ~RECOGNITION_STATUS_NOT_AVAILABLE;
return KEYPHRASE_ENROLLED;
}
+ /**
+ * @return The corresponding {@link KeyphraseSoundModel} or null if none is found.
+ */
+ private KeyphraseSoundModel internalGetKeyphraseSoundModel(int keyphraseId) {
+ List<KeyphraseSoundModel> soundModels;
+ try {
+ soundModels = mModelManagementService
+ .listRegisteredKeyphraseSoundModels(mVoiceInteractionService);
+ if (soundModels == null || soundModels.isEmpty()) {
+ Slog.i(TAG, "No available sound models for keyphrase ID: " + keyphraseId);
+ return null;
+ }
+ for (KeyphraseSoundModel soundModel : soundModels) {
+ if (soundModel.keyphrases == null) {
+ continue;
+ }
+ for (Keyphrase keyphrase : soundModel.keyphrases) {
+ // TODO: Check the user handle here to only load a model for the current user.
+ if (keyphrase.id == keyphraseId) {
+ return soundModel;
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "RemoteException in listRegisteredKeyphraseSoundModels!");
+ }
+ return null;
+ }
+
/** @hide */
static final class SoundTriggerListener implements SoundTriggerHelper.Listener {
private final Callback mCallback;
@@ -252,14 +367,15 @@
}
@Override
- public void onKeyphraseSpoken() {
+ public void onKeyphraseSpoken(byte[] data) {
Slog.i(TAG, "onKeyphraseSpoken");
- mCallback.onDetected();
+ mCallback.onDetected(data);
}
@Override
public void onListeningStateChanged(int state) {
Slog.i(TAG, "onListeningStateChanged: state=" + state);
+ // TODO: Set/unset the RECOGNITION_STATUS_ACTIVE flag here.
if (state == SoundTriggerHelper.STATE_STARTED) {
mCallback.onDetectionStarted();
} else if (state == SoundTriggerHelper.STATE_STOPPED) {
diff --git a/core/java/android/service/voice/IVoiceInteractionService.aidl b/core/java/android/service/voice/IVoiceInteractionService.aidl
index e9e2f4c..c9915a2 100644
--- a/core/java/android/service/voice/IVoiceInteractionService.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionService.aidl
@@ -20,4 +20,5 @@
* @hide
*/
oneway interface IVoiceInteractionService {
+ void ready();
}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index cf8d502..1f5d327 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -18,15 +18,19 @@
import android.annotation.SdkConstant;
import android.app.Service;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.SoundTriggerHelper;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractionManagerService;
@@ -64,14 +68,58 @@
public static final String SERVICE_META_DATA = "android.voice_interaction";
IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() {
+ @Override public void ready() {
+ mHandler.sendEmptyMessage(MSG_READY);
+ }
};
+ MyHandler mHandler;
+
IVoiceInteractionManagerService mSystemService;
private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo;
private SoundTriggerHelper mSoundTriggerHelper;
+ static final int MSG_READY = 1;
+
+ class MyHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_READY:
+ onReady();
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ }
+
+ /**
+ * Check whether the given service component is the currently active
+ * VoiceInteractionService.
+ */
+ public static boolean isActiveService(Context context, ComponentName service) {
+ String cur = Settings.Secure.getString(context.getContentResolver(),
+ Settings.Secure.VOICE_INTERACTION_SERVICE);
+ if (cur == null || cur.isEmpty()) {
+ return false;
+ }
+ ComponentName curComp = ComponentName.unflattenFromString(cur);
+ if (curComp == null) {
+ return false;
+ }
+ return curComp.equals(cur);
+ }
+
+ /**
+ * Initiate the execution of a new {@link android.service.voice.VoiceInteractionSession}.
+ * @param args Arbitrary arguments that will be propagated to the session.
+ */
public void startSession(Bundle args) {
+ if (mSystemService == null) {
+ throw new IllegalStateException("Not available until onReady() is called");
+ }
try {
mSystemService.startSession(mInterface, args);
} catch (RemoteException e) {
@@ -81,10 +129,7 @@
@Override
public void onCreate() {
super.onCreate();
- mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
- ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
- mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager());
- mSoundTriggerHelper = new SoundTriggerHelper();
+ mHandler = new MyHandler();
}
@Override
@@ -96,6 +141,19 @@
}
/**
+ * Called during service initialization to tell you when the system is ready
+ * to receive interaction from it. You should generally do initialization here
+ * rather than in {@link #onCreate()}. Methods such as {@link #startSession}
+ * and {@link #getAlwaysOnHotwordDetector} will not be operational until this point.
+ */
+ public void onReady() {
+ mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
+ ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+ mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager());
+ mSoundTriggerHelper = new SoundTriggerHelper();
+ }
+
+ /**
* @param keyphrase The keyphrase that's being used, for example "Hello Android".
* @param locale The locale for which the enrollment needs to be performed.
* This is a Java locale, for example "en_US".
@@ -104,10 +162,13 @@
*/
public final AlwaysOnHotwordDetector getAlwaysOnHotwordDetector(
String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) {
+ if (mSystemService == null) {
+ throw new IllegalStateException("Not available until onReady() is called");
+ }
// TODO: Cache instances and return the same one instead of creating a new interactor
// for the same keyphrase/locale combination.
return new AlwaysOnHotwordDetector(keyphrase, locale, callback,
- mKeyphraseEnrollmentInfo, mSoundTriggerHelper);
+ mKeyphraseEnrollmentInfo, mSoundTriggerHelper, mInterface, mSystemService);
}
/**
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
index a909ead..d27e2cd 100644
--- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -40,6 +40,7 @@
private ServiceInfo mServiceInfo;
private String mSessionService;
+ private String mRecognitionService;
private String mSettingsActivity;
public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
@@ -82,6 +83,8 @@
com.android.internal.R.styleable.VoiceInteractionService);
mSessionService = array.getString(
com.android.internal.R.styleable.VoiceInteractionService_sessionService);
+ mRecognitionService = array.getString(
+ com.android.internal.R.styleable.VoiceInteractionService_recognitionService);
mSettingsActivity = array.getString(
com.android.internal.R.styleable.VoiceInteractionService_settingsActivity);
array.recycle();
@@ -119,6 +122,10 @@
return mSessionService;
}
+ public String getRecognitionService() {
+ return mRecognitionService;
+ }
+
public String getSettingsActivity() {
return mSettingsActivity;
}
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index c6005b9..363f97f 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -160,7 +160,7 @@
@Override
public TransitionSet setDuration(long duration) {
super.setDuration(duration);
- if (mDuration >= 0) {
+ if (mDuration >= 0 && mTransitions != null) {
int numTransitions = mTransitions.size();
for (int i = 0; i < numTransitions; ++i) {
mTransitions.get(i).setDuration(duration);
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 6cda905..3f10b92 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -75,9 +75,7 @@
public static final int DENSITY_400 = 400;
/**
- * Standard quantized DPI for extra-extra-high-density screens. Applications
- * should not generally worry about this density; relying on XHIGH graphics
- * being scaled up to it should be sufficient for almost all cases.
+ * Standard quantized DPI for extra-extra-high-density screens.
*/
public static final int DENSITY_XXHIGH = 480;
diff --git a/core/java/android/util/ExceptionUtils.java b/core/java/android/util/ExceptionUtils.java
index 6aae84d..f5d515d 100644
--- a/core/java/android/util/ExceptionUtils.java
+++ b/core/java/android/util/ExceptionUtils.java
@@ -39,4 +39,20 @@
throw new IOException(e.getMessage().substring(PREFIX_IO.length()));
}
}
+
+ public static String getCompleteMessage(String msg, Throwable t) {
+ final StringBuilder builder = new StringBuilder();
+ if (msg != null) {
+ builder.append(msg).append(": ");
+ }
+ builder.append(t.getMessage());
+ while ((t = t.getCause()) != null) {
+ builder.append(": ").append(t.getMessage());
+ }
+ return builder.toString();
+ }
+
+ public static String getCompleteMessage(Throwable t) {
+ return getCompleteMessage(null, t);
+ }
}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index d7d3c72..910f862 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -168,7 +168,15 @@
nSetViewport(mRenderer, width, height);
}
- private static native void nSetViewport(long renderer, int width, int height);
+ private static native void nSetViewport(long renderer,
+ int width, int height);
+
+ @Override
+ public void setHighContrastText(boolean highContrastText) {
+ nSetHighContrastText(mRenderer, highContrastText);
+ }
+
+ private static native void nSetHighContrastText(long renderer, boolean highContrastText);
@Override
public int onPreDraw(Rect dirty) {
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 26f47f9..cc090ad5 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -46,6 +46,12 @@
public static final int CLOCK_TICK = 4;
/**
+ * The user has pressed either a day or month or year date of a Calendar.
+ * @hide
+ */
+ public static final int CALENDAR_DATE = 5;
+
+ /**
* This is a private constant. Feel free to renumber as desired.
* @hide
*/
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index f2f363a..8c9b819 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -327,6 +327,12 @@
}
/**
+ * Indicates that the content drawn by HardwareDrawCallbacks needs to
+ * be updated, which will be done by the next call to draw()
+ */
+ abstract void invalidateRoot();
+
+ /**
* Draws the specified view.
*
* @param view The view to draw.
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index ae59bbc..a61d771 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -80,7 +80,7 @@
void removeWindowToken(IBinder token);
void addAppToken(int addPos, IApplicationToken token, int groupId, int stackId,
int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
- int configChanges, boolean voiceInteraction);
+ int configChanges, boolean voiceInteraction, boolean launchTaskBehind);
void setAppGroupId(IBinder token, int groupId);
void setAppOrientation(IApplicationToken token, int requestedOrientation);
int getAppOrientation(IApplicationToken token);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index fb8ce15..b033780 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -81,6 +81,9 @@
// applied as translation when updating the root render node.
private int mInsetTop, mInsetLeft;
+ // Whether the surface has insets. Used to protect opacity.
+ private boolean mHasInsets;
+
// Light and shadow properties specified by the theme.
private final float mLightY;
private final float mLightZ;
@@ -93,6 +96,7 @@
private RenderNode mRootNode;
private Choreographer mChoreographer;
private boolean mProfilingEnabled;
+ private boolean mRootNodeNeedsUpdate;
ThreadedRenderer(Context context, boolean translucent) {
final TypedArray a = context.obtainStyledAttributes(
@@ -187,12 +191,17 @@
final float lightX = width / 2.0f;
mWidth = width;
mHeight = height;
- if (surfaceInsets != null) {
+ if (surfaceInsets != null && !surfaceInsets.isEmpty()) {
+ mHasInsets = true;
mInsetLeft = surfaceInsets.left;
mInsetTop = surfaceInsets.top;
mSurfaceWidth = width + mInsetLeft + surfaceInsets.right;
mSurfaceHeight = height + mInsetTop + surfaceInsets.bottom;
+
+ // If the surface has insets, it can't be opaque.
+ setOpaque(false);
} else {
+ mHasInsets = false;
mInsetLeft = 0;
mInsetTop = 0;
mSurfaceWidth = width;
@@ -204,7 +213,7 @@
@Override
void setOpaque(boolean opaque) {
- nSetOpaque(mNativeProxy, opaque);
+ nSetOpaque(mNativeProxy, opaque && !mHasInsets);
}
@Override
@@ -247,30 +256,41 @@
return changed;
}
- private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
+ private void updateViewTreeDisplayList(View view) {
view.mPrivateFlags |= View.PFLAG_DRAWN;
-
view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
== View.PFLAG_INVALIDATED;
view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
-
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
- HardwareCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
- try {
- canvas.save();
- canvas.translate(mInsetLeft, mInsetTop);
- callbacks.onHardwarePreDraw(canvas);
- canvas.drawRenderNode(view.getDisplayList());
- callbacks.onHardwarePostDraw(canvas);
- canvas.restore();
- } finally {
- mRootNode.end(canvas);
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
-
+ view.getDisplayList();
view.mRecreateDisplayList = false;
}
+ private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
+ updateViewTreeDisplayList(view);
+
+ if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
+ HardwareCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
+ try {
+ canvas.save();
+ canvas.translate(mInsetLeft, mInsetTop);
+ callbacks.onHardwarePreDraw(canvas);
+ canvas.drawRenderNode(view.getDisplayList());
+ callbacks.onHardwarePostDraw(canvas);
+ canvas.restore();
+ mRootNodeNeedsUpdate = false;
+ } finally {
+ mRootNode.end(canvas);
+ }
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+
+ @Override
+ void invalidateRoot() {
+ mRootNodeNeedsUpdate = true;
+ }
+
@Override
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
attachInfo.mIgnoreDirtyState = true;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a09a061..a3e2c96 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4852,8 +4852,8 @@
*/
private void manageFocusHotspot(boolean focused, View v) {
final Rect r = new Rect();
- if (!focused && v != null && mAttachInfo != null) {
- v.getBoundsOnScreen(r);
+ if (v != null && mAttachInfo != null) {
+ v.getHotspotBounds(r);
final int[] location = mAttachInfo.mTmpLocation;
getLocationOnScreen(location);
r.offset(-location[0], -location[1]);
@@ -4867,6 +4867,22 @@
}
/**
+ * Populates <code>outRect</code> with the hotspot bounds. By default,
+ * the hotspot bounds are identical to the screen bounds.
+ *
+ * @param outRect rect to populate with hotspot bounds
+ * @hide Only for internal use by views and widgets.
+ */
+ public void getHotspotBounds(Rect outRect) {
+ final Drawable background = getBackground();
+ if (background != null) {
+ background.getHotspotBounds(outRect);
+ } else {
+ getBoundsOnScreen(outRect);
+ }
+ }
+
+ /**
* Request that a rectangle of this view be visible on the screen,
* scrolling if necessary just enough.
*
@@ -13730,6 +13746,7 @@
int layerType = getLayerType();
final HardwareCanvas canvas = renderNode.start(width, height);
+ canvas.setHighContrastText(mAttachInfo.mHighContrastText);
try {
final HardwareLayer layer = getHardwareLayer();
@@ -19897,6 +19914,11 @@
boolean mViewScrollChanged;
/**
+ * Set to true if high contrast mode enabled
+ */
+ boolean mHighContrastText;
+
+ /**
* Global to the view hierarchy used as a temporary for dealing with
* x/y points in the transparent region computations.
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7fab808..a8d3f99 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -63,6 +63,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
+import android.view.accessibility.AccessibilityManager.HighTextContrastChangeListener;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.accessibility.IAccessibilityInteractionConnection;
@@ -313,6 +314,7 @@
AccessibilityInteractionController mAccessibilityInteractionController;
AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager;
+ HighContrastTextManager mHighContrastTextManager;
SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
@@ -370,12 +372,15 @@
mPreviousTransparentRegion = new Region();
mFirst = true; // true for the first time the view is added
mAdded = false;
+ mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
mAccessibilityManager = AccessibilityManager.getInstance(context);
mAccessibilityInteractionConnectionManager =
new AccessibilityInteractionConnectionManager();
mAccessibilityManager.addAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager);
- mAttachInfo = new View.AttachInfo(mWindowSession, mWindow, display, this, mHandler, this);
+ mHighContrastTextManager = new HighContrastTextManager();
+ mAccessibilityManager.addHighTextContrastStateChangeListener(
+ mHighContrastTextManager);
mViewConfiguration = ViewConfiguration.get(context);
mDensity = context.getResources().getDisplayMetrics().densityDpi;
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
@@ -461,6 +466,16 @@
}
}
+ // Compute surface insets required to draw at specified Z value.
+ // TODO: Use real shadow insets for a constant max Z.
+ if (view.isHardwareAccelerated()) {
+ final int surfaceInset = (int) Math.ceil(view.getZ() * 2);
+ attrs.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
+ } else {
+ // Software accelerated windows can't use insets.
+ attrs.surfaceInsets.setEmpty();
+ }
+
CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
mTranslator = compatibilityInfo.getTranslator();
mDisplayAdjustments.setActivityToken(attrs.token);
@@ -1713,8 +1728,8 @@
if (hwInitialized ||
mWidth != mAttachInfo.mHardwareRenderer.getWidth() ||
mHeight != mAttachInfo.mHardwareRenderer.getHeight()) {
- final Rect shadowInsets = params != null ? params.shadowInsets : null;
- mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight, shadowInsets);
+ final Rect surfaceInsets = params != null ? params.surfaceInsets : null;
+ mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight, surfaceInsets);
if (!hwInitialized) {
mAttachInfo.mHardwareRenderer.invalidate(mSurface);
mFullRedrawNeeded = true;
@@ -2370,8 +2385,6 @@
attachInfo.mTreeObserver.dispatchOnScrollChanged();
}
- final WindowManager.LayoutParams params = mWindowAttributes;
- final Rect surfaceInsets = params != null ? params.shadowInsets : null;
boolean animating = mScroller != null && mScroller.computeScrollOffset();
final int curScrollY;
if (animating) {
@@ -2429,14 +2442,27 @@
attachInfo.mTreeObserver.dispatchOnDraw();
- final int xOffset = surfaceInsets != null ? -surfaceInsets.left : 0;
- final int yOffset = curScrollY + (surfaceInsets != null ? -surfaceInsets.top : 0);
+ int xOffset = 0;
+ int yOffset = curScrollY;
+ final WindowManager.LayoutParams params = mWindowAttributes;
+ final Rect surfaceInsets = params != null ? params.surfaceInsets : null;
+ if (surfaceInsets != null) {
+ xOffset -= surfaceInsets.left;
+ yOffset -= surfaceInsets.top;
+
+ // Offset dirty rect for surface insets.
+ dirty.offset(surfaceInsets.left, surfaceInsets.right);
+ }
+
if (!dirty.isEmpty() || mIsAnimating) {
if (attachInfo.mHardwareRenderer != null && attachInfo.mHardwareRenderer.isEnabled()) {
// Draw with hardware renderer.
mIsAnimating = false;
- mHardwareYOffset = yOffset;
- mHardwareXOffset = xOffset;
+ if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
+ mHardwareYOffset = yOffset;
+ mHardwareXOffset = xOffset;
+ mAttachInfo.mHardwareRenderer.invalidateRoot();
+ }
mResizeAlpha = resizeAlpha;
dirty.setEmpty();
@@ -2488,19 +2514,19 @@
boolean scalingRequired, Rect dirty) {
// Draw with software renderer.
- Canvas canvas;
+ final Canvas canvas;
try {
- int left = dirty.left;
- int top = dirty.top;
- int right = dirty.right;
- int bottom = dirty.bottom;
+ final int left = dirty.left;
+ final int top = dirty.top;
+ final int right = dirty.right;
+ final int bottom = dirty.bottom;
canvas = mSurface.lockCanvas(dirty);
// The dirty rectangle can be modified by Surface.lockCanvas()
//noinspection ConstantConditions
- if (left != dirty.left || top != dirty.top || right != dirty.right ||
- bottom != dirty.bottom) {
+ if (left != dirty.left || top != dirty.top || right != dirty.right
+ || bottom != dirty.bottom) {
attachInfo.mIgnoreDirtyState = true;
}
@@ -2822,6 +2848,10 @@
// Set the new focus host and node.
mAccessibilityFocusedHost = view;
mAccessibilityFocusedVirtualView = node;
+
+ if (mAttachInfo.mHardwareRenderer != null) {
+ mAttachInfo.mHardwareRenderer.invalidateRoot();
+ }
}
@Override
@@ -2889,6 +2919,8 @@
mAccessibilityInteractionConnectionManager.ensureNoConnection();
mAccessibilityManager.removeAccessibilityStateChangeListener(
mAccessibilityInteractionConnectionManager);
+ mAccessibilityManager.removeHighTextContrastStateChangeListener(
+ mHighContrastTextManager);
removeSendWindowContentChangedCallback();
destroyHardwareRenderer();
@@ -3155,7 +3187,7 @@
mFullRedrawNeeded = true;
try {
final WindowManager.LayoutParams lp = mWindowAttributes;
- final Rect surfaceInsets = lp != null ? lp.shadowInsets : null;
+ final Rect surfaceInsets = lp != null ? lp.surfaceInsets : null;
mAttachInfo.mHardwareRenderer.initializeIfNeeded(
mWidth, mHeight, mSurface, surfaceInsets);
} catch (OutOfResourcesException e) {
@@ -6560,7 +6592,7 @@
public void onAccessibilityStateChanged(boolean enabled) {
if (enabled) {
ensureConnection();
- if (mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
+ if (mAttachInfo.mHasWindowFocus) {
mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
View focusedView = mView.findFocus();
if (focusedView != null && focusedView != mView) {
@@ -6574,14 +6606,12 @@
}
public void ensureConnection() {
- if (mAttachInfo != null) {
- final boolean registered =
+ final boolean registered =
mAttachInfo.mAccessibilityWindowId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
- if (!registered) {
- mAttachInfo.mAccessibilityWindowId =
+ if (!registered) {
+ mAttachInfo.mAccessibilityWindowId =
mAccessibilityManager.addAccessibilityInteractionConnection(mWindow,
new AccessibilityInteractionConnection(ViewRootImpl.this));
- }
}
}
@@ -6595,6 +6625,19 @@
}
}
+ final class HighContrastTextManager implements HighTextContrastChangeListener {
+ HighContrastTextManager() {
+ mAttachInfo.mHighContrastText = mAccessibilityManager.isHighTextContrastEnabled();
+ }
+ @Override
+ public void onHighTextContrastStateChanged(boolean enabled) {
+ mAttachInfo.mHighContrastText = enabled;
+
+ // Destroy Displaylists so they can be recreated with high contrast recordings
+ destroyHardwareResources();
+ }
+ }
+
/**
* This class is an interface this ViewAncestor provides to the
* AccessibilityManagerService to the latter can interact with
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index aa71ed8..c169d35 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -23,6 +23,8 @@
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -157,7 +159,7 @@
private static final String PROPERTY_HARDWARE_UI = "persist.sys.ui.hw";
private final Context mContext;
-
+
private TypedArray mWindowStyle;
private Callback mCallback;
private OnWindowDismissedCallback mOnWindowDismissedCallback;
@@ -181,7 +183,7 @@
private int mDefaultWindowFormat = PixelFormat.OPAQUE;
private boolean mHasSoftInputMode = false;
-
+
private boolean mDestroyed;
// The current window attributes.
@@ -227,7 +229,7 @@
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTouchEvent(MotionEvent event);
-
+
/**
* Called to process trackball events. At the very least your
* implementation must call
@@ -313,14 +315,14 @@
* Called when a panel's menu is opened by the user. This may also be
* called when the menu is changing from one type to another (for
* example, from the icon menu to the expanded menu).
- *
+ *
* @param featureId The panel that the menu is in.
* @param menu The menu that is opened.
* @return Return true to allow the menu to open, or false to prevent
* the menu from opening.
*/
public boolean onMenuOpened(int featureId, Menu menu);
-
+
/**
* Called when a panel's menu item has been selected by the user.
*
@@ -364,31 +366,31 @@
* for more information.
*/
public void onAttachedToWindow();
-
+
/**
* Called when the window has been attached to the window manager.
* See {@link View#onDetachedFromWindow() View.onDetachedFromWindow()}
* for more information.
*/
public void onDetachedFromWindow();
-
+
/**
* Called when a panel is being closed. If another logical subsequent
* panel is being opened (and this panel is being closed to make room for the subsequent
* panel), this method will NOT be called.
- *
+ *
* @param featureId The panel that is being displayed.
* @param menu If onCreatePanelView() returned null, this is the Menu
* being displayed in the panel.
*/
public void onPanelClosed(int featureId, Menu menu);
-
+
/**
* Called when the user signals the desire to start a search.
- *
+ *
* @return true if search launched, false if activity refuses (blocks)
- *
- * @see android.app.Activity#onSearchRequested()
+ *
+ * @see android.app.Activity#onSearchRequested()
*/
public boolean onSearchRequested();
@@ -457,7 +459,7 @@
return mWindowStyle;
}
}
-
+
/**
* Set the container for this window. If not set, the DecorWindow
* operates as a top-level window; otherwise, it negotiates with the
@@ -488,7 +490,7 @@
public final boolean hasChildren() {
return mHasChildren;
}
-
+
/** @hide */
public final void destroy() {
mDestroyed = true;
@@ -622,14 +624,14 @@
* callback will be used to tell you about state changes to the surface.
*/
public abstract void takeSurface(SurfaceHolder.Callback2 callback);
-
+
/**
* Take ownership of this window's InputQueue. The window will no
* longer read and dispatch input events from the queue; it is your
* responsibility to do so.
*/
public abstract void takeInputQueue(InputQueue.Callback callback);
-
+
/**
* Return whether this window is being displayed with a floating style
* (based on the {@link android.R.attr#windowIsFloating} attribute in
@@ -740,7 +742,7 @@
}
dispatchWindowAttributesChanged(attrs);
}
-
+
/**
* Convenience function to set the flag bits as specified in flags, as
* per {@link #setFlags}.
@@ -756,7 +758,7 @@
public void addPrivateFlags(int flags) {
setPrivateFlags(flags, flags);
}
-
+
/**
* Convenience function to clear the flag bits as specified in flags, as
* per {@link #setFlags}.
@@ -772,7 +774,7 @@
* Set the flags of the window, as per the
* {@link WindowManager.LayoutParams WindowManager.LayoutParams}
* flags.
- *
+ *
* <p>Note that some flags must be set before the window decoration is
* created (by the first call to
* {@link #setContentView(View, android.view.ViewGroup.LayoutParams)} or
@@ -859,20 +861,20 @@
protected final int getForcedWindowFlags() {
return mForcedWindowFlags;
}
-
+
/**
* Has the app specified their own soft input mode?
*/
protected final boolean hasSoftInputMode() {
return mHasSoftInputMode;
}
-
+
/** @hide */
public void setCloseOnTouchOutside(boolean close) {
mCloseOnTouchOutside = close;
mSetCloseOnTouchOutside = true;
}
-
+
/** @hide */
public void setCloseOnTouchOutsideIfNotSet(boolean close) {
if (!mSetCloseOnTouchOutside) {
@@ -880,10 +882,10 @@
mSetCloseOnTouchOutside = true;
}
}
-
+
/** @hide */
public abstract void alwaysReadCloseOnTouchAttr();
-
+
/** @hide */
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
@@ -892,7 +894,7 @@
}
return false;
}
-
+
private boolean isOutOfBounds(Context context, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
@@ -902,7 +904,7 @@
|| (x > (decorView.getWidth()+slop))
|| (y > (decorView.getHeight()+slop));
}
-
+
/**
* Enable extended screen features. This must be called before
* setContentView(). May be called as many times as desired as long as it
@@ -989,7 +991,7 @@
* of the window that can not, from this point forward, be changed: the
* features that have been requested with {@link #requestFeature(int)},
* and certain window flags as described in {@link #setFlags(int, int)}.
- *
+ *
* @param view The desired content to display.
* @param params Layout parameters for the view.
*/
@@ -1037,7 +1039,7 @@
public abstract void togglePanel(int featureId, KeyEvent event);
public abstract void invalidatePanelMenu(int featureId);
-
+
public abstract boolean performPanelShortcut(int featureId,
int keyCode,
KeyEvent event,
@@ -1052,17 +1054,17 @@
/**
* Should be called when the configuration is changed.
- *
+ *
* @param newConfig The new configuration.
*/
public abstract void onConfigurationChanged(Configuration newConfig);
-
+
/**
* Change the background of this window to a Drawable resource. Setting the
* background to null will make the window be opaque. To make the window
* transparent, you can use an empty drawable (for instance a ColorDrawable
* with the color 0 or the system drawable android:drawable/empty.)
- *
+ *
* @param resid The resource identifier of a drawable resource which will be
* installed as the new background.
*/
@@ -1173,7 +1175,7 @@
*
*/
public abstract boolean superDispatchTouchEvent(MotionEvent event);
-
+
/**
* Used by custom windows, such as Dialog, to pass the trackball event
* further down the view hierarchy. Application developers should
@@ -1181,7 +1183,7 @@
*
*/
public abstract boolean superDispatchTrackballEvent(MotionEvent event);
-
+
/**
* Used by custom windows, such as Dialog, to pass the generic motion event
* further down the view hierarchy. Application developers should
@@ -1194,11 +1196,11 @@
* Retrieve the top-level window decor view (containing the standard
* window frame/decorations and the client's content inside of that), which
* can be added as a window to the window manager.
- *
+ *
* <p><em>Note that calling this function for the first time "locks in"
* various window characteristics as described in
* {@link #setContentView(View, android.view.ViewGroup.LayoutParams)}.</em></p>
- *
+ *
* @return Returns the top-level window decor view.
*/
public abstract View getDecorView();
@@ -1206,16 +1208,16 @@
/**
* Retrieve the current decor view, but only if it has already been created;
* otherwise returns null.
- *
+ *
* @return Returns the top-level window decor or null.
* @see #getDecorView
*/
public abstract View peekDecorView();
public abstract Bundle saveHierarchyState();
-
+
public abstract void restoreHierarchyState(Bundle savedInstanceState);
-
+
protected abstract void onActive();
/**
@@ -1233,10 +1235,10 @@
{
return mFeatures;
}
-
+
/**
* Query for the availability of a certain feature.
- *
+ *
* @param feature The feature ID to check
* @return true if the feature is enabled, false otherwise.
*/
@@ -1290,9 +1292,9 @@
* @param event the {@link android.view.KeyEvent} to use to help check.
*/
public abstract boolean isShortcutKey(int keyCode, KeyEvent event);
-
+
/**
- * @see android.app.Activity#setVolumeControlStream(int)
+ * @see android.app.Activity#setVolumeControlStream(int)
*/
public abstract void setVolumeControlStream(int streamType);
@@ -1302,6 +1304,19 @@
public abstract int getVolumeControlStream();
/**
+ * @see android.app.Activity#setMediaController(android.media.session.MediaController)
+ */
+ public void setMediaController(MediaController controller) {
+ }
+
+ /**
+ * @see android.app.Activity#getMediaController()
+ */
+ public MediaController getMediaController() {
+ return null;
+ }
+
+ /**
* Set extra options that will influence the UI for this window.
* @param uiOptions Flags specifying extra options for this window.
*/
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index c06b5d8..034778f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1298,7 +1298,7 @@
*
* @hide
*/
- public Rect shadowInsets = new Rect();
+ public Rect surfaceInsets = new Rect();
/**
* The desired bitmap format. May be one of the constants in
@@ -1580,10 +1580,10 @@
out.writeInt(hasSystemUiListeners ? 1 : 0);
out.writeInt(inputFeatures);
out.writeLong(userActivityTimeout);
- out.writeInt(shadowInsets.left);
- out.writeInt(shadowInsets.top);
- out.writeInt(shadowInsets.right);
- out.writeInt(shadowInsets.bottom);
+ out.writeInt(surfaceInsets.left);
+ out.writeInt(surfaceInsets.top);
+ out.writeInt(surfaceInsets.right);
+ out.writeInt(surfaceInsets.bottom);
}
public static final Parcelable.Creator<LayoutParams> CREATOR
@@ -1626,7 +1626,10 @@
hasSystemUiListeners = in.readInt() != 0;
inputFeatures = in.readInt();
userActivityTimeout = in.readLong();
- shadowInsets.set(in.readInt(), in.readInt(), in.readInt(), in.readInt());
+ surfaceInsets.left = in.readInt();
+ surfaceInsets.top = in.readInt();
+ surfaceInsets.right = in.readInt();
+ surfaceInsets.bottom = in.readInt();
}
@SuppressWarnings({"PointlessBitwiseExpression"})
@@ -1658,7 +1661,7 @@
/** {@hide} */
public static final int TRANSLUCENT_FLAGS_CHANGED = 1<<19;
/** {@hide} */
- public static final int SHADOW_INSETS_CHANGED = 1<<20;
+ public static final int SURFACE_INSETS_CHANGED = 1<<20;
/** {@hide} */
public static final int EVERYTHING_CHANGED = 0xffffffff;
@@ -1794,9 +1797,9 @@
changes |= USER_ACTIVITY_TIMEOUT_CHANGED;
}
- if (!shadowInsets.equals(o.shadowInsets)) {
- shadowInsets.set(o.shadowInsets);
- changes |= SHADOW_INSETS_CHANGED;
+ if (!surfaceInsets.equals(o.surfaceInsets)) {
+ surfaceInsets.set(o.surfaceInsets);
+ changes |= SURFACE_INSETS_CHANGED;
}
return changes;
@@ -1898,8 +1901,8 @@
if (userActivityTimeout >= 0) {
sb.append(" userActivityTimeout=").append(userActivityTimeout);
}
- if (!shadowInsets.equals(Insets.NONE)) {
- sb.append(" shadowInsets=").append(shadowInsets);
+ if (!surfaceInsets.equals(Insets.NONE)) {
+ sb.append(" surfaceInsets=").append(surfaceInsets);
}
sb.append('}');
return sb.toString();
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index cbc38c6..94e2c0e 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -18,6 +18,7 @@
import android.Manifest;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
@@ -76,6 +77,9 @@
public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002;
/** @hide */
+ public static final int STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED = 0x00000004;
+
+ /** @hide */
public static final int INVERSION_DISABLED = -1;
/** @hide */
@@ -127,13 +131,19 @@
boolean mIsTouchExplorationEnabled;
+ boolean mIsHighTextContrastEnabled;
+
private final CopyOnWriteArrayList<AccessibilityStateChangeListener>
mAccessibilityStateChangeListeners = new CopyOnWriteArrayList<
AccessibilityStateChangeListener>();
private final CopyOnWriteArrayList<TouchExplorationStateChangeListener>
mTouchExplorationStateChangeListeners = new CopyOnWriteArrayList<
- TouchExplorationStateChangeListener>();
+ TouchExplorationStateChangeListener>();
+
+ private final CopyOnWriteArrayList<HighTextContrastChangeListener>
+ mHighTextContrastStateChangeListeners = new CopyOnWriteArrayList<
+ HighTextContrastChangeListener>();
/**
* Listener for the system accessibility state. To listen for changes to the
@@ -166,6 +176,24 @@
public void onTouchExplorationStateChanged(boolean enabled);
}
+ /**
+ * Listener for the system high text contrast state. To listen for changes to
+ * the high text contrast state on the device, implement this interface and
+ * register it with the system by calling
+ * {@link #addHighTextContrastStateChangeListener}.
+ *
+ * @hide
+ */
+ public interface HighTextContrastChangeListener {
+
+ /**
+ * Called when the high text contrast enabled state changes.
+ *
+ * @param enabled Whether high text contrast is enabled.
+ */
+ public void onHighTextContrastStateChanged(boolean enabled);
+ }
+
private final IAccessibilityManagerClient.Stub mClient =
new IAccessibilityManagerClient.Stub() {
public void setState(int state) {
@@ -262,6 +290,27 @@
}
/**
+ * Returns if the high text contrast in the system is enabled.
+ * <p>
+ * <strong>Note:</strong> You need to query this only if you application is
+ * doing its own rendering and does not rely on the platform rendering pipeline.
+ * </p>
+ *
+ * @return True if high text contrast is enabled, false otherwise.
+ *
+ * @hide
+ */
+ public boolean isHighTextContrastEnabled() {
+ synchronized (mLock) {
+ IAccessibilityManager service = getServiceLocked();
+ if (service == null) {
+ return false;
+ }
+ return mIsHighTextContrastEnabled;
+ }
+ }
+
+ /**
* Sends an {@link AccessibilityEvent}.
*
* @param event The event to send.
@@ -434,7 +483,7 @@
* @return True if successfully registered.
*/
public boolean addAccessibilityStateChangeListener(
- AccessibilityStateChangeListener listener) {
+ @NonNull AccessibilityStateChangeListener listener) {
// Final CopyOnArrayList - no lock needed.
return mAccessibilityStateChangeListeners.add(listener);
}
@@ -446,7 +495,7 @@
* @return True if successfully unregistered.
*/
public boolean removeAccessibilityStateChangeListener(
- AccessibilityStateChangeListener listener) {
+ @NonNull AccessibilityStateChangeListener listener) {
// Final CopyOnArrayList - no lock needed.
return mAccessibilityStateChangeListeners.remove(listener);
}
@@ -459,7 +508,7 @@
* @return True if successfully registered.
*/
public boolean addTouchExplorationStateChangeListener(
- TouchExplorationStateChangeListener listener) {
+ @NonNull TouchExplorationStateChangeListener listener) {
// Final CopyOnArrayList - no lock needed.
return mTouchExplorationStateChangeListeners.add(listener);
}
@@ -471,12 +520,41 @@
* @return True if successfully unregistered.
*/
public boolean removeTouchExplorationStateChangeListener(
- TouchExplorationStateChangeListener listener) {
+ @NonNull TouchExplorationStateChangeListener listener) {
// Final CopyOnArrayList - no lock needed.
return mTouchExplorationStateChangeListeners.remove(listener);
}
/**
+ * Registers a {@link HighTextContrastChangeListener} for changes in
+ * the global high text contrast state of the system.
+ *
+ * @param listener The listener.
+ * @return True if successfully registered.
+ *
+ * @hide
+ */
+ public boolean addHighTextContrastStateChangeListener(
+ @NonNull HighTextContrastChangeListener listener) {
+ // Final CopyOnArrayList - no lock needed.
+ return mHighTextContrastStateChangeListeners.add(listener);
+ }
+
+ /**
+ * Unregisters a {@link HighTextContrastChangeListener}.
+ *
+ * @param listener The listener.
+ * @return True if successfully unregistered.
+ *
+ * @hide
+ */
+ public boolean removeHighTextContrastStateChangeListener(
+ @NonNull HighTextContrastChangeListener listener) {
+ // Final CopyOnArrayList - no lock needed.
+ return mHighTextContrastStateChangeListeners.remove(listener);
+ }
+
+ /**
* Sets the current state and notifies listeners, if necessary.
*
* @param stateFlags The state flags.
@@ -485,13 +563,17 @@
final boolean enabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
final boolean touchExplorationEnabled =
(stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
+ final boolean highTextContrastEnabled =
+ (stateFlags & STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED) != 0;
final boolean wasEnabled = mIsEnabled;
final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled;
+ final boolean wasHighTextContrastEnabled = mIsHighTextContrastEnabled;
// Ensure listeners get current state from isZzzEnabled() calls.
mIsEnabled = enabled;
mIsTouchExplorationEnabled = touchExplorationEnabled;
+ mIsHighTextContrastEnabled = highTextContrastEnabled;
if (wasEnabled != enabled) {
mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED);
@@ -500,6 +582,10 @@
if (wasTouchExplorationEnabled != touchExplorationEnabled) {
mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_EXPLORATION_STATE_CHANGED);
}
+
+ if (wasHighTextContrastEnabled != highTextContrastEnabled) {
+ mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED);
+ }
}
/**
@@ -600,9 +686,25 @@
}
}
+ /**
+ * Notifies the registered {@link HighTextContrastChangeListener}s.
+ */
+ private void handleNotifyHighTextContrastStateChanged() {
+ final boolean isHighTextContrastEnabled;
+ synchronized (mLock) {
+ isHighTextContrastEnabled = mIsHighTextContrastEnabled;
+ }
+ final int listenerCount = mHighTextContrastStateChangeListeners.size();
+ for (int i = 0; i < listenerCount; i++) {
+ mHighTextContrastStateChangeListeners.get(i)
+ .onHighTextContrastStateChanged(isHighTextContrastEnabled);
+ }
+ }
+
private final class MyHandler extends Handler {
public static final int MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED = 1;
public static final int MSG_NOTIFY_EXPLORATION_STATE_CHANGED = 2;
+ public static final int MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED = 3;
public MyHandler(Looper looper) {
super(looper, null, false);
@@ -617,7 +719,11 @@
case MSG_NOTIFY_EXPLORATION_STATE_CHANGED: {
handleNotifyTouchExplorationStateChanged();
- }
+ } break;
+
+ case MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED: {
+ handleNotifyHighTextContrastStateChanged();
+ } break;
}
}
}
diff --git a/core/java/android/webkit/WebResourceRequest.java b/core/java/android/webkit/WebResourceRequest.java
new file mode 100644
index 0000000..dc7c808
--- /dev/null
+++ b/core/java/android/webkit/WebResourceRequest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.webkit;
+
+import android.net.Uri;
+
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Encompasses parameters to the {@link WebViewClient#shouldInterceptRequest} method.
+ */
+public interface WebResourceRequest {
+ /**
+ * Gets the URL for which the resource request was made.
+ *
+ * @return the URL for which the resource request was made.
+ */
+ Uri getUrl();
+
+ /**
+ * Gets whether the request was made for the main frame.
+ *
+ * @return whether the request was made for the main frame. Will be false for iframes,
+ * for example.
+ */
+ boolean isForMainFrame();
+
+ /**
+ * Gets whether a gesture was associated with the request.
+ * <p>
+ * <strong>IMPORTANT:</strong>
+ * This should not be used to implement any form of security. It is possible for the content
+ * to spoof this.
+ *
+ * @return whether a gesture was associated with the request.
+ */
+ boolean hasUserGestureInsecure();
+
+ /**
+ * Gets the method associated with the request, for example "GET".
+ *
+ * @return the method associated with the request.
+ */
+ String getMethod();
+
+ /**
+ * Gets the headers associated with the request. These are represented as a mapping of header
+ * name to header value.
+ *
+ * @return the headers associated with the request.
+ */
+ Map<String, String> getRequestHeaders();
+}
diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java
index f21e2b4..ad6e9aa 100644
--- a/core/java/android/webkit/WebResourceResponse.java
+++ b/core/java/android/webkit/WebResourceResponse.java
@@ -17,6 +17,7 @@
package android.webkit;
import java.io.InputStream;
+import java.util.Map;
/**
* Encapsulates a resource response. Applications can return an instance of this
@@ -24,9 +25,11 @@
* response when the WebView requests a particular resource.
*/
public class WebResourceResponse {
- // Accessed by jni, do not rename without modifying the jni code.
private String mMimeType;
private String mEncoding;
+ private int mStatusCode;
+ private String mReasonPhrase;
+ private Map<String, String> mResponseHeaders;
private InputStream mInputStream;
/**
@@ -47,6 +50,28 @@
}
/**
+ * Constructs a resource response with the given parameters. Callers must
+ * implement {@link InputStream#read(byte[]) InputStream.read(byte[])} for
+ * the input stream.
+ *
+ * @param mimeType the resource response's MIME type, for example text/html
+ * @param encoding the resource response's encoding
+ * @param statusCode the status code needs to be in the ranges [100, 299], [400, 599].
+ * Causing a redirect by specifying a 3xx code is not supported.
+ * @param reasonPhrase the phrase describing the status code, for example "OK". Must be non-null
+ * and not empty.
+ * @param responseHeaders the resource response's headers represented as a mapping of header
+ * name -> header value.
+ * @param data the input stream that provides the resource response's data
+ */
+ public WebResourceResponse(String mimeType, String encoding, int statusCode,
+ String reasonPhrase, Map<String, String> responseHeaders, InputStream data) {
+ this(mimeType, encoding, data);
+ setStatusCodeAndReasonPhrase(statusCode, reasonPhrase);
+ setResponseHeaders(responseHeaders);
+ }
+
+ /**
* Sets the resource response's MIME type, for example text/html.
*
* @param mimeType the resource response's MIME type
@@ -84,7 +109,73 @@
}
/**
- * Sets the input stream that provides the resource respone's data. Callers
+ * Sets the resource response's status code and reason phrase.
+ *
+ * @param statusCode the status code needs to be in the ranges [100, 299], [400, 599].
+ * Causing a redirect by specifying a 3xx code is not supported.
+ * @param reasonPhrase the phrase describing the status code, for example "OK". Must be non-null
+ * and not empty.
+ */
+ public void setStatusCodeAndReasonPhrase(int statusCode, String reasonPhrase) {
+ if (statusCode < 100)
+ throw new IllegalArgumentException("statusCode can't be less than 100.");
+ if (statusCode > 599)
+ throw new IllegalArgumentException("statusCode can't be greater than 599.");
+ if (statusCode > 299 && statusCode < 400)
+ throw new IllegalArgumentException("statusCode can't be in the [300, 399] range.");
+ if (reasonPhrase == null)
+ throw new IllegalArgumentException("reasonPhrase can't be null.");
+ if (reasonPhrase.trim().isEmpty())
+ throw new IllegalArgumentException("reasonPhrase can't be empty.");
+ for (int i = 0; i < reasonPhrase.length(); i++) {
+ int c = reasonPhrase.charAt(i);
+ if (c > 0x7F) {
+ throw new IllegalArgumentException(
+ "reasonPhrase can't contain non-ASCII characters.");
+ }
+ }
+ mStatusCode = statusCode;
+ mReasonPhrase = reasonPhrase;
+ }
+
+ /**
+ * Gets the resource response's status code.
+ *
+ * @return the resource response's status code.
+ */
+ public int getStatusCode() {
+ return mStatusCode;
+ }
+
+ /**
+ * Gets the description of the resource response's status code.
+ *
+ * @return the description of the resource response's status code.
+ */
+ public String getReasonPhrase() {
+ return mReasonPhrase;
+ }
+
+ /**
+ * Sets the headers for the resource response.
+ *
+ * @param headers mapping of header name -> header value.
+ */
+ public void setResponseHeaders(Map<String, String> headers) {
+ mResponseHeaders = headers;
+ }
+
+ /**
+ * Gets the headers for the resource response.
+ *
+ * @return the headers for the resource response.
+ */
+ public Map<String, String> getResponseHeaders() {
+ return mResponseHeaders;
+ }
+
+ /**
+ * Sets the input stream that provides the resource response's data. Callers
* must implement {@link InputStream#read(byte[]) InputStream.read(byte[])}.
*
* @param data the input stream that provides the resource response's data
@@ -94,7 +185,7 @@
}
/**
- * Gets the input stream that provides the resource respone's data.
+ * Gets the input stream that provides the resource response's data.
*
* @return the input stream that provides the resource response's data
*/
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 290a574..adf4803 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2471,4 +2471,16 @@
mProvider.getViewDelegate().preDispatchDraw(canvas);
super.dispatchDraw(canvas);
}
+
+ @Override
+ public void onStartTemporaryDetach() {
+ super.onStartTemporaryDetach();
+ mProvider.getViewDelegate().onStartTemporaryDetach();
+ }
+
+ @Override
+ public void onFinishTemporaryDetach() {
+ super.onFinishTemporaryDetach();
+ mProvider.getViewDelegate().onFinishTemporaryDetach();
+ }
}
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 62b80c4a..d52dd60 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -96,13 +96,36 @@
* @return A {@link android.webkit.WebResourceResponse} containing the
* response information or null if the WebView should load the
* resource itself.
+ * @deprecated Use {@link #shouldInterceptRequest(WebView, WebResourceRequest)
+ * shouldInterceptRequest(WebView, WebResourceRequest)} instead.
*/
+ @Deprecated
public WebResourceResponse shouldInterceptRequest(WebView view,
String url) {
return null;
}
/**
+ * Notify the host application of a resource request and allow the
+ * application to return the data. If the return value is null, the WebView
+ * will continue to load the resource as usual. Otherwise, the return
+ * response and data will be used. NOTE: This method is called on a thread
+ * other than the UI thread so clients should exercise caution
+ * when accessing private data or the view system.
+ *
+ * @param view The {@link android.webkit.WebView} that is requesting the
+ * resource.
+ * @param request Object containing the details of the request.
+ * @return A {@link android.webkit.WebResourceResponse} containing the
+ * response information or null if the WebView should load the
+ * resource itself.
+ */
+ public WebResourceResponse shouldInterceptRequest(WebView view,
+ WebResourceRequest request) {
+ return shouldInterceptRequest(view, request.getUrl().toString());
+ }
+
+ /**
* Notify the host application that there have been an excessive number of
* HTTP redirects. As the host application if it would like to continue
* trying to load the resource. The default behavior is to send the cancel
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 5081ff5..b6fd363 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -360,6 +360,10 @@
public void setLayerType(int layerType, Paint paint);
public void preDispatchDraw(Canvas canvas);
+
+ public void onStartTemporaryDetach();
+
+ public void onFinishTemporaryDetach();
}
interface ScrollDelegate {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 9701c6f..aa0b94f 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -36,7 +36,6 @@
import android.util.AttributeSet;
import android.util.Log;
import android.util.LongSparseArray;
-import android.util.MathUtils;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.StateSet;
@@ -61,8 +60,6 @@
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.inputmethod.BaseInputConnection;
@@ -7269,290 +7266,4 @@
}
}
}
-
- /**
- * Abstract position scroller that handles sub-position scrolling but has no
- * understanding of layout.
- */
- abstract class AbsSubPositionScroller extends AbsPositionScroller {
- private static final int DURATION_AUTO = -1;
-
- private static final int DURATION_AUTO_MIN = 100;
- private static final int DURATION_AUTO_MAX = 500;
-
- private final SubScroller mSubScroller = new SubScroller();
-
- /**
- * The target offset in pixels between the top of the list and the top
- * of the target position.
- */
- private int mOffset;
-
- /**
- * Scroll the minimum amount to get the target view entirely on-screen.
- */
- private void scrollToPosition(final int targetPosition, final boolean useOffset,
- final int offset, final int boundPosition, final int duration) {
- stop();
-
- if (mDataChanged) {
- // Wait until we're back in a stable state to try this.
- mPositionScrollAfterLayout = new Runnable() {
- @Override
- public void run() {
- scrollToPosition(
- targetPosition, useOffset, offset, boundPosition, duration);
- }
- };
- return;
- }
-
- if (mAdapter == null) {
- // Can't scroll anywhere without an adapter.
- return;
- }
-
- final int itemCount = getCount();
- final int clampedPosition = MathUtils.constrain(targetPosition, 0, itemCount - 1);
- final int clampedBoundPosition = MathUtils.constrain(boundPosition, -1, itemCount - 1);
- final int firstPosition = getFirstVisiblePosition();
- final int lastPosition = firstPosition + getChildCount();
- final int targetRow = getRowForPosition(clampedPosition);
- final int firstRow = getRowForPosition(firstPosition);
- final int lastRow = getRowForPosition(lastPosition);
- if (useOffset || targetRow <= firstRow) {
- // Offset so the target row is top-aligned.
- mOffset = offset;
- } else if (targetRow >= lastRow - 1) {
- // Offset so the target row is bottom-aligned.
- final int listHeight = getHeight() - getPaddingTop() - getPaddingBottom();
- mOffset = getHeightForPosition(clampedPosition) - listHeight;
- } else {
- // Don't scroll, target is entirely on-screen.
- return;
- }
-
- float endSubRow = targetRow;
- if (clampedBoundPosition != INVALID_POSITION) {
- final int boundRow = getRowForPosition(clampedBoundPosition);
- if (boundRow >= firstRow && boundRow < lastRow && boundRow != targetRow) {
- endSubRow = computeBoundSubRow(targetRow, boundRow);
- }
- }
-
- final View firstChild = getChildAt(0);
- if (firstChild == null) {
- return;
- }
-
- final int firstChildHeight = firstChild.getHeight();
- final float startOffsetRatio;
- if (firstChildHeight == 0) {
- startOffsetRatio = 0;
- } else {
- startOffsetRatio = -firstChild.getTop() / (float) firstChildHeight;
- }
-
- final float startSubRow = MathUtils.constrain(
- firstRow + startOffsetRatio, 0, getCount());
- if (startSubRow == endSubRow && mOffset == 0) {
- // Don't scroll, target is already in position.
- return;
- }
-
- final int durationMillis;
- if (duration == DURATION_AUTO) {
- final float subRowDelta = Math.abs(startSubRow - endSubRow);
- durationMillis = (int) MathUtils.lerp(
- DURATION_AUTO_MIN, DURATION_AUTO_MAX, subRowDelta / getCount());
- } else {
- durationMillis = duration;
- }
-
- mSubScroller.startScroll(startSubRow, endSubRow, durationMillis);
-
- postOnAnimation(mAnimationFrame);
- }
-
- /**
- * Given a target row and offset, computes the sub-row position that
- * aligns with the top of the list. If the offset is negative, the
- * resulting sub-row will be smaller than the target row.
- */
- private float resolveOffset(int targetRow, int offset) {
- // Compute the target sub-row position by finding the actual row
- // indicated by the target and offset.
- int remainingOffset = offset;
- int targetHeight = getHeightForRow(targetRow);
- if (offset < 0) {
- // Subtract row heights until we find the right row.
- while (targetRow > 0 && remainingOffset < 0) {
- remainingOffset += targetHeight;
- targetRow--;
- targetHeight = getHeightForRow(targetRow);
- }
- } else if (offset > 0) {
- // Add row heights until we find the right row.
- while (targetRow < getCount() - 1 && remainingOffset > targetHeight) {
- remainingOffset -= targetHeight;
- targetRow++;
- targetHeight = getHeightForRow(targetRow);
- }
- }
-
- final float targetOffsetRatio;
- if (remainingOffset < 0 || targetHeight == 0) {
- targetOffsetRatio = 0;
- } else {
- targetOffsetRatio = remainingOffset / (float) targetHeight;
- }
-
- return targetRow + targetOffsetRatio;
- }
-
- private float computeBoundSubRow(int targetRow, int boundRow) {
- final float targetSubRow = resolveOffset(targetRow, mOffset);
- mOffset = 0;
-
- // The target row is below the bound row, so the end position would
- // push the bound position above the list. Abort!
- if (targetSubRow >= boundRow) {
- return boundRow;
- }
-
- // Compute the closest possible sub-position that wouldn't push the
- // bound position's view further below the list.
- final int listHeight = getHeight() - getPaddingTop() - getPaddingBottom();
- final int boundHeight = getHeightForRow(boundRow);
- final float boundSubRow = resolveOffset(boundRow, -listHeight + boundHeight);
-
- return Math.max(boundSubRow, targetSubRow);
- }
-
- @Override
- public void start(int position) {
- scrollToPosition(position, false, 0, INVALID_POSITION, DURATION_AUTO);
- }
-
- @Override
- public void start(int position, int boundPosition) {
- scrollToPosition(position, false, 0, boundPosition, DURATION_AUTO);
- }
-
- @Override
- public void startWithOffset(int position, int offset) {
- scrollToPosition(position, true, offset, INVALID_POSITION, DURATION_AUTO);
- }
-
- @Override
- public void startWithOffset(int position, int offset, int duration) {
- scrollToPosition(position, true, offset, INVALID_POSITION, duration);
- }
-
- @Override
- public void stop() {
- removeCallbacks(mAnimationFrame);
- }
-
- /**
- * Returns the height of a row, which is computed as the maximum height of
- * the items in the row.
- *
- * @param row the row index
- * @return row height in pixels
- */
- public abstract int getHeightForRow(int row);
-
- /**
- * Returns the row for the specified item position.
- *
- * @param position the item position
- * @return the row index
- */
- public abstract int getRowForPosition(int position);
-
- /**
- * Returns the first item position within the specified row.
- *
- * @param row the row
- * @return the position of the first item in the row
- */
- public abstract int getFirstPositionForRow(int row);
-
- private void onAnimationFrame() {
- final boolean shouldPost = mSubScroller.computePosition();
- final float subRow = mSubScroller.getPosition();
-
- final int row = (int) subRow;
- final int position = getFirstPositionForRow(row);
- if (position >= getCount()) {
- // Invalid position, abort scrolling.
- return;
- }
-
- final int rowHeight = getHeightForRow(row);
- final int offset = (int) (rowHeight * (subRow - row));
- final int addOffset = (int) (mOffset * mSubScroller.getInterpolatedValue());
- setSelectionFromTop(position, -offset - addOffset);
-
- if (shouldPost) {
- postOnAnimation(mAnimationFrame);
- }
- }
-
- private Runnable mAnimationFrame = new Runnable() {
- @Override
- public void run() {
- onAnimationFrame();
- }
- };
- }
-
- /**
- * Scroller capable of returning floating point positions.
- */
- static class SubScroller {
- private static final Interpolator INTERPOLATOR = new AccelerateDecelerateInterpolator();
-
- private float mStartPosition;
- private float mEndPosition;
- private long mStartTime;
- private long mDuration;
-
- private float mPosition;
- private float mInterpolatedValue;
-
- public void startScroll(float startPosition, float endPosition, int duration) {
- mStartPosition = startPosition;
- mEndPosition = endPosition;
- mDuration = duration;
-
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mPosition = startPosition;
- mInterpolatedValue = 0;
- }
-
- public boolean computePosition() {
- final long elapsed = AnimationUtils.currentAnimationTimeMillis() - mStartTime;
- final float value;
- if (mDuration <= 0) {
- value = 1;
- } else {
- value = MathUtils.constrain(elapsed / (float) mDuration, 0, 1);
- }
-
- mInterpolatedValue = INTERPOLATOR.getInterpolation(value);
- mPosition = (mEndPosition - mStartPosition) * mInterpolatedValue + mStartPosition;
-
- return elapsed < mDuration;
- }
-
- public float getPosition() {
- return mPosition;
- }
-
- public float getInterpolatedValue() {
- return mInterpolatedValue;
- }
- }
}
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 2c1a77c..8f49fb8 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -17,7 +17,9 @@
package android.widget;
import android.annotation.Widget;
+import android.app.UiModeManager;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.os.Parcel;
@@ -49,6 +51,8 @@
import libcore.icu.ICU;
+import static android.os.Build.VERSION_CODES.L;
+
/**
* This class is a widget for selecting a date. The date can be selected by a
* year, month, and day spinners or a {@link CalendarView}. The set of spinners
@@ -70,6 +74,15 @@
* @attr ref android.R.styleable#DatePicker_minDate
* @attr ref android.R.styleable#DatePicker_spinnersShown
* @attr ref android.R.styleable#DatePicker_calendarViewShown
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekBackgroundColor
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekTextAppearance
+ * @attr ref android.R.styleable#DatePicker_dateSelectorBackgroundColor
+ * @attr ref android.R.styleable#DatePicker_dateSelectorMonthTextAppearance
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfMonthTextAppearance
+ * @attr ref android.R.styleable#DatePicker_dateSelectorYearTextAppearance
+ * @attr ref android.R.styleable#DatePicker_dateSelectorYearListItemTextAppearance
+ * @attr ref android.R.styleable#DatePicker_dateSelectorYearListSelectedCircleColor
+ * @attr ref android.R.styleable#DatePicker_calendarTextColor
*/
@Widget
public class DatePicker extends FrameLayout {
@@ -78,6 +91,10 @@
private DatePickerDelegate mDelegate;
+ private int mDefStyleAttr;
+ private int mDefStyleRes;
+ private Context mContext;
+
/**
* The callback used to indicate the user changes\d the date.
*/
@@ -110,7 +127,65 @@
public DatePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mDelegate = new LegacyDatePickerDelegate(this, context, attrs, defStyleAttr, defStyleRes);
+ mContext = context;
+ mDefStyleAttr = defStyleAttr;
+ mDefStyleRes = defStyleRes;
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker,
+ mDefStyleAttr, mDefStyleRes);
+
+ // Create the correct UI delegate. Default is the legacy one.
+ final boolean isLegacyMode = a.getBoolean(R.styleable.DatePicker_legacyMode,
+ isLegacyMode());
+
+ a.recycle();
+
+ setLegacyMode(isLegacyMode, attrs);
+ }
+
+ private boolean isLegacyMode() {
+ UiModeManager uiModeManager =
+ (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
+ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
+ return true;
+ }
+ final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
+ return targetSdkVersion < L;
+ }
+
+ private DatePickerDelegate createLegacyUIDelegate(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ return new LegacyDatePickerDelegate(this, context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ private DatePickerDelegate createNewUIDelegate(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ return new android.widget.DatePickerDelegate(this, context, attrs, defStyleAttr,
+ defStyleRes);
+ }
+
+ /**
+ * @hide
+ */
+ public void setLegacyMode(boolean isLegacyMode, AttributeSet attrs) {
+ removeAllViewsInLayout();
+ mDelegate = isLegacyMode ?
+ createLegacyUIDelegate(mContext, attrs, mDefStyleAttr, mDefStyleRes) :
+ createNewUIDelegate(mContext, attrs, mDefStyleAttr, mDefStyleRes);
+ }
+
+ /**
+ * @hide
+ */
+ public void setShowDoneButton(boolean showDoneButton) {
+ mDelegate.setShowDoneButton(showDoneButton);
+ }
+
+ /**
+ * @hide
+ */
+ public void setDismissCallback(DatePickerDismissCallback callback) {
+ mDelegate.setDismissCallback(callback);
}
/**
@@ -129,7 +204,7 @@
}
/**
- * Updates the current date.
+ * Update the current date.
*
* @param year The year.
* @param month The month which is <strong>starting from zero</strong>.
@@ -171,7 +246,7 @@
* @return The minimal supported date.
*/
public long getMinDate() {
- return mDelegate.getMinDate();
+ return mDelegate.getMinDate().getTimeInMillis();
}
/**
@@ -196,7 +271,7 @@
* @return The maximal supported date.
*/
public long getMaxDate() {
- return mDelegate.getMaxDate();
+ return mDelegate.getMaxDate().getTimeInMillis();
}
/**
@@ -300,6 +375,182 @@
mDelegate.setSpinnersShown(shown);
}
+ /**
+ * Sets the background color for the date selector's day of week.
+ *
+ * @param color The background color.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekBackgroundColor
+ */
+ public void setDateSelectorDayOfWeekBackgroundColor(int color) {
+ mDelegate.setDateSelectorDayOfWeekBackgroundColor(color);
+ }
+
+ /**
+ * Gets the background color for the date selector's day of week.
+ *
+ * @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekBackgroundColor
+ */
+ public int getDateSelectorDayOfWeekBackgroundColor() {
+ return mDelegate.getDateSelectorDayOfWeekBackgroundColor();
+ }
+
+ /**
+ * Sets the text appearance for the date selector's day of week.
+ *
+ * @param resId The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekTextAppearance
+ */
+ public void setDateSelectorDayOfWeekTextAppearance(int resId) {
+ mDelegate.setDateSelectorDayOfWeekTextAppearance(resId);
+ }
+
+ /**
+ * Gets the text appearance for the date selector's day of week.
+ *
+ * @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfWeekTextAppearance
+ */
+ public int getDateSelectorDayOfWeekTextAppearance() {
+ return mDelegate.getDateSelectorDayOfWeekTextAppearance();
+ }
+
+ /**
+ * Sets the background color for the date selector's.
+ *
+ * @param color The background color.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorBackgroundColor
+ */
+ public void setDateSelectorBackgroundColor(int color) {
+ mDelegate.setDateSelectorBackgroundColor(color);
+ }
+
+ /**
+ * Gets the background color for the date selector's.
+ *
+ * @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorBackgroundColor
+ */
+ public int getDateSelectorBackgroundColor() {
+ return mDelegate.getDateSelectorBackgroundColor();
+ }
+
+ /**
+ * Sets the text appearance for the date selector's month.
+ *
+ * @param resId The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorMonthTextAppearance
+ */
+ public void setDateSelectorMonthTextAppearance(int resId) {
+ mDelegate.setDateSelectorMonthTextAppearance(resId);
+ }
+
+ /**
+ * Gets the text appearance for the date selector's month.
+ *
+ * @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorMonthTextAppearance
+ */
+ public int getDateSelectorMonthTextAppearance() {
+ return mDelegate.getDateSelectorMonthTextAppearance();
+ }
+
+ /**
+ * Sets the text appearance for the date selector's day of month.
+ *
+ * @param resId The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfMonthTextAppearance
+ */
+ public void setDateSelectorDayOfMonthTextAppearance(int resId) {
+ mDelegate.setDateSelectorDayOfMonthTextAppearance(resId);
+ }
+
+ /**
+ * Gets the text appearance for the date selector's day of month.
+ *
+ * @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorDayOfMonthTextAppearance
+ */
+ public int getDateSelectorDayOfMonthTextAppearance() {
+ return mDelegate.getDateSelectorDayOfMonthTextAppearance();
+ }
+
+ /**
+ * Sets the text appearance for the date selector's year.
+ *
+ * @param resId The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorYearTextAppearance
+ */
+ public void setDateSelectorYearTextAppearance(int resId) {
+ mDelegate.setDateSelectorYearTextAppearance(resId);
+ }
+
+ /**
+ * Gets the text appearance for the date selector's year.
+ *
+ * @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorYearTextAppearance
+ */
+ public int getDateSelectorYearTextAppearance() {
+ return mDelegate.getDateSelectorYearTextAppearance();
+ }
+
+ /**
+ * Sets the text appearance for the year list item.
+ *
+ * @param resId The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorYearListItemTextAppearance
+ */
+ public void setDateSelectorYearListItemTextAppearance(int resId) {
+ mDelegate.setDateSelectorYearListItemTextAppearance(resId);
+ }
+
+ /**
+ * Gets the text appearance for the year list item.
+ *
+ * @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#DatePicker_dateSelectorYearListItemTextAppearance
+ */
+ public int getDateSelectorYearListItemTextAppearance() {
+ return mDelegate.getDateSelectorYearListItemTextAppearance();
+ }
+
+ /**
+ * Sets the text color state list for the calendar.
+ *
+ * @param colors The text color state list.
+ *
+ * @attr ref android.R.styleable#DatePicker_calendarTextColor
+ */
+ public void setCalendarTextColor(ColorStateList colors) {
+ mDelegate.setCalendarTextColor(colors);
+ }
+
+ /**
+ * Gets the text color state list for the calendar.
+ *
+ * @return The text color state list for the calendar.
+ *
+ * @attr ref android.R.styleable#DatePicker_calendarTextColor
+ */
+ public ColorStateList getCalendarTextColor() {
+ return mDelegate.getCalendarTextColors();
+ }
+
// Override so we are in complete control of save / restore for this widget.
@Override
protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
@@ -323,6 +574,8 @@
* A delegate interface that defined the public API of the DatePicker. Allows different
* DatePicker implementations. This would need to be implemented by the DatePicker delegates
* for the real behavior.
+ *
+ * @hide
*/
interface DatePickerDelegate {
void init(int year, int monthOfYear, int dayOfMonth,
@@ -335,15 +588,42 @@
int getDayOfMonth();
void setMinDate(long minDate);
- long getMinDate();
+ Calendar getMinDate();
void setMaxDate(long maxDate);
- long getMaxDate();
+ Calendar getMaxDate();
void setEnabled(boolean enabled);
boolean isEnabled();
- CalendarView getCalendarView ();
+ void setDateSelectorDayOfWeekBackgroundColor(int color);
+ int getDateSelectorDayOfWeekBackgroundColor();
+
+ void setDateSelectorDayOfWeekTextAppearance(int resId);
+ int getDateSelectorDayOfWeekTextAppearance();
+
+ void setDateSelectorBackgroundColor(int color);
+ int getDateSelectorBackgroundColor();
+
+ void setDateSelectorMonthTextAppearance(int resId);
+ int getDateSelectorMonthTextAppearance();
+
+ void setDateSelectorDayOfMonthTextAppearance(int resId);
+ int getDateSelectorDayOfMonthTextAppearance();
+
+ void setDateSelectorYearTextAppearance(int resId);
+ int getDateSelectorYearTextAppearance();
+
+ void setDateSelectorYearListItemTextAppearance(int resId);
+ int getDateSelectorYearListItemTextAppearance();
+
+ void setDateSelectorYearListSelectedCircleColor(int color);
+ int getDateSelectorYearListSelectedCircleColor();
+
+ void setCalendarTextColor(ColorStateList colors);
+ ColorStateList getCalendarTextColors();
+
+ CalendarView getCalendarView();
void setCalendarViewShown(boolean shown);
boolean getCalendarViewShown();
@@ -351,6 +631,9 @@
void setSpinnersShown(boolean shown);
boolean getSpinnersShown();
+ void setShowDoneButton(boolean showDoneButton);
+ void setDismissCallback(DatePickerDismissCallback callback);
+
void onConfigurationChanged(Configuration newConfig);
void dispatchRestoreInstanceState(SparseArray<Parcelable> container);
@@ -366,7 +649,7 @@
/**
* An abstract class which can be used as a start for DatePicker implementations
*/
- abstract static class AbstractTimePickerDelegate implements DatePickerDelegate {
+ abstract static class AbstractDatePickerDelegate implements DatePickerDelegate {
// The delegator
protected DatePicker mDelegator;
@@ -379,7 +662,7 @@
// Callbacks
protected OnDateChangedListener mOnDateChangedListener;
- public AbstractTimePickerDelegate(DatePicker delegator, Context context) {
+ public AbstractDatePickerDelegate(DatePicker delegator, Context context) {
mDelegator = delegator;
mContext = context;
@@ -396,9 +679,18 @@
}
/**
+ * A callback interface for dismissing the DatePicker when included into a Dialog
+ *
+ * @hide
+ */
+ public static interface DatePickerDismissCallback {
+ void dismiss(DatePicker view, boolean isCancel, int year, int month, int dayOfMonth);
+ }
+
+ /**
* A delegate implementing the basic DatePicker
*/
- private static class LegacyDatePickerDelegate extends AbstractTimePickerDelegate {
+ private static class LegacyDatePickerDelegate extends AbstractDatePickerDelegate {
private static final String DATE_FORMAT = "MM/dd/yyyy";
@@ -466,7 +758,7 @@
String minDate = attributesArray.getString(R.styleable.DatePicker_minDate);
String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate);
int layoutResourceId = attributesArray.getResourceId(
- R.styleable.DatePicker_internalLayout, R.layout.date_picker);
+ R.styleable.DatePicker_legacyLayout, R.layout.date_picker_legacy);
attributesArray.recycle();
LayoutInflater inflater = (LayoutInflater) context
@@ -643,8 +935,10 @@
}
@Override
- public long getMinDate() {
- return mCalendarView.getMinDate();
+ public Calendar getMinDate() {
+ final Calendar minDate = Calendar.getInstance();
+ minDate.setTimeInMillis(mCalendarView.getMinDate());
+ return minDate;
}
@Override
@@ -664,8 +958,10 @@
}
@Override
- public long getMaxDate() {
- return mCalendarView.getMaxDate();
+ public Calendar getMaxDate() {
+ final Calendar maxDate = Calendar.getInstance();
+ maxDate.setTimeInMillis(mCalendarView.getMaxDate());
+ return maxDate;
}
@Override
@@ -683,6 +979,87 @@
}
@Override
+ public void setDateSelectorDayOfWeekBackgroundColor(int color) {
+ }
+
+ @Override
+ public int getDateSelectorDayOfWeekBackgroundColor() {
+ return 0;
+ }
+
+ @Override
+ public void setDateSelectorDayOfWeekTextAppearance(int resId) {
+ }
+
+ @Override
+ public int getDateSelectorDayOfWeekTextAppearance() {
+ return 0;
+ }
+
+ @Override
+ public void setDateSelectorBackgroundColor(int color) {
+ }
+
+ @Override
+ public int getDateSelectorBackgroundColor() {
+ return 0;
+ }
+
+ @Override
+ public void setDateSelectorMonthTextAppearance(int resId) {
+ }
+
+ @Override
+ public int getDateSelectorMonthTextAppearance() {
+ return 0;
+ }
+
+ @Override
+ public void setDateSelectorDayOfMonthTextAppearance(int resId) {
+ }
+
+ @Override
+ public int getDateSelectorDayOfMonthTextAppearance() {
+ return 0;
+ }
+
+ @Override
+ public void setDateSelectorYearTextAppearance(int resId) {
+ }
+
+ @Override
+ public int getDateSelectorYearTextAppearance() {
+ return 0;
+ }
+
+ @Override
+ public void setDateSelectorYearListItemTextAppearance(int resId) {
+ }
+
+ @Override
+ public int getDateSelectorYearListItemTextAppearance() {
+ return 0;
+ }
+
+ @Override
+ public void setDateSelectorYearListSelectedCircleColor(int color) {
+ }
+
+ @Override
+ public int getDateSelectorYearListSelectedCircleColor() {
+ return 0;
+ }
+
+ @Override
+ public void setCalendarTextColor(ColorStateList colors) {
+ }
+
+ @Override
+ public ColorStateList getCalendarTextColors() {
+ return ColorStateList.valueOf(0);
+ }
+
+ @Override
public CalendarView getCalendarView() {
return mCalendarView;
}
@@ -708,6 +1085,16 @@
}
@Override
+ public void setShowDoneButton(boolean showDoneButton) {
+ // Nothing to do
+ }
+
+ @Override
+ public void setDismissCallback(DatePickerDismissCallback callback) {
+ // Nothing to do
+ }
+
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
setCurrentLocale(newConfig.locale);
}
diff --git a/core/java/android/widget/DatePickerController.java b/core/java/android/widget/DatePickerController.java
new file mode 100644
index 0000000..6a074da
--- /dev/null
+++ b/core/java/android/widget/DatePickerController.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package android.widget;
+
+import java.util.Calendar;
+
+/**
+ * Controller class to communicate among the various components of the date picker dialog.
+ *
+ * @hide
+ */
+interface DatePickerController {
+
+ void onYearSelected(int year);
+
+ void onDayOfMonthSelected(int year, int month, int day);
+
+ void registerOnDateChangedListener(OnDateChangedListener listener);
+
+ void unregisterOnDateChangedListener(OnDateChangedListener listener);
+
+ Calendar getSelectedDay();
+
+ int getFirstDayOfWeek();
+
+ int getMinYear();
+ int getMaxYear();
+
+ int getMinMonth();
+ int getMaxMonth();
+
+ int getMinDay();
+ int getMaxDay();
+
+ void setMinDate(long minDate);
+ Calendar getMinDate();
+
+ void setMaxDate(long maxDate);
+ Calendar getMaxDate();
+
+ void tryVibrate();
+}
diff --git a/core/java/android/widget/DatePickerDelegate.java b/core/java/android/widget/DatePickerDelegate.java
new file mode 100644
index 0000000..31044d4
--- /dev/null
+++ b/core/java/android/widget/DatePickerDelegate.java
@@ -0,0 +1,979 @@
+/*
+ * 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.
+ */
+
+package android.widget;
+
+import android.animation.Keyframe;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.HapticFeedbackConstants;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+
+import com.android.internal.R;
+import com.android.internal.widget.AccessibleDateAnimator;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+
+/**
+ * A delegate for picking up a date (day / month / year).
+ */
+class DatePickerDelegate extends DatePicker.AbstractDatePickerDelegate implements
+ View.OnClickListener, DatePickerController {
+
+ private static final int UNINITIALIZED = -1;
+ private static final int MONTH_AND_DAY_VIEW = 0;
+ private static final int YEAR_VIEW = 1;
+
+ private static final int DEFAULT_START_YEAR = 1900;
+ private static final int DEFAULT_END_YEAR = 2100;
+
+ private static final int PULSE_ANIMATOR_DURATION = 544;
+
+ private static final int ANIMATION_DURATION = 300;
+ private static final int ANIMATION_DELAY = 650;
+
+ private static final int MONTH_INDEX = 0;
+ private static final int DAY_INDEX = 1;
+ private static final int YEAR_INDEX = 2;
+
+ private SimpleDateFormat mYearFormat = new SimpleDateFormat("y", Locale.getDefault());
+ private SimpleDateFormat mDayFormat = new SimpleDateFormat("d", Locale.getDefault());
+
+ private TextView mDayOfWeekView;
+ private LinearLayout mDateLayout;
+ private LinearLayout mMonthAndDayLayout;
+ private TextView mSelectedMonthTextView;
+ private TextView mSelectedDayTextView;
+ private TextView mSelectedYearView;
+ private DayPickerView mDayPickerView;
+ private YearPickerView mYearPickerView;
+
+ private ViewGroup mLayoutButtons;
+
+ private boolean mIsEnabled = true;
+
+ // Accessibility strings.
+ private String mDayPickerDescription;
+ private String mSelectDay;
+ private String mYearPickerDescription;
+ private String mSelectYear;
+
+ private AccessibleDateAnimator mAnimator;
+
+ private DatePicker.OnDateChangedListener mDateChangedListener;
+
+ private boolean mDelayAnimation = true;
+
+ private int mCurrentView = UNINITIALIZED;
+
+ private Calendar mCurrentDate;
+ private Calendar mTempDate;
+ private Calendar mMinDate;
+ private Calendar mMaxDate;
+
+ // For showing the done button when in a Dialog
+ private Button mDoneButton;
+ private boolean mShowDoneButton;
+ private DatePicker.DatePickerDismissCallback mDismissCallback;
+
+ private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>();
+
+ private int mDayOfWeekTextAppearanceResId;
+ private int mMonthTextAppearanceResId;
+ private int mDayOfMonthTextAppearanceResId;
+ private int mYearTextAppearanceResId;
+
+ private int mYearListItemTextAppearanceResId;
+
+ private int mDayOfWeekBackgroundColor;
+ private int mMonthAndDayBackgroundColor;
+
+ private ColorStateList mCalendarTextColors;
+
+ public DatePickerDelegate(DatePicker delegator, Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+
+ super(delegator, context);
+
+ final Locale locale = Locale.getDefault();
+ mMinDate = getCalendarForLocale(mMinDate, locale);
+ mMaxDate = getCalendarForLocale(mMaxDate, locale);
+ mTempDate = getCalendarForLocale(mMaxDate, locale);
+
+ mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
+
+ mMinDate.set(DEFAULT_START_YEAR, 1, 1);
+ mMaxDate.set(DEFAULT_END_YEAR, 12, 31);
+
+ // process style attributes
+ final TypedArray a = mContext.obtainStyledAttributes(attrs,
+ R.styleable.DatePicker, defStyleAttr, defStyleRes);
+
+ final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+
+ final int layoutResourceId = a.getResourceId(
+ R.styleable.DatePicker_internalLayout, R.layout.date_picker_holo);
+
+ View mainView = inflater.inflate(layoutResourceId, null);
+ mDelegator.addView(mainView);
+
+ mDayOfWeekView = (TextView) mainView.findViewById(R.id.date_picker_header);
+ mDateLayout = (LinearLayout) mainView.findViewById(R.id.day_picker_selector_layout);
+ mMonthAndDayLayout = (LinearLayout) mainView.findViewById(
+ R.id.date_picker_month_and_day_layout);
+ mMonthAndDayLayout.setOnClickListener(this);
+ mSelectedMonthTextView = (TextView) mainView.findViewById(R.id.date_picker_month);
+ mSelectedDayTextView = (TextView) mainView.findViewById(R.id.date_picker_day);
+ mSelectedYearView = (TextView) mainView.findViewById(R.id.date_picker_year);
+ mSelectedYearView.setOnClickListener(this);
+
+ // Use Theme attributes if possible
+ mDayOfWeekTextAppearanceResId = a.getResourceId(
+ R.styleable.DatePicker_dateSelectorDayOfWeekTextAppearance, -1);
+ if (mDayOfWeekTextAppearanceResId != -1) {
+ mDayOfWeekView.setTextAppearance(context, mDayOfWeekTextAppearanceResId);
+ }
+
+ mMonthTextAppearanceResId = a.getResourceId(
+ R.styleable.DatePicker_dateSelectorMonthTextAppearance, -1);
+ if (mMonthTextAppearanceResId != -1) {
+ mSelectedMonthTextView.setTextAppearance(context, mMonthTextAppearanceResId);
+ }
+
+ mDayOfMonthTextAppearanceResId = a.getResourceId(
+ R.styleable.DatePicker_dateSelectorDayOfMonthTextAppearance, -1);
+ if (mDayOfMonthTextAppearanceResId != -1) {
+ mSelectedDayTextView.setTextAppearance(context, mDayOfMonthTextAppearanceResId);
+ }
+
+ mYearTextAppearanceResId = a.getResourceId(
+ R.styleable.DatePicker_dateSelectorYearTextAppearance, -1);
+ if (mYearTextAppearanceResId != -1) {
+ mSelectedYearView.setTextAppearance(context, mYearTextAppearanceResId);
+ }
+
+ Resources res = mDelegator.getResources();
+
+ mDayOfWeekBackgroundColor = a.getColor(
+ R.styleable.DatePicker_dateSelectorDayOfWeekBackgroundColor,
+ res.getColor(
+ R.color.datepicker_default_header_dayofweek_background_color_holo_light));
+ mDayOfWeekView.setBackgroundColor(mDayOfWeekBackgroundColor);
+
+ mMonthAndDayBackgroundColor = a.getColor(R.styleable.DatePicker_dateSelectorBackgroundColor,
+ res.getColor(R.color.datepicker_default_header_selector_background_holo_light));
+ mMonthAndDayLayout.setBackgroundColor(mMonthAndDayBackgroundColor);
+
+ mDayPickerView = new DayPickerView(mContext, this);
+ mYearPickerView = new YearPickerView(mContext);
+ mYearPickerView.init(this);
+
+ ColorStateList colors = a.getColorStateList(R.styleable.DatePicker_calendarTextColor);
+ setCalendarTextColor(colors);
+
+ mDayPickerDescription = res.getString(R.string.day_picker_description);
+ mSelectDay = res.getString(R.string.select_day);
+ mYearPickerDescription = res.getString(R.string.year_picker_description);
+ mSelectYear = res.getString(R.string.select_year);
+
+ mAnimator = (AccessibleDateAnimator) mainView.findViewById(R.id.animator);
+ mAnimator.addView(mDayPickerView);
+ mAnimator.addView(mYearPickerView);
+ mAnimator.setDateMillis(mCurrentDate.getTimeInMillis());
+ Animation animation = new AlphaAnimation(0.0f, 1.0f);
+ animation.setDuration(ANIMATION_DURATION);
+ mAnimator.setInAnimation(animation);
+ Animation animation2 = new AlphaAnimation(1.0f, 0.0f);
+ animation2.setDuration(ANIMATION_DURATION);
+ mAnimator.setOutAnimation(animation2);
+
+ mLayoutButtons = (ViewGroup) mainView.findViewById(R.id.layout_buttons);
+ mDoneButton = (Button) mainView.findViewById(R.id.done);
+ mDoneButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ tryVibrate();
+ if (mDismissCallback != null) {
+ mDismissCallback.dismiss(mDelegator, false, mCurrentDate.get(Calendar.YEAR),
+ mCurrentDate.get(Calendar.MONTH),
+ mCurrentDate.get(Calendar.DAY_OF_MONTH));
+ }
+ }
+ });
+
+ updateDisplay(false);
+ setCurrentView(MONTH_AND_DAY_VIEW);
+ }
+
+ /**
+ * Gets a calendar for locale bootstrapped with the value of a given calendar.
+ *
+ * @param oldCalendar The old calendar.
+ * @param locale The locale.
+ */
+ private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+ if (oldCalendar == null) {
+ return Calendar.getInstance(locale);
+ } else {
+ final long currentTimeMillis = oldCalendar.getTimeInMillis();
+ Calendar newCalendar = Calendar.getInstance(locale);
+ newCalendar.setTimeInMillis(currentTimeMillis);
+ return newCalendar;
+ }
+ }
+
+ /**
+ * Compute the array representing the order of Month / Day / Year views in their layout.
+ * Will be used for I18N purpose as the order of them depends on the Locale.
+ */
+ private int[] getMonthDayYearIndexes(String pattern) {
+ int[] result = new int[3];
+
+ final String filteredPattern = pattern.replaceAll("'.*?'", "");
+
+ final int dayIndex = filteredPattern.indexOf('d');
+ final int monthMIndex = filteredPattern.indexOf("M");
+ final int monthIndex = (monthMIndex != -1) ? monthMIndex : filteredPattern.indexOf("L");
+ final int yearIndex = filteredPattern.indexOf("y");
+
+ if (yearIndex < monthIndex) {
+ result[YEAR_INDEX] = 0;
+
+ if (monthIndex < dayIndex) {
+ result[MONTH_INDEX] = 1;
+ result[DAY_INDEX] = 2;
+ } else {
+ result[MONTH_INDEX] = 2;
+ result[DAY_INDEX] = 1;
+ }
+ } else {
+ result[YEAR_INDEX] = 2;
+
+ if (monthIndex < dayIndex) {
+ result[MONTH_INDEX] = 0;
+ result[DAY_INDEX] = 1;
+ } else {
+ result[MONTH_INDEX] = 1;
+ result[DAY_INDEX] = 0;
+ }
+ }
+ return result;
+ }
+
+ private void updateDisplay(boolean announce) {
+ if (mDayOfWeekView != null) {
+ mDayOfWeekView.setText(mCurrentDate.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG,
+ Locale.getDefault()));
+ }
+ final String bestDateTimePattern =
+ DateFormat.getBestDateTimePattern(mCurrentLocale, "yMMMd");
+
+ // Compute indices of Month, Day and Year views
+ int[] viewIndices = getMonthDayYearIndexes(bestDateTimePattern);
+
+ // Restart from a clean state
+ mMonthAndDayLayout.removeAllViews();
+ mDateLayout.removeView(mSelectedYearView);
+
+ // Position the Year View at the correct location
+ if (viewIndices[YEAR_INDEX] == 0) {
+ mDateLayout.addView(mSelectedYearView, 0);
+ } else {
+ mDateLayout.addView(mSelectedYearView, 1);
+ }
+
+ // Position Day and Month Views
+ if (viewIndices[MONTH_INDEX] > viewIndices[DAY_INDEX]) {
+ // Day View is first
+ mMonthAndDayLayout.addView(mSelectedDayTextView);
+ mMonthAndDayLayout.addView(mSelectedMonthTextView);
+ } else {
+ // Month View is first
+ mMonthAndDayLayout.addView(mSelectedMonthTextView);
+ mMonthAndDayLayout.addView(mSelectedDayTextView);
+ }
+
+ mSelectedMonthTextView.setText(mCurrentDate.getDisplayName(Calendar.MONTH, Calendar.SHORT,
+ Locale.getDefault()).toUpperCase(Locale.getDefault()));
+ mSelectedDayTextView.setText(mDayFormat.format(mCurrentDate.getTime()));
+ mSelectedYearView.setText(mYearFormat.format(mCurrentDate.getTime()));
+
+ // Accessibility.
+ long millis = mCurrentDate.getTimeInMillis();
+ mAnimator.setDateMillis(millis);
+ int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR;
+ String monthAndDayText = DateUtils.formatDateTime(mContext, millis, flags);
+ mMonthAndDayLayout.setContentDescription(monthAndDayText);
+
+ if (announce) {
+ flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
+ String fullDateText = DateUtils.formatDateTime(mContext, millis, flags);
+ mAnimator.announceForAccessibility(fullDateText);
+ }
+ updatePickers();
+ }
+
+ private void setCurrentView(final int viewIndex) {
+ long millis = mCurrentDate.getTimeInMillis();
+
+ switch (viewIndex) {
+ case MONTH_AND_DAY_VIEW:
+ ObjectAnimator pulseAnimator = getPulseAnimator(mMonthAndDayLayout, 0.9f,
+ 1.05f);
+ if (mDelayAnimation) {
+ pulseAnimator.setStartDelay(ANIMATION_DELAY);
+ mDelayAnimation = false;
+ }
+ mDayPickerView.onDateChanged();
+ if (mCurrentView != viewIndex) {
+ mMonthAndDayLayout.setSelected(true);
+ mSelectedYearView.setSelected(false);
+ mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW);
+ mCurrentView = viewIndex;
+ }
+ pulseAnimator.start();
+
+ int flags = DateUtils.FORMAT_SHOW_DATE;
+ String dayString = DateUtils.formatDateTime(mContext, millis, flags);
+ mAnimator.setContentDescription(mDayPickerDescription + ": " + dayString);
+ mAnimator.announceForAccessibility(mSelectDay);
+ break;
+ case YEAR_VIEW:
+ pulseAnimator = getPulseAnimator(mSelectedYearView, 0.85f, 1.1f);
+ if (mDelayAnimation) {
+ pulseAnimator.setStartDelay(ANIMATION_DELAY);
+ mDelayAnimation = false;
+ }
+ mYearPickerView.onDateChanged();
+ if (mCurrentView != viewIndex) {
+ mMonthAndDayLayout.setSelected(false);
+ mSelectedYearView.setSelected(true);
+ mAnimator.setDisplayedChild(YEAR_VIEW);
+ mCurrentView = viewIndex;
+ }
+ pulseAnimator.start();
+
+ CharSequence yearString = mYearFormat.format(millis);
+ mAnimator.setContentDescription(mYearPickerDescription + ": " + yearString);
+ mAnimator.announceForAccessibility(mSelectYear);
+ break;
+ }
+ }
+
+ @Override
+ public void init(int year, int monthOfYear, int dayOfMonth,
+ DatePicker.OnDateChangedListener callBack) {
+ mDateChangedListener = callBack;
+ mCurrentDate.set(Calendar.YEAR, year);
+ mCurrentDate.set(Calendar.MONTH, monthOfYear);
+ mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+ updateDisplay(false);
+ }
+
+ @Override
+ public void updateDate(int year, int month, int dayOfMonth) {
+ mCurrentDate.set(Calendar.YEAR, year);
+ mCurrentDate.set(Calendar.MONTH, month);
+ mCurrentDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
+ mDateChangedListener.onDateChanged(mDelegator, year, month, dayOfMonth);
+ updateDisplay(false);
+ }
+
+ @Override
+ public int getYear() {
+ return mCurrentDate.get(Calendar.YEAR);
+ }
+
+ @Override
+ public int getMonth() {
+ return mCurrentDate.get(Calendar.MONTH);
+ }
+
+ @Override
+ public int getDayOfMonth() {
+ return mCurrentDate.get(Calendar.DAY_OF_MONTH);
+ }
+
+ @Override
+ public void setMinDate(long minDate) {
+ mTempDate.setTimeInMillis(minDate);
+ if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
+ && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+ return;
+ }
+ if (mCurrentDate.before(mTempDate)) {
+ mCurrentDate.setTimeInMillis(minDate);
+ updatePickers();
+ updateDisplay(false);
+ }
+ mMinDate.setTimeInMillis(minDate);
+ mDayPickerView.goTo(getSelectedDay(), false, true, true);
+ }
+
+ @Override
+ public Calendar getMinDate() {
+ return mMinDate;
+ }
+
+ @Override
+ public void setMaxDate(long maxDate) {
+ mTempDate.setTimeInMillis(maxDate);
+ if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
+ && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+ return;
+ }
+ if (mCurrentDate.after(mTempDate)) {
+ mCurrentDate.setTimeInMillis(maxDate);
+ updatePickers();
+ updateDisplay(false);
+ }
+ mMaxDate.setTimeInMillis(maxDate);
+ mDayPickerView.goTo(getSelectedDay(), false, true, true);
+ }
+
+ @Override
+ public Calendar getMaxDate() {
+ return mMaxDate;
+ }
+
+ @Override
+ public int getFirstDayOfWeek() {
+ return mCurrentDate.getFirstDayOfWeek();
+ }
+
+ @Override
+ public int getMinYear() {
+ return mMinDate.get(Calendar.YEAR);
+ }
+
+ @Override
+ public int getMaxYear() {
+ return mMaxDate.get(Calendar.YEAR);
+ }
+
+ @Override
+ public int getMinMonth() {
+ return mMinDate.get(Calendar.MONTH);
+ }
+
+ @Override
+ public int getMaxMonth() {
+ return mMaxDate.get(Calendar.MONTH);
+ }
+
+ @Override
+ public int getMinDay() {
+ return mMinDate.get(Calendar.DAY_OF_MONTH);
+ }
+
+ @Override
+ public int getMaxDay() {
+ return mMaxDate.get(Calendar.DAY_OF_MONTH);
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ mMonthAndDayLayout.setEnabled(enabled);
+ mSelectedYearView.setEnabled(enabled);
+ mAnimator.setEnabled(enabled);
+ mIsEnabled = enabled;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ @Override
+ public void setDateSelectorDayOfWeekBackgroundColor(int color) {
+ if (mDayOfWeekBackgroundColor != color) {
+ mDayOfWeekBackgroundColor = color;
+ mDayOfWeekView.setBackgroundColor(color);
+ }
+ }
+
+ @Override
+ public int getDateSelectorDayOfWeekBackgroundColor() {
+ return mDayOfWeekBackgroundColor;
+ }
+
+ @Override
+ public void setDateSelectorDayOfWeekTextAppearance(int resId) {
+ if (mDayOfWeekTextAppearanceResId != resId && resId > 0) {
+ mDayOfWeekTextAppearanceResId = resId;
+ mDayOfWeekView.setTextAppearance(mContext, resId);
+ }
+ }
+
+ @Override
+ public int getDateSelectorDayOfWeekTextAppearance() {
+ return mDayOfWeekTextAppearanceResId;
+ }
+
+ @Override
+ public void setDateSelectorBackgroundColor(int color) {
+ if (mMonthAndDayBackgroundColor != color) {
+ mMonthAndDayBackgroundColor = color;
+ mMonthAndDayLayout.setBackgroundColor(color);
+ }
+ }
+
+ @Override
+ public int getDateSelectorBackgroundColor() {
+ return mMonthAndDayBackgroundColor;
+ }
+
+ @Override
+ public void setDateSelectorMonthTextAppearance(int resId) {
+ if (mMonthTextAppearanceResId != resId && resId > 0) {
+ mMonthTextAppearanceResId = resId;
+ mSelectedMonthTextView.setTextAppearance(mContext, resId);
+ }
+ }
+
+ @Override
+ public int getDateSelectorMonthTextAppearance() {
+ return mMonthTextAppearanceResId;
+ }
+
+ @Override
+ public void setDateSelectorDayOfMonthTextAppearance(int resId) {
+ if (mDayOfMonthTextAppearanceResId != resId && resId > 0) {
+ mDayOfMonthTextAppearanceResId = resId;
+ mSelectedDayTextView.setTextAppearance(mContext, resId);
+ }
+ }
+
+ @Override
+ public int getDateSelectorDayOfMonthTextAppearance() {
+ return mDayOfMonthTextAppearanceResId;
+ }
+
+ @Override
+ public void setDateSelectorYearTextAppearance(int resId) {
+ if (mYearTextAppearanceResId != resId && resId > 0) {
+ mYearTextAppearanceResId = resId;
+ mSelectedYearView.setTextAppearance(mContext, resId);
+ }
+ }
+
+ @Override
+ public int getDateSelectorYearTextAppearance() {
+ return mYearTextAppearanceResId;
+ }
+
+ @Override
+ public void setDateSelectorYearListItemTextAppearance(int resId) {
+ if (mYearListItemTextAppearanceResId != resId) {
+ mYearListItemTextAppearanceResId = resId;
+ mYearPickerView.setItemTextAppearance(resId);
+ }
+ }
+
+ @Override
+ public int getDateSelectorYearListItemTextAppearance() {
+ return mYearListItemTextAppearanceResId;
+ }
+
+ @Override
+ public void setDateSelectorYearListSelectedCircleColor(int color) {
+ mYearPickerView.setYearSelectedCircleColor(color);
+ }
+
+ @Override
+ public int getDateSelectorYearListSelectedCircleColor() {
+ return mYearPickerView.getYearSelectedCircleColor();
+ }
+
+ @Override
+ public void setCalendarTextColor(ColorStateList colors) {
+ if (colors == null) {
+ return;
+ }
+ if (mCalendarTextColors == null || !mCalendarTextColors.equals(colors)) {
+ mCalendarTextColors = colors;
+ mDayPickerView.setCalendarTextColor(colors);
+ }
+ }
+
+ @Override
+ public ColorStateList getCalendarTextColors() {
+ return mCalendarTextColors;
+ }
+
+ @Override
+ public CalendarView getCalendarView() {
+ throw new UnsupportedOperationException(
+ "CalendarView does not exists for the new DatePicker");
+ }
+
+ @Override
+ public void setCalendarViewShown(boolean shown) {
+ // No-op for compatibility with the old DatePicker.
+ }
+
+ @Override
+ public boolean getCalendarViewShown() {
+ return false;
+ }
+
+ @Override
+ public void setSpinnersShown(boolean shown) {
+ // No-op for compatibility with the old DatePicker.
+ }
+
+ @Override
+ public boolean getSpinnersShown() {
+ return false;
+ }
+
+ @Override
+ public void setShowDoneButton(boolean showDoneButton) {
+ mShowDoneButton = showDoneButton;
+ updateDoneButtonVisibility();
+ }
+
+ private void updateDoneButtonVisibility() {
+ mLayoutButtons.setVisibility(mShowDoneButton ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public void setDismissCallback(DatePicker.DatePickerDismissCallback callback) {
+ mDismissCallback = callback;
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ mYearFormat = new SimpleDateFormat("y", newConfig.locale);
+ mDayFormat = new SimpleDateFormat("d", newConfig.locale);
+ }
+
+ @Override
+ public void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+ // Nothing to do
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState(Parcelable superState) {
+ final int year = mCurrentDate.get(Calendar.YEAR);
+ final int month = mCurrentDate.get(Calendar.MONTH);
+ final int day = mCurrentDate.get(Calendar.DAY_OF_MONTH);
+
+ int listPosition = -1;
+ int listPositionOffset = -1;
+
+ if (mCurrentView == MONTH_AND_DAY_VIEW) {
+ listPosition = mDayPickerView.getMostVisiblePosition();
+ } else if (mCurrentView == YEAR_VIEW) {
+ listPosition = mYearPickerView.getFirstVisiblePosition();
+ listPositionOffset = mYearPickerView.getFirstPositionOffset();
+ }
+
+ return new SavedState(superState, year, month, day, mMinDate.getTimeInMillis(),
+ mMaxDate.getTimeInMillis(), mCurrentView, listPosition, listPositionOffset);
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ SavedState ss = (SavedState) state;
+
+ mCurrentDate.set(ss.getSelectedDay(), ss.getSelectedMonth(), ss.getSelectedYear());
+ mCurrentView = ss.getCurrentView();
+ mMinDate.setTimeInMillis(ss.getMinDate());
+ mMaxDate.setTimeInMillis(ss.getMaxDate());
+
+ updateDisplay(false);
+ setCurrentView(mCurrentView);
+
+ final int listPosition = ss.getListPosition();
+ if (listPosition != -1) {
+ if (mCurrentView == MONTH_AND_DAY_VIEW) {
+ mDayPickerView.postSetSelection(listPosition);
+ } else if (mCurrentView == YEAR_VIEW) {
+ mYearPickerView.postSetSelectionFromTop(listPosition, ss.getListPositionOffset());
+ }
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ onPopulateAccessibilityEvent(event);
+ return true;
+ }
+
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ event.getText().add(mCurrentDate.getTime().toString());
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ event.setClassName(DatePicker.class.getName());
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ info.setClassName(DatePicker.class.getName());
+ }
+
+ @Override
+ public void onYearSelected(int year) {
+ adjustDayInMonthIfNeeded(mCurrentDate.get(Calendar.MONTH), year);
+ mCurrentDate.set(Calendar.YEAR, year);
+ updatePickers();
+ setCurrentView(MONTH_AND_DAY_VIEW);
+ updateDisplay(true);
+ updateDoneButtonEnableState();
+ }
+
+ // If the newly selected month / year does not contain the currently selected day number,
+ // change the selected day number to the last day of the selected month or year.
+ // e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30
+ // e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013
+ private void adjustDayInMonthIfNeeded(int month, int year) {
+ int day = mCurrentDate.get(Calendar.DAY_OF_MONTH);
+ int daysInMonth = getDaysInMonth(month, year);
+ if (day > daysInMonth) {
+ mCurrentDate.set(Calendar.DAY_OF_MONTH, daysInMonth);
+ }
+ }
+
+ public static int getDaysInMonth(int month, int year) {
+ switch (month) {
+ case Calendar.JANUARY:
+ case Calendar.MARCH:
+ case Calendar.MAY:
+ case Calendar.JULY:
+ case Calendar.AUGUST:
+ case Calendar.OCTOBER:
+ case Calendar.DECEMBER:
+ return 31;
+ case Calendar.APRIL:
+ case Calendar.JUNE:
+ case Calendar.SEPTEMBER:
+ case Calendar.NOVEMBER:
+ return 30;
+ case Calendar.FEBRUARY:
+ return (year % 4 == 0) ? 29 : 28;
+ default:
+ throw new IllegalArgumentException("Invalid Month");
+ }
+ }
+
+ @Override
+ public void onDayOfMonthSelected(int year, int month, int day) {
+ mCurrentDate.set(Calendar.YEAR, year);
+ mCurrentDate.set(Calendar.MONTH, month);
+ mCurrentDate.set(Calendar.DAY_OF_MONTH, day);
+ updatePickers();
+ updateDisplay(true);
+ updateDoneButtonEnableState();
+ }
+
+ private void updateDoneButtonEnableState() {
+ if (mShowDoneButton) {
+ final boolean enabled = mCurrentDate.equals(mMinDate) ||
+ mCurrentDate.equals(mMaxDate) ||
+ (mCurrentDate.after(mMinDate) && mCurrentDate.before(mMaxDate));
+ mDoneButton.setEnabled(enabled);
+ }
+ }
+
+ private void updatePickers() {
+ Iterator<OnDateChangedListener> iterator = mListeners.iterator();
+ while (iterator.hasNext()) {
+ iterator.next().onDateChanged();
+ }
+ }
+
+ @Override
+ public void registerOnDateChangedListener(OnDateChangedListener listener) {
+ mListeners.add(listener);
+ }
+
+ @Override
+ public void unregisterOnDateChangedListener(OnDateChangedListener listener) {
+ mListeners.remove(listener);
+ }
+
+ @Override
+ public Calendar getSelectedDay() {
+ return mCurrentDate;
+ }
+
+ @Override
+ public void tryVibrate() {
+ mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE);
+ }
+
+ @Override
+ public void onClick(View v) {
+ tryVibrate();
+ if (v.getId() == R.id.date_picker_year) {
+ setCurrentView(YEAR_VIEW);
+ } else if (v.getId() == R.id.date_picker_month_and_day_layout) {
+ setCurrentView(MONTH_AND_DAY_VIEW);
+ }
+ }
+
+ /**
+ * Class for managing state storing/restoring.
+ */
+ private static class SavedState extends View.BaseSavedState {
+
+ private final int mSelectedYear;
+ private final int mSelectedMonth;
+ private final int mSelectedDay;
+ private final long mMinDate;
+ private final long mMaxDate;
+ private final int mCurrentView;
+ private final int mListPosition;
+ private final int mListPositionOffset;
+
+ /**
+ * Constructor called from {@link DatePicker#onSaveInstanceState()}
+ */
+ private SavedState(Parcelable superState, int year, int month, int day,
+ long minDate, long maxDate, int currentView, int listPosition,
+ int listPositionOffset) {
+ super(superState);
+ mSelectedYear = year;
+ mSelectedMonth = month;
+ mSelectedDay = day;
+ mMinDate = minDate;
+ mMaxDate = maxDate;
+ mCurrentView = currentView;
+ mListPosition = listPosition;
+ mListPositionOffset = listPositionOffset;
+ }
+
+ /**
+ * Constructor called from {@link #CREATOR}
+ */
+ private SavedState(Parcel in) {
+ super(in);
+ mSelectedYear = in.readInt();
+ mSelectedMonth = in.readInt();
+ mSelectedDay = in.readInt();
+ mMinDate = in.readLong();
+ mMaxDate = in.readLong();
+ mCurrentView = in.readInt();
+ mListPosition = in.readInt();
+ mListPositionOffset = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mSelectedYear);
+ dest.writeInt(mSelectedMonth);
+ dest.writeInt(mSelectedDay);
+ dest.writeLong(mMinDate);
+ dest.writeLong(mMaxDate);
+ dest.writeInt(mCurrentView);
+ dest.writeInt(mListPosition);
+ dest.writeInt(mListPositionOffset);
+ }
+
+ public int getSelectedDay() {
+ return mSelectedDay;
+ }
+
+ public int getSelectedMonth() {
+ return mSelectedMonth;
+ }
+
+ public int getSelectedYear() {
+ return mSelectedYear;
+ }
+
+ public long getMinDate() {
+ return mMinDate;
+ }
+
+ public long getMaxDate() {
+ return mMaxDate;
+ }
+
+ public int getCurrentView() {
+ return mCurrentView;
+ }
+
+ public int getListPosition() {
+ return mListPosition;
+ }
+
+ public int getListPositionOffset() {
+ return mListPositionOffset;
+ }
+
+ @SuppressWarnings("all")
+ // suppress unused and hiding
+ public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ /**
+ * Render an animator to pulsate a view in place.
+ * @param labelToAnimate the view to pulsate.
+ * @return The animator object. Use .start() to begin.
+ */
+ public static ObjectAnimator getPulseAnimator(View labelToAnimate, float decreaseRatio,
+ float increaseRatio) {
+ Keyframe k0 = Keyframe.ofFloat(0f, 1f);
+ Keyframe k1 = Keyframe.ofFloat(0.275f, decreaseRatio);
+ Keyframe k2 = Keyframe.ofFloat(0.69f, increaseRatio);
+ Keyframe k3 = Keyframe.ofFloat(1f, 1f);
+
+ PropertyValuesHolder scaleX = PropertyValuesHolder.ofKeyframe(View.SCALE_X, k0, k1, k2, k3);
+ PropertyValuesHolder scaleY = PropertyValuesHolder.ofKeyframe(View.SCALE_Y, k0, k1, k2, k3);
+ ObjectAnimator pulseAnimator =
+ ObjectAnimator.ofPropertyValuesHolder(labelToAnimate, scaleX, scaleY);
+ pulseAnimator.setDuration(PULSE_ANIMATOR_DURATION);
+
+ return pulseAnimator;
+ }
+}
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
new file mode 100644
index 0000000..c44bd46
--- /dev/null
+++ b/core/java/android/widget/DayPickerView.java
@@ -0,0 +1,506 @@
+/*
+ * 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.
+ */
+
+package android.widget;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * This displays a list of months in a calendar format with selectable days.
+ */
+class DayPickerView extends ListView implements AbsListView.OnScrollListener,
+ OnDateChangedListener {
+
+ private static final String TAG = "DayPickerView";
+
+ // How long the GoTo fling animation should last
+ private static final int GOTO_SCROLL_DURATION = 250;
+
+ // How long to wait after receiving an onScrollStateChanged notification before acting on it
+ private static final int SCROLL_CHANGE_DELAY = 40;
+
+ private static int LIST_TOP_OFFSET = -1; // so that the top line will be under the separator
+
+ private SimpleDateFormat mYearFormat = new SimpleDateFormat("yyyy", Locale.getDefault());
+
+ // These affect the scroll speed and feel
+ private float mFriction = 1.0f;
+
+ // highlighted time
+ private Calendar mSelectedDay = Calendar.getInstance();
+ private SimpleMonthAdapter mAdapter;
+
+ private Calendar mTempDay = Calendar.getInstance();
+
+ // which month should be displayed/highlighted [0-11]
+ private int mCurrentMonthDisplayed;
+ // used for tracking what state listview is in
+ private int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+ // used for tracking what state listview is in
+ private int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE;
+
+ private DatePickerController mController;
+ private boolean mPerformingScroll;
+
+ private ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable(this);
+
+ public DayPickerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public DayPickerView(Context context, DatePickerController controller) {
+ super(context);
+ init();
+ setController(controller);
+ }
+
+ public void setController(DatePickerController controller) {
+ if (mController != null) {
+ mController.unregisterOnDateChangedListener(this);
+ }
+ mController = controller;
+ mController.registerOnDateChangedListener(this);
+ setUpAdapter();
+ setAdapter(mAdapter);
+ onDateChanged();
+ }
+
+ public void init() {
+ setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+ setDrawSelectorOnTop(false);
+
+ setUpListView();
+ }
+
+ public void onChange() {
+ setUpAdapter();
+ setAdapter(mAdapter);
+ }
+
+ /**
+ * Creates a new adapter if necessary and sets up its parameters. Override
+ * this method to provide a custom adapter.
+ */
+ protected void setUpAdapter() {
+ if (mAdapter == null) {
+ mAdapter = new SimpleMonthAdapter(getContext(), mController);
+ } else {
+ mAdapter.setSelectedDay(mSelectedDay);
+ mAdapter.notifyDataSetChanged();
+ }
+ // refresh the view with the new parameters
+ mAdapter.notifyDataSetChanged();
+ }
+
+ /*
+ * Sets all the required fields for the list view. Override this method to
+ * set a different list view behavior.
+ */
+ protected void setUpListView() {
+ // Transparent background on scroll
+ setCacheColorHint(0);
+ // No dividers
+ setDivider(null);
+ // Items are clickable
+ setItemsCanFocus(true);
+ // The thumb gets in the way, so disable it
+ setFastScrollEnabled(false);
+ setVerticalScrollBarEnabled(false);
+ setOnScrollListener(this);
+ setFadingEdgeLength(0);
+ // Make the scrolling behavior nicer
+ setFriction(ViewConfiguration.getScrollFriction() * mFriction);
+ }
+
+ private int getDiffMonths(Calendar start, Calendar end){
+ final int diffYears = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
+ final int diffMonths = end.get(Calendar.MONTH) - start.get(Calendar.MONTH) + 12 * diffYears;
+ return diffMonths;
+ }
+
+ private int getPositionFromDay(Calendar day) {
+ final int diffMonthMax = getDiffMonths(mController.getMinDate(), mController.getMaxDate());
+ int diffMonth = getDiffMonths(mController.getMinDate(), day);
+
+ if (diffMonth < 0 ) {
+ diffMonth = 0;
+ } else if (diffMonth > diffMonthMax) {
+ diffMonth = diffMonthMax;
+ }
+
+ return diffMonth;
+ }
+
+ /**
+ * This moves to the specified time in the view. If the time is not already
+ * in range it will move the list so that the first of the month containing
+ * the time is at the top of the view. If the new time is already in view
+ * the list will not be scrolled unless forceScroll is true. This time may
+ * optionally be highlighted as selected as well.
+ *
+ * @param day The day to move to
+ * @param animate Whether to scroll to the given time or just redraw at the
+ * new location
+ * @param setSelected Whether to set the given time as selected
+ * @param forceScroll Whether to recenter even if the time is already
+ * visible
+ * @return Whether or not the view animated to the new location
+ */
+ public boolean goTo(Calendar day, boolean animate, boolean setSelected,
+ boolean forceScroll) {
+
+ // Set the selected day
+ if (setSelected) {
+ mSelectedDay.setTimeInMillis(day.getTimeInMillis());
+ }
+
+ mTempDay.setTimeInMillis(day.getTimeInMillis());
+ final int position = getPositionFromDay(day);
+
+ View child;
+ int i = 0;
+ int top = 0;
+ // Find a child that's completely in the view
+ do {
+ child = getChildAt(i++);
+ if (child == null) {
+ break;
+ }
+ top = child.getTop();
+ } while (top < 0);
+
+ // Compute the first and last position visible
+ int selectedPosition;
+ if (child != null) {
+ selectedPosition = getPositionForView(child);
+ } else {
+ selectedPosition = 0;
+ }
+
+ if (setSelected) {
+ mAdapter.setSelectedDay(mSelectedDay);
+ }
+
+ // Check if the selected day is now outside of our visible range
+ // and if so scroll to the month that contains it
+ if (position != selectedPosition || forceScroll) {
+ setMonthDisplayed(mTempDay);
+ mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING;
+ if (animate) {
+ smoothScrollToPositionFromTop(
+ position, LIST_TOP_OFFSET, GOTO_SCROLL_DURATION);
+ return true;
+ } else {
+ postSetSelection(position);
+ }
+ } else if (setSelected) {
+ setMonthDisplayed(mSelectedDay);
+ }
+ return false;
+ }
+
+ public void postSetSelection(final int position) {
+ clearFocus();
+ post(new Runnable() {
+
+ @Override
+ public void run() {
+ setSelection(position);
+ }
+ });
+ onScrollStateChanged(this, OnScrollListener.SCROLL_STATE_IDLE);
+ }
+
+ /**
+ * Updates the title and selected month if the view has moved to a new
+ * month.
+ */
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ SimpleMonthView child = (SimpleMonthView) view.getChildAt(0);
+ if (child == null) {
+ return;
+ }
+
+ mPreviousScrollState = mCurrentScrollState;
+ }
+
+ /**
+ * Sets the month displayed at the top of this view based on time. Override
+ * to add custom events when the title is changed.
+ */
+ protected void setMonthDisplayed(Calendar date) {
+ if (mCurrentMonthDisplayed != date.get(Calendar.MONTH)) {
+ mCurrentMonthDisplayed = date.get(Calendar.MONTH);
+ invalidateViews();
+ }
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ // use a post to prevent re-entering onScrollStateChanged before it
+ // exits
+ mScrollStateChangedRunnable.doScrollStateChange(view, scrollState);
+ }
+
+ void setCalendarTextColor(ColorStateList colors) {
+ mAdapter.setCalendarTextColor(colors);
+ }
+
+ protected class ScrollStateRunnable implements Runnable {
+ private int mNewState;
+ private View mParent;
+
+ ScrollStateRunnable(View view) {
+ mParent = view;
+ }
+
+ /**
+ * Sets up the runnable with a short delay in case the scroll state
+ * immediately changes again.
+ *
+ * @param view The list view that changed state
+ * @param scrollState The new state it changed to
+ */
+ public void doScrollStateChange(AbsListView view, int scrollState) {
+ mParent.removeCallbacks(this);
+ mNewState = scrollState;
+ mParent.postDelayed(this, SCROLL_CHANGE_DELAY);
+ }
+
+ @Override
+ public void run() {
+ mCurrentScrollState = mNewState;
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG,
+ "new scroll state: " + mNewState + " old state: " + mPreviousScrollState);
+ }
+ // Fix the position after a scroll or a fling ends
+ if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
+ && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE
+ && mPreviousScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
+ mPreviousScrollState = mNewState;
+ int i = 0;
+ View child = getChildAt(i);
+ while (child != null && child.getBottom() <= 0) {
+ child = getChildAt(++i);
+ }
+ if (child == null) {
+ // The view is no longer visible, just return
+ return;
+ }
+ int firstPosition = getFirstVisiblePosition();
+ int lastPosition = getLastVisiblePosition();
+ boolean scroll = firstPosition != 0 && lastPosition != getCount() - 1;
+ final int top = child.getTop();
+ final int bottom = child.getBottom();
+ final int midpoint = getHeight() / 2;
+ if (scroll && top < LIST_TOP_OFFSET) {
+ if (bottom > midpoint) {
+ smoothScrollBy(top, GOTO_SCROLL_DURATION);
+ } else {
+ smoothScrollBy(bottom, GOTO_SCROLL_DURATION);
+ }
+ }
+ } else {
+ mPreviousScrollState = mNewState;
+ }
+ }
+ }
+
+ /**
+ * Gets the position of the view that is most prominently displayed within the list view.
+ */
+ public int getMostVisiblePosition() {
+ final int firstPosition = getFirstVisiblePosition();
+ final int height = getHeight();
+
+ int maxDisplayedHeight = 0;
+ int mostVisibleIndex = 0;
+ int i=0;
+ int bottom = 0;
+ while (bottom < height) {
+ View child = getChildAt(i);
+ if (child == null) {
+ break;
+ }
+ bottom = child.getBottom();
+ int displayedHeight = Math.min(bottom, height) - Math.max(0, child.getTop());
+ if (displayedHeight > maxDisplayedHeight) {
+ mostVisibleIndex = i;
+ maxDisplayedHeight = displayedHeight;
+ }
+ i++;
+ }
+ return firstPosition + mostVisibleIndex;
+ }
+
+ @Override
+ public void onDateChanged() {
+ goTo(mController.getSelectedDay(), false, true, true);
+ }
+
+ /**
+ * Attempts to return the date that has accessibility focus.
+ *
+ * @return The date that has accessibility focus, or {@code null} if no date
+ * has focus.
+ */
+ private Calendar findAccessibilityFocus() {
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ if (child instanceof SimpleMonthView) {
+ final Calendar focus = ((SimpleMonthView) child).getAccessibilityFocus();
+ if (focus != null) {
+ return focus;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Attempts to restore accessibility focus to a given date. No-op if
+ * {@code day} is {@code null}.
+ *
+ * @param day The date that should receive accessibility focus
+ * @return {@code true} if focus was restored
+ */
+ private boolean restoreAccessibilityFocus(Calendar day) {
+ if (day == null) {
+ return false;
+ }
+
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+ if (child instanceof SimpleMonthView) {
+ if (((SimpleMonthView) child).restoreAccessibilityFocus(day)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ protected void layoutChildren() {
+ final Calendar focusedDay = findAccessibilityFocus();
+ super.layoutChildren();
+ if (mPerformingScroll) {
+ mPerformingScroll = false;
+ } else {
+ restoreAccessibilityFocus(focusedDay);
+ }
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ mYearFormat = new SimpleDateFormat("yyyy", Locale.getDefault());
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setItemCount(-1);
+ }
+
+ private String getMonthAndYearString(Calendar day) {
+ StringBuffer sbuf = new StringBuffer();
+ sbuf.append(day.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault()));
+ sbuf.append(" ");
+ sbuf.append(mYearFormat.format(day.getTime()));
+ return sbuf.toString();
+ }
+
+ /**
+ * Necessary for accessibility, to ensure we support "scrolling" forward and backward
+ * in the month list.
+ */
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+
+ /**
+ * When scroll forward/backward events are received, announce the newly scrolled-to month.
+ */
+ @Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (action != AccessibilityNodeInfo.ACTION_SCROLL_FORWARD &&
+ action != AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
+ return super.performAccessibilityAction(action, arguments);
+ }
+
+ // Figure out what month is showing.
+ int firstVisiblePosition = getFirstVisiblePosition();
+ int month = firstVisiblePosition % 12;
+ int year = firstVisiblePosition / 12 + mController.getMinYear();
+ Calendar day = Calendar.getInstance();
+ day.set(year, month, 1);
+
+ // Scroll either forward or backward one month.
+ if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) {
+ day.add(Calendar.MONTH, 1);
+ if (day.get(Calendar.MONTH) == 12) {
+ day.set(Calendar.MONTH, 0);
+ day.add(Calendar.YEAR, 1);
+ }
+ } else if (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
+ View firstVisibleView = getChildAt(0);
+ // If the view is fully visible, jump one month back. Otherwise, we'll just jump
+ // to the first day of first visible month.
+ if (firstVisibleView != null && firstVisibleView.getTop() >= -1) {
+ // There's an off-by-one somewhere, so the top of the first visible item will
+ // actually be -1 when it's at the exact top.
+ day.add(Calendar.MONTH, -1);
+ if (day.get(Calendar.MONTH) == -1) {
+ day.set(Calendar.MONTH, 11);
+ day.add(Calendar.YEAR, -1);
+ }
+ }
+ }
+
+ // Go to that month.
+ announceForAccessibility(getMonthAndYearString(day));
+ goTo(day, true, false, true);
+ mPerformingScroll = true;
+ return true;
+ }
+}
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 3758d86..57b8dcb 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -21,7 +21,6 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.content.Context;
import android.graphics.Canvas;
@@ -106,7 +105,6 @@
private float mPullDistance;
private final Rect mBounds = new Rect();
- private final RectF mArcRect = new RectF();
private final Paint mPaint = new Paint();
private float mRadius;
private float mBaseGlowHeight;
@@ -318,11 +316,9 @@
final int count = canvas.save();
- final float y = mBounds.height();
- final float centerY = y - mRadius;
final float centerX = mBounds.centerX();
+ final float centerY = mBounds.height() - mRadius;
- mArcRect.set(centerX - mRadius, centerY - mRadius, centerX + mRadius, centerY + mRadius);
canvas.scale(1.f, Math.min(mGlowScaleY, 1.f), centerX, 0);
final float displacement = Math.max(0, Math.min(mDisplacement, 1.f)) - 0.5f;
@@ -330,7 +326,7 @@
canvas.clipRect(mBounds);
canvas.translate(translateX, 0);
- canvas.drawArc(mArcRect, 45, 90, false, mPaint);
+ canvas.drawCircle(centerX, centerY, mRadius, mPaint);
canvas.restoreToCount(count);
boolean oneLastFrame = false;
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 93810b3..33cc66e 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1029,11 +1029,6 @@
}
@Override
- AbsPositionScroller createPositionScroller() {
- return new GridViewPositionScroller();
- }
-
- @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Sets up mListPadding
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -2392,33 +2387,4 @@
column, 1, row, 1, isHeading, isSelected);
info.setCollectionItemInfo(itemInfo);
}
-
- /**
- * Sub-position scroller that understands the layout of a GridView.
- */
- class GridViewPositionScroller extends AbsSubPositionScroller {
- @Override
- public int getRowForPosition(int position) {
- return position / mNumColumns;
- }
-
- @Override
- public int getFirstPositionForRow(int row) {
- return row * mNumColumns;
- }
-
- @Override
- public int getHeightForRow(int row) {
- final int firstRowPosition = row * mNumColumns;
- final int lastRowPosition = Math.min(getCount(), firstRowPosition + mNumColumns);
- int maxHeight = 0;
- for (int i = firstRowPosition; i < lastRowPosition; i++) {
- final int height = getHeightForPosition(i);
- if (height > maxHeight) {
- maxHeight = height;
- }
- }
- return maxHeight;
- }
- }
}
diff --git a/core/java/android/widget/LegacyTimePickerDelegate.java b/core/java/android/widget/LegacyTimePickerDelegate.java
index 2216003..6dd70ba 100644
--- a/core/java/android/widget/LegacyTimePickerDelegate.java
+++ b/core/java/android/widget/LegacyTimePickerDelegate.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
+import android.graphics.Color;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateFormat;
@@ -104,14 +105,13 @@
super(delegator, context);
// process style attributes
- final TypedArray attributesArray = mContext.obtainStyledAttributes(
+ final TypedArray a = mContext.obtainStyledAttributes(
attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
- final int layoutResourceId = attributesArray.getResourceId(
+ final int layoutResourceId = a.getResourceId(
R.styleable.TimePicker_legacyLayout, R.layout.time_picker_legacy);
- attributesArray.recycle();
+ a.recycle();
- final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(layoutResourceId, mDelegator, true);
// hour
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 1baeca8..9db1e05 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3872,11 +3872,6 @@
}
@Override
- AbsPositionScroller createPositionScroller() {
- return new ListViewPositionScroller();
- }
-
- @Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(ListView.class.getName());
@@ -3905,24 +3900,4 @@
0, 1, position, 1, isHeading, isSelected);
info.setCollectionItemInfo(itemInfo);
}
-
- /**
- * Sub-position scroller that understands the layout of a ListView.
- */
- class ListViewPositionScroller extends AbsSubPositionScroller {
- @Override
- public int getRowForPosition(int position) {
- return position;
- }
-
- @Override
- public int getFirstPositionForRow(int row) {
- return row;
- }
-
- @Override
- public int getHeightForRow(int row) {
- return getHeightForPosition(row);
- }
- }
}
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl b/core/java/android/widget/OnDateChangedListener.java
similarity index 65%
rename from telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl
rename to core/java/android/widget/OnDateChangedListener.java
index 3a02b06..29be888 100644
--- a/telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl
+++ b/core/java/android/widget/OnDateChangedListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package android.widget;
/**
- * Callback interface for when DTMF has been sent.
+ * The callback used to notify other date picker components of a change in the selected date.
+ *
*/
-oneway interface IThirdPartyCallSendDtmfCallback {
- /**
- * Called when the DTMF code has been sent.
- */
- void onSendDtmfCompleted();
+interface OnDateChangedListener {
+
+ public void onDateChanged();
}
+
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index a35d447..41d3e320 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1096,10 +1096,6 @@
p.softInputMode = mSoftInputMode;
p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
- // TODO: Use real shadow insets once that algorithm is finalized.
- final int shadowInset = (int) Math.ceil(mElevation * 2);
- p.shadowInsets.set(shadowInset, shadowInset, shadowInset, shadowInset);
-
return p;
}
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 883183e..9b763c1 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -36,6 +36,7 @@
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
@@ -190,6 +191,8 @@
private int mAmOrPm;
private int mAmOrPmPressed;
+ private int mDisabledAlpha;
+
private RectF mRectF = new RectF();
private boolean mInputEnabled = true;
private OnValueSelectedListener mListener;
@@ -310,15 +313,18 @@
public RadialTimePickerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs);
+ // Pull disabled alpha from theme.
+ final TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
+ mDisabledAlpha = (int) (outValue.getFloat() * 255 + 0.5f);
+
// process style attributes
+ final Resources res = getResources();
final TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.TimePicker,
defStyle, 0);
- final Resources res = getResources();
-
mAmPmUnselectedColor = a.getColor(R.styleable.TimePicker_amPmUnselectedBackgroundColor,
res.getColor(R.color.timepicker_default_ampm_unselected_background_color_material));
-
mAmPmSelectedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor,
res.getColor(R.color.timepicker_default_ampm_selected_background_color_material));
@@ -406,10 +412,6 @@
res.getColor(R.color.timepicker_default_numbers_background_color_material)));
mPaintBackground.setAntiAlias(true);
- mPaintDisabled.setColor(a.getColor(R.styleable.TimePicker_disabledColor,
- res.getColor(R.color.timepicker_default_disabled_color_material)));
- mPaintDisabled.setAntiAlias(true);
-
if (DEBUG) {
mPaintDebug.setColor(DEBUG_COLOR);
mPaintDebug.setAntiAlias(true);
@@ -722,7 +724,11 @@
@Override
public void onDraw(Canvas canvas) {
- canvas.save();
+ if (!mInputEnabled) {
+ canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), mDisabledAlpha);
+ } else {
+ canvas.save();
+ }
calculateGridSizesHours();
calculateGridSizesMinutes();
@@ -749,12 +755,6 @@
drawAmPm(canvas);
}
- if(!mInputEnabled) {
- // Draw outer view rectangle
- mRectF.set(0, 0, getWidth(), getHeight());
- canvas.drawRect(mRectF, mPaintDisabled);
- }
-
if (DEBUG) {
drawDebug(canvas);
}
diff --git a/core/java/android/widget/SimpleMonthAdapter.java b/core/java/android/widget/SimpleMonthAdapter.java
new file mode 100644
index 0000000..53d0839
--- /dev/null
+++ b/core/java/android/widget/SimpleMonthAdapter.java
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+package android.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.Calendar;
+import java.util.HashMap;
+
+/**
+ * An adapter for a list of {@link android.widget.SimpleMonthView} items.
+ */
+class SimpleMonthAdapter extends BaseAdapter implements SimpleMonthView.OnDayClickListener {
+ private static final String TAG = "SimpleMonthAdapter";
+
+ private final Context mContext;
+ private final DatePickerController mController;
+ private Calendar mSelectedDay;
+
+ private ColorStateList mCalendarTextColors;
+
+ public SimpleMonthAdapter(Context context, DatePickerController controller) {
+ mContext = context;
+ mController = controller;
+ init();
+ setSelectedDay(mController.getSelectedDay());
+ }
+
+ /**
+ * Updates the selected day and related parameters.
+ *
+ * @param day The day to highlight
+ */
+ public void setSelectedDay(Calendar day) {
+ if (mSelectedDay != day) {
+ mSelectedDay = day;
+ notifyDataSetChanged();
+ }
+ }
+
+ void setCalendarTextColor(ColorStateList colors) {
+ mCalendarTextColors = colors;
+ }
+
+ /**
+ * Set up the gesture detector and selected time
+ */
+ protected void init() {
+ mSelectedDay = Calendar.getInstance();
+ }
+
+ @Override
+ public int getCount() {
+ final int diffYear = mController.getMaxYear() - mController.getMinYear();
+ final int diffMonth = 1 + mController.getMaxMonth() - mController.getMinMonth()
+ + 12 * diffYear;
+ return diffMonth;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ SimpleMonthView v;
+ HashMap<String, Integer> drawingParams = null;
+ if (convertView != null) {
+ v = (SimpleMonthView) convertView;
+ // We store the drawing parameters in the view so it can be recycled
+ drawingParams = (HashMap<String, Integer>) v.getTag();
+ } else {
+ v = new SimpleMonthView(mContext);
+ // Set up the new view
+ AbsListView.LayoutParams params = new AbsListView.LayoutParams(
+ AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.MATCH_PARENT);
+ v.setLayoutParams(params);
+ v.setClickable(true);
+ v.setOnDayClickListener(this);
+ if (mCalendarTextColors != null) {
+ v.setTextColor(mCalendarTextColors);
+ }
+ }
+ if (drawingParams == null) {
+ drawingParams = new HashMap<String, Integer>();
+ } else {
+ drawingParams.clear();
+ }
+ final int currentMonth = position + mController.getMinMonth();
+ final int month = currentMonth % 12;
+ final int year = currentMonth / 12 + mController.getMinYear();
+
+ int selectedDay = -1;
+ if (isSelectedDayInMonth(year, month)) {
+ selectedDay = mSelectedDay.get(Calendar.DAY_OF_MONTH);
+ }
+
+ // Invokes requestLayout() to ensure that the recycled view is set with the appropriate
+ // height/number of weeks before being displayed.
+ v.reuse();
+
+ final int enabledDayRangeStart;
+ if (mController.getMinMonth() == month && mController.getMinYear() == year) {
+ enabledDayRangeStart = mController.getMinDay();
+ } else {
+ enabledDayRangeStart = 1;
+ }
+
+ final int enabledDayRangeEnd;
+ if (mController.getMaxMonth() == month && mController.getMaxYear() == year) {
+ enabledDayRangeEnd = mController.getMaxDay();
+ } else {
+ enabledDayRangeEnd = 31;
+ }
+
+ drawingParams.put(SimpleMonthView.VIEW_PARAMS_SELECTED_DAY, selectedDay);
+ drawingParams.put(SimpleMonthView.VIEW_PARAMS_YEAR, year);
+ drawingParams.put(SimpleMonthView.VIEW_PARAMS_MONTH, month);
+ drawingParams.put(SimpleMonthView.VIEW_PARAMS_WEEK_START, mController.getFirstDayOfWeek());
+ drawingParams.put(SimpleMonthView.VIEW_PARAMS_ENABLEDDAYRANGE_START, enabledDayRangeStart);
+ drawingParams.put(SimpleMonthView.VIEW_PARAMS_ENABLEDDAYRANGE_END, enabledDayRangeEnd);
+ v.setMonthParams(drawingParams);
+ v.invalidate();
+ return v;
+ }
+
+ private boolean isSelectedDayInMonth(int year, int month) {
+ return mSelectedDay.get(Calendar.YEAR) == year && mSelectedDay.get(Calendar.MONTH) == month;
+ }
+
+ @Override
+ public void onDayClick(SimpleMonthView view, Calendar day) {
+ if (day != null) {
+ onDayTapped(day);
+ }
+ }
+
+ /**
+ * Maintains the same hour/min/sec but moves the day to the tapped day.
+ *
+ * @param day The day that was tapped
+ */
+ protected void onDayTapped(Calendar day) {
+ mController.tryVibrate();
+ mController.onDayOfMonthSelected(day.get(Calendar.YEAR), day.get(Calendar.MONTH),
+ day.get(Calendar.DAY_OF_MONTH));
+ setSelectedDay(day);
+ }
+}
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
new file mode 100644
index 0000000..7589711
--- /dev/null
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -0,0 +1,720 @@
+/*
+ * 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.
+ */
+
+package android.widget;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.text.format.Time;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import com.android.internal.R;
+import com.android.internal.widget.ExploreByTouchHelper;
+
+import java.security.InvalidParameterException;
+import java.util.Calendar;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * A calendar-like view displaying a specified month and the appropriate selectable day numbers
+ * within the specified month.
+ */
+class SimpleMonthView extends View {
+ private static final String TAG = "SimpleMonthView";
+
+ /**
+ * These params can be passed into the view to control how it appears.
+ * {@link #VIEW_PARAMS_WEEK} is the only required field, though the default
+ * values are unlikely to fit most layouts correctly.
+ */
+ /**
+ * This sets the height of this week in pixels
+ */
+ static final String VIEW_PARAMS_HEIGHT = "height";
+ /**
+ * This specifies the position (or weeks since the epoch) of this week,
+ * calculated using
+ */
+ static final String VIEW_PARAMS_MONTH = "month";
+ /**
+ * This specifies the position (or weeks since the epoch) of this week,
+ * calculated using
+ */
+ static final String VIEW_PARAMS_YEAR = "year";
+ /**
+ * This sets one of the days in this view as selected {@link Time#SUNDAY}
+ * through {@link Time#SATURDAY}.
+ */
+ static final String VIEW_PARAMS_SELECTED_DAY = "selected_day";
+ /**
+ * Which day the week should start on. {@link Time#SUNDAY} through
+ * {@link Time#SATURDAY}.
+ */
+ static final String VIEW_PARAMS_WEEK_START = "week_start";
+ /**
+ * First enabled day.
+ */
+ static final String VIEW_PARAMS_ENABLEDDAYRANGE_START = "enabled_day_range_start";
+ /**
+ * Last enabled day.
+ */
+ static final String VIEW_PARAMS_ENABLEDDAYRANGE_END = "enabled_day_range_end";
+
+ private static int DEFAULT_HEIGHT = 32;
+ private static int MIN_HEIGHT = 10;
+
+ private static final int DEFAULT_SELECTED_DAY = -1;
+ private static final int DEFAULT_WEEK_START = Calendar.SUNDAY;
+ private static final int DEFAULT_NUM_DAYS = 7;
+ private static final int DEFAULT_NUM_ROWS = 6;
+ private static final int MAX_NUM_ROWS = 6;
+
+ private static final int SELECTED_CIRCLE_ALPHA = 60;
+
+ private static int DAY_SEPARATOR_WIDTH = 1;
+
+ private int mMiniDayNumberTextSize;
+ private int mMonthLabelTextSize;
+ private int mMonthDayLabelTextSize;
+ private int mMonthHeaderSize;
+ private int mDaySelectedCircleSize;
+
+ // used for scaling to the device density
+ private static float mScale = 0;
+
+ // affects the padding on the sides of this view
+ private int mPadding = 0;
+
+ private String mDayOfWeekTypeface;
+ private String mMonthTitleTypeface;
+
+ private Paint mDayNumberPaint;
+ private Paint mDayNumberDisabledPaint;
+ private Paint mDayNumberSelectedPaint;
+
+ private Paint mMonthTitlePaint;
+ private Paint mMonthDayLabelPaint;
+
+ private final Formatter mFormatter;
+ private final StringBuilder mStringBuilder;
+
+ private int mMonth;
+ private int mYear;
+
+ // Quick reference to the width of this view, matches parent
+ private int mWidth;
+
+ // The height this view should draw at in pixels, set by height param
+ private int mRowHeight = DEFAULT_HEIGHT;
+
+ // If this view contains the today
+ private boolean mHasToday = false;
+
+ // Which day is selected [0-6] or -1 if no day is selected
+ private int mSelectedDay = -1;
+
+ // Which day is today [0-6] or -1 if no day is today
+ private int mToday = DEFAULT_SELECTED_DAY;
+
+ // Which day of the week to start on [0-6]
+ private int mWeekStart = DEFAULT_WEEK_START;
+
+ // How many days to display
+ private int mNumDays = DEFAULT_NUM_DAYS;
+
+ // The number of days + a spot for week number if it is displayed
+ private int mNumCells = mNumDays;
+
+ private int mDayOfWeekStart = 0;
+
+ // First enabled day
+ private int mEnabledDayStart = 1;
+
+ // Last enabled day
+ private int mEnabledDayEnd = 31;
+
+ private final Calendar mCalendar = Calendar.getInstance();
+ private final Calendar mDayLabelCalendar = Calendar.getInstance();
+
+ private final MonthViewTouchHelper mTouchHelper;
+
+ private int mNumRows = DEFAULT_NUM_ROWS;
+
+ // Optional listener for handling day click actions
+ private OnDayClickListener mOnDayClickListener;
+
+ // Whether to prevent setting the accessibility delegate
+ private boolean mLockAccessibilityDelegate;
+
+ private int mNormalTextColor;
+ private int mDisabledTextColor;
+ private int mSelectedDayColor;
+
+ public SimpleMonthView(Context context) {
+ this(context, null);
+ }
+
+ public SimpleMonthView(Context context, AttributeSet attrs) {
+ this(context, attrs, R.attr.datePickerStyle);
+ }
+
+ public SimpleMonthView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs);
+
+ final Resources res = context.getResources();
+
+ mDayOfWeekTypeface = res.getString(R.string.day_of_week_label_typeface);
+ mMonthTitleTypeface = res.getString(R.string.sans_serif);
+
+ mStringBuilder = new StringBuilder(50);
+ mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
+
+ mMiniDayNumberTextSize = res.getDimensionPixelSize(R.dimen.datepicker_day_number_size);
+ mMonthLabelTextSize = res.getDimensionPixelSize(R.dimen.datepicker_month_label_size);
+ mMonthDayLabelTextSize = res.getDimensionPixelSize(
+ R.dimen.datepicker_month_day_label_text_size);
+ mMonthHeaderSize = res.getDimensionPixelOffset(
+ R.dimen.datepicker_month_list_item_header_height);
+ mDaySelectedCircleSize = res.getDimensionPixelSize(
+ R.dimen.datepicker_day_number_select_circle_radius);
+
+ mRowHeight = (res.getDimensionPixelOffset(R.dimen.datepicker_view_animator_height)
+ - mMonthHeaderSize) / MAX_NUM_ROWS;
+
+ // Set up accessibility components.
+ mTouchHelper = new MonthViewTouchHelper(this);
+ setAccessibilityDelegate(mTouchHelper);
+ setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ mLockAccessibilityDelegate = true;
+
+ // Sets up any standard paints that will be used
+ initView();
+ }
+
+ void setTextColor(ColorStateList colors) {
+ final Resources res = getContext().getResources();
+
+ mNormalTextColor = colors.getColorForState(ENABLED_STATE_SET,
+ res.getColor(R.color.datepicker_default_normal_text_color_holo_light));
+ mMonthTitlePaint.setColor(mNormalTextColor);
+ mMonthDayLabelPaint.setColor(mNormalTextColor);
+
+ mDisabledTextColor = colors.getColorForState(EMPTY_STATE_SET,
+ res.getColor(R.color.datepicker_default_disabled_text_color_holo_light));
+ mDayNumberDisabledPaint.setColor(mDisabledTextColor);
+
+ mSelectedDayColor = colors.getColorForState(ENABLED_SELECTED_STATE_SET,
+ res.getColor(R.color.holo_blue_light));
+ mDayNumberSelectedPaint.setColor(mSelectedDayColor);
+ mDayNumberSelectedPaint.setAlpha(SELECTED_CIRCLE_ALPHA);
+ }
+
+ @Override
+ public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
+ // Workaround for a JB MR1 issue where accessibility delegates on
+ // top-level ListView items are overwritten.
+ if (!mLockAccessibilityDelegate) {
+ super.setAccessibilityDelegate(delegate);
+ }
+ }
+
+ public void setOnDayClickListener(OnDayClickListener listener) {
+ mOnDayClickListener = listener;
+ }
+
+ @Override
+ public boolean dispatchHoverEvent(MotionEvent event) {
+ // First right-of-refusal goes the touch exploration helper.
+ if (mTouchHelper.dispatchHoverEvent(event)) {
+ return true;
+ }
+ return super.dispatchHoverEvent(event);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_UP:
+ final int day = getDayFromLocation(event.getX(), event.getY());
+ if (day >= 0) {
+ onDayClick(day);
+ }
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * Sets up the text and style properties for painting.
+ */
+ private void initView() {
+ mMonthTitlePaint = new Paint();
+ mMonthTitlePaint.setAntiAlias(true);
+ mMonthTitlePaint.setColor(mNormalTextColor);
+ mMonthTitlePaint.setTextSize(mMonthLabelTextSize);
+ mMonthTitlePaint.setTypeface(Typeface.create(mMonthTitleTypeface, Typeface.BOLD));
+ mMonthTitlePaint.setTextAlign(Align.CENTER);
+ mMonthTitlePaint.setStyle(Style.FILL);
+ mMonthTitlePaint.setFakeBoldText(true);
+
+ mMonthDayLabelPaint = new Paint();
+ mMonthDayLabelPaint.setAntiAlias(true);
+ mMonthDayLabelPaint.setColor(mNormalTextColor);
+ mMonthDayLabelPaint.setTextSize(mMonthDayLabelTextSize);
+ mMonthDayLabelPaint.setTypeface(Typeface.create(mDayOfWeekTypeface, Typeface.NORMAL));
+ mMonthDayLabelPaint.setTextAlign(Align.CENTER);
+ mMonthDayLabelPaint.setStyle(Style.FILL);
+ mMonthDayLabelPaint.setFakeBoldText(true);
+
+ mDayNumberSelectedPaint = new Paint();
+ mDayNumberSelectedPaint.setAntiAlias(true);
+ mDayNumberSelectedPaint.setColor(mSelectedDayColor);
+ mDayNumberSelectedPaint.setAlpha(SELECTED_CIRCLE_ALPHA);
+ mDayNumberSelectedPaint.setTextAlign(Align.CENTER);
+ mDayNumberSelectedPaint.setStyle(Style.FILL);
+ mDayNumberSelectedPaint.setFakeBoldText(true);
+
+ mDayNumberPaint = new Paint();
+ mDayNumberPaint.setAntiAlias(true);
+ mDayNumberPaint.setTextSize(mMiniDayNumberTextSize);
+ mDayNumberPaint.setTextAlign(Align.CENTER);
+ mDayNumberPaint.setStyle(Style.FILL);
+ mDayNumberPaint.setFakeBoldText(false);
+
+ mDayNumberDisabledPaint = new Paint();
+ mDayNumberDisabledPaint.setAntiAlias(true);
+ mDayNumberDisabledPaint.setColor(mDisabledTextColor);
+ mDayNumberDisabledPaint.setTextSize(mMiniDayNumberTextSize);
+ mDayNumberDisabledPaint.setTextAlign(Align.CENTER);
+ mDayNumberDisabledPaint.setStyle(Style.FILL);
+ mDayNumberDisabledPaint.setFakeBoldText(false);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ drawMonthTitle(canvas);
+ drawWeekDayLabels(canvas);
+ drawDays(canvas);
+ }
+
+ /**
+ * Sets all the parameters for displaying this week. The only required
+ * parameter is the week number. Other parameters have a default value and
+ * will only update if a new value is included, except for focus month,
+ * which will always default to no focus month if no value is passed in. See
+ * {@link #VIEW_PARAMS_HEIGHT} for more info on parameters.
+ *
+ * @param params A map of the new parameters, see
+ * {@link #VIEW_PARAMS_HEIGHT}
+ */
+ void setMonthParams(HashMap<String, Integer> params) {
+ if (!params.containsKey(VIEW_PARAMS_MONTH) && !params.containsKey(VIEW_PARAMS_YEAR)) {
+ throw new InvalidParameterException(
+ "You must specify the month and year for this view");
+ }
+ setTag(params);
+ // We keep the current value for any params not present
+ if (params.containsKey(VIEW_PARAMS_HEIGHT)) {
+ mRowHeight = params.get(VIEW_PARAMS_HEIGHT);
+ if (mRowHeight < MIN_HEIGHT) {
+ mRowHeight = MIN_HEIGHT;
+ }
+ }
+ if (params.containsKey(VIEW_PARAMS_SELECTED_DAY)) {
+ mSelectedDay = params.get(VIEW_PARAMS_SELECTED_DAY);
+ }
+
+ // Allocate space for caching the day numbers and focus values
+ mMonth = params.get(VIEW_PARAMS_MONTH);
+ mYear = params.get(VIEW_PARAMS_YEAR);
+
+ // Figure out what day today is
+ final Time today = new Time(Time.getCurrentTimezone());
+ today.setToNow();
+ mHasToday = false;
+ mToday = -1;
+
+ mCalendar.set(Calendar.MONTH, mMonth);
+ mCalendar.set(Calendar.YEAR, mYear);
+ mCalendar.set(Calendar.DAY_OF_MONTH, 1);
+ mDayOfWeekStart = mCalendar.get(Calendar.DAY_OF_WEEK);
+
+ if (params.containsKey(VIEW_PARAMS_WEEK_START)) {
+ mWeekStart = params.get(VIEW_PARAMS_WEEK_START);
+ } else {
+ mWeekStart = mCalendar.getFirstDayOfWeek();
+ }
+
+ if (params.containsKey(VIEW_PARAMS_ENABLEDDAYRANGE_START)) {
+ mEnabledDayStart = params.get(VIEW_PARAMS_ENABLEDDAYRANGE_START);
+ }
+ if (params.containsKey(VIEW_PARAMS_ENABLEDDAYRANGE_END)) {
+ mEnabledDayEnd = params.get(VIEW_PARAMS_ENABLEDDAYRANGE_END);
+ }
+
+ mNumCells = getDaysInMonth(mMonth, mYear);
+ for (int i = 0; i < mNumCells; i++) {
+ final int day = i + 1;
+ if (sameDay(day, today)) {
+ mHasToday = true;
+ mToday = day;
+ }
+ }
+ mNumRows = calculateNumRows();
+
+ // Invalidate cached accessibility information.
+ mTouchHelper.invalidateRoot();
+ }
+
+ private static int getDaysInMonth(int month, int year) {
+ switch (month) {
+ case Calendar.JANUARY:
+ case Calendar.MARCH:
+ case Calendar.MAY:
+ case Calendar.JULY:
+ case Calendar.AUGUST:
+ case Calendar.OCTOBER:
+ case Calendar.DECEMBER:
+ return 31;
+ case Calendar.APRIL:
+ case Calendar.JUNE:
+ case Calendar.SEPTEMBER:
+ case Calendar.NOVEMBER:
+ return 30;
+ case Calendar.FEBRUARY:
+ return (year % 4 == 0) ? 29 : 28;
+ default:
+ throw new IllegalArgumentException("Invalid Month");
+ }
+ }
+
+ public void reuse() {
+ mNumRows = DEFAULT_NUM_ROWS;
+ requestLayout();
+ }
+
+ private int calculateNumRows() {
+ int offset = findDayOffset();
+ int dividend = (offset + mNumCells) / mNumDays;
+ int remainder = (offset + mNumCells) % mNumDays;
+ return (dividend + (remainder > 0 ? 1 : 0));
+ }
+
+ private boolean sameDay(int day, Time today) {
+ return mYear == today.year &&
+ mMonth == today.month &&
+ day == today.monthDay;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mRowHeight * mNumRows
+ + mMonthHeaderSize);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mWidth = w;
+
+ // Invalidate cached accessibility information.
+ mTouchHelper.invalidateRoot();
+ }
+
+ private String getMonthAndYearString() {
+ int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR
+ | DateUtils.FORMAT_NO_MONTH_DAY;
+ mStringBuilder.setLength(0);
+ long millis = mCalendar.getTimeInMillis();
+ return DateUtils.formatDateRange(getContext(), mFormatter, millis, millis, flags,
+ Time.getCurrentTimezone()).toString();
+ }
+
+ private void drawMonthTitle(Canvas canvas) {
+ int x = (mWidth + 2 * mPadding) / 2;
+ int y = (mMonthHeaderSize - mMonthDayLabelTextSize) / 2 + (mMonthLabelTextSize / 3);
+ canvas.drawText(getMonthAndYearString(), x, y, mMonthTitlePaint);
+ }
+
+ private void drawWeekDayLabels(Canvas canvas) {
+ int y = mMonthHeaderSize - (mMonthDayLabelTextSize / 2);
+ int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
+
+ for (int i = 0; i < mNumDays; i++) {
+ int calendarDay = (i + mWeekStart) % mNumDays;
+ int x = (2 * i + 1) * dayWidthHalf + mPadding;
+ mDayLabelCalendar.set(Calendar.DAY_OF_WEEK, calendarDay);
+ canvas.drawText(mDayLabelCalendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT,
+ Locale.getDefault()).toUpperCase(Locale.getDefault()), x, y,
+ mMonthDayLabelPaint);
+ }
+ }
+
+ /**
+ * Draws the month days.
+ */
+ private void drawDays(Canvas canvas) {
+ int y = (((mRowHeight + mMiniDayNumberTextSize) / 2) - DAY_SEPARATOR_WIDTH)
+ + mMonthHeaderSize;
+ int dayWidthHalf = (mWidth - mPadding * 2) / (mNumDays * 2);
+ int j = findDayOffset();
+ for (int day = 1; day <= mNumCells; day++) {
+ int x = (2 * j + 1) * dayWidthHalf + mPadding;
+ if (mSelectedDay == day) {
+ canvas.drawCircle(x, y - (mMiniDayNumberTextSize / 3), mDaySelectedCircleSize,
+ mDayNumberSelectedPaint);
+ }
+
+ if (mHasToday && mToday == day) {
+ mDayNumberPaint.setColor(mSelectedDayColor);
+ } else {
+ mDayNumberPaint.setColor(mNormalTextColor);
+ }
+ final Paint paint = (day < mEnabledDayStart || day > mEnabledDayEnd) ?
+ mDayNumberDisabledPaint : mDayNumberPaint;
+ canvas.drawText(String.format("%d", day), x, y, paint);
+ j++;
+ if (j == mNumDays) {
+ j = 0;
+ y += mRowHeight;
+ }
+ }
+ }
+
+ private int findDayOffset() {
+ return (mDayOfWeekStart < mWeekStart ? (mDayOfWeekStart + mNumDays) : mDayOfWeekStart)
+ - mWeekStart;
+ }
+
+ /**
+ * Calculates the day that the given x position is in, accounting for week
+ * number. Returns the day or -1 if the position wasn't in a day.
+ *
+ * @param x The x position of the touch event
+ * @return The day number, or -1 if the position wasn't in a day
+ */
+ private int getDayFromLocation(float x, float y) {
+ int dayStart = mPadding;
+ if (x < dayStart || x > mWidth - mPadding) {
+ return -1;
+ }
+ // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
+ int row = (int) (y - mMonthHeaderSize) / mRowHeight;
+ int column = (int) ((x - dayStart) * mNumDays / (mWidth - dayStart - mPadding));
+
+ int day = column - findDayOffset() + 1;
+ day += row * mNumDays;
+ if (day < 1 || day > mNumCells) {
+ return -1;
+ }
+ return day;
+ }
+
+ /**
+ * Called when the user clicks on a day. Handles callbacks to the
+ * {@link OnDayClickListener} if one is set.
+ *
+ * @param day The day that was clicked
+ */
+ private void onDayClick(int day) {
+ if (mOnDayClickListener != null) {
+ Calendar date = Calendar.getInstance();
+ date.set(mYear, mMonth, day);
+ mOnDayClickListener.onDayClick(this, date);
+ }
+
+ // This is a no-op if accessibility is turned off.
+ mTouchHelper.sendEventForVirtualView(day, AccessibilityEvent.TYPE_VIEW_CLICKED);
+ }
+
+ /**
+ * @return The date that has accessibility focus, or {@code null} if no date
+ * has focus
+ */
+ Calendar getAccessibilityFocus() {
+ final int day = mTouchHelper.getFocusedVirtualView();
+ Calendar date = null;
+ if (day >= 0) {
+ date = Calendar.getInstance();
+ date.set(mYear, mMonth, day);
+ }
+ return date;
+ }
+
+ /**
+ * Clears accessibility focus within the view. No-op if the view does not
+ * contain accessibility focus.
+ */
+ public void clearAccessibilityFocus() {
+ mTouchHelper.clearFocusedVirtualView();
+ }
+
+ /**
+ * Attempts to restore accessibility focus to the specified date.
+ *
+ * @param day The date which should receive focus
+ * @return {@code false} if the date is not valid for this month view, or
+ * {@code true} if the date received focus
+ */
+ boolean restoreAccessibilityFocus(Calendar day) {
+ if ((day.get(Calendar.YEAR) != mYear) || (day.get(Calendar.MONTH) != mMonth) ||
+ (day.get(Calendar.DAY_OF_MONTH) > mNumCells)) {
+ return false;
+ }
+ mTouchHelper.setFocusedVirtualView(day.get(Calendar.DAY_OF_MONTH));
+ return true;
+ }
+
+ /**
+ * Provides a virtual view hierarchy for interfacing with an accessibility
+ * service.
+ */
+ private class MonthViewTouchHelper extends ExploreByTouchHelper {
+ private static final String DATE_FORMAT = "dd MMMM yyyy";
+
+ private final Rect mTempRect = new Rect();
+ private final Calendar mTempCalendar = Calendar.getInstance();
+
+ public MonthViewTouchHelper(View host) {
+ super(host);
+ }
+
+ public void setFocusedVirtualView(int virtualViewId) {
+ getAccessibilityNodeProvider(SimpleMonthView.this).performAction(
+ virtualViewId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
+ }
+
+ public void clearFocusedVirtualView() {
+ final int focusedVirtualView = getFocusedVirtualView();
+ if (focusedVirtualView != ExploreByTouchHelper.INVALID_ID) {
+ getAccessibilityNodeProvider(SimpleMonthView.this).performAction(
+ focusedVirtualView,
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS,
+ null);
+ }
+ }
+
+ @Override
+ protected int getVirtualViewAt(float x, float y) {
+ final int day = getDayFromLocation(x, y);
+ if (day >= 0) {
+ return day;
+ }
+ return ExploreByTouchHelper.INVALID_ID;
+ }
+
+ @Override
+ protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
+ for (int day = 1; day <= mNumCells; day++) {
+ virtualViewIds.add(day);
+ }
+ }
+
+ @Override
+ protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
+ event.setContentDescription(getItemDescription(virtualViewId));
+ }
+
+ @Override
+ protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo node) {
+ getItemBounds(virtualViewId, mTempRect);
+
+ node.setContentDescription(getItemDescription(virtualViewId));
+ node.setBoundsInParent(mTempRect);
+ node.addAction(AccessibilityNodeInfo.ACTION_CLICK);
+
+ if (virtualViewId == mSelectedDay) {
+ node.setSelected(true);
+ }
+
+ }
+
+ @Override
+ protected boolean onPerformActionForVirtualView(int virtualViewId, int action,
+ Bundle arguments) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_CLICK:
+ onDayClick(virtualViewId);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Calculates the bounding rectangle of a given time object.
+ *
+ * @param day The day to calculate bounds for
+ * @param rect The rectangle in which to store the bounds
+ */
+ private void getItemBounds(int day, Rect rect) {
+ final int offsetX = mPadding;
+ final int offsetY = mMonthHeaderSize;
+ final int cellHeight = mRowHeight;
+ final int cellWidth = ((mWidth - (2 * mPadding)) / mNumDays);
+ final int index = ((day - 1) + findDayOffset());
+ final int row = (index / mNumDays);
+ final int column = (index % mNumDays);
+ final int x = (offsetX + (column * cellWidth));
+ final int y = (offsetY + (row * cellHeight));
+
+ rect.set(x, y, (x + cellWidth), (y + cellHeight));
+ }
+
+ /**
+ * Generates a description for a given time object. Since this
+ * description will be spoken, the components are ordered by descending
+ * specificity as DAY MONTH YEAR.
+ *
+ * @param day The day to generate a description for
+ * @return A description of the time object
+ */
+ private CharSequence getItemDescription(int day) {
+ mTempCalendar.set(mYear, mMonth, day);
+ final CharSequence date = DateFormat.format(DATE_FORMAT,
+ mTempCalendar.getTimeInMillis());
+
+ if (day == mSelectedDay) {
+ return getContext().getString(R.string.item_is_selected, date);
+ }
+
+ return date;
+ }
+ }
+
+ /**
+ * Handles callbacks when the user clicks on a time object.
+ */
+ public interface OnDayClickListener {
+ public void onDayClick(SimpleMonthView view, Calendar day);
+ }
+}
diff --git a/core/java/android/widget/TextViewWithCircularIndicator.java b/core/java/android/widget/TextViewWithCircularIndicator.java
new file mode 100644
index 0000000..22d770c
--- /dev/null
+++ b/core/java/android/widget/TextViewWithCircularIndicator.java
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+package android.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.util.AttributeSet;
+
+import com.android.internal.R;
+
+class TextViewWithCircularIndicator extends TextView {
+
+ private static final int SELECTED_CIRCLE_ALPHA = 60;
+
+ private final Paint mCirclePaint = new Paint();
+
+ private final String mItemIsSelectedText;
+ private int mCircleColor;
+ private boolean mDrawIndicator;
+
+ public TextViewWithCircularIndicator(Context context) {
+ this(context, null);
+ }
+
+ public TextViewWithCircularIndicator(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TextViewWithCircularIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public TextViewWithCircularIndicator(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+
+ super(context, attrs);
+ Resources res = context.getResources();
+
+ // Use Theme attributes if possible
+ final TypedArray a = mContext.obtainStyledAttributes(attrs,
+ R.styleable.DatePicker, defStyleAttr, defStyleRes);
+
+ final int resId = a.getResourceId(
+ R.styleable.DatePicker_dateSelectorYearListItemTextAppearance, -1);
+ if (resId != -1) {
+ setTextAppearance(context, resId);
+ }
+
+ mItemIsSelectedText = res.getString(R.string.item_is_selected);
+
+ a.recycle();
+
+ init();
+ }
+
+ private void init() {
+ mCirclePaint.setTypeface(Typeface.create(mCirclePaint.getTypeface(), Typeface.BOLD));
+ mCirclePaint.setAntiAlias(true);
+ mCirclePaint.setTextAlign(Paint.Align.CENTER);
+ mCirclePaint.setStyle(Paint.Style.FILL);
+ }
+
+ public void setCircleColor(int color) {
+ if (color != mCircleColor) {
+ mCircleColor = color;
+ mCirclePaint.setColor(mCircleColor);
+ mCirclePaint.setAlpha(SELECTED_CIRCLE_ALPHA);
+ requestLayout();
+ }
+ }
+
+ public void setDrawIndicator(boolean drawIndicator) {
+ mDrawIndicator = drawIndicator;
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (mDrawIndicator) {
+ final int width = getWidth();
+ final int height = getHeight();
+ int radius = Math.min(width, height) / 2;
+ canvas.drawCircle(width / 2, height / 2, radius, mCirclePaint);
+ }
+ }
+
+ @Override
+ public CharSequence getContentDescription() {
+ CharSequence itemText = getText();
+ if (mDrawIndicator) {
+ return String.format(mItemIsSelectedText, itemText);
+ } else {
+ return itemText;
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 5021960..58a6562 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -17,7 +17,6 @@
package android.widget;
import android.annotation.Widget;
-import android.app.UiModeManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
@@ -30,8 +29,6 @@
import java.util.Locale;
-import static android.os.Build.VERSION_CODES.L;
-
/**
* A view for selecting the time of day, in either 24 hour or AM/PM mode. The
* hour, each minute digit, and AM/PM (if applicable) can be conrolled by
@@ -41,20 +38,14 @@
* by entering single digits. Under AM/PM mode, the user can hit 'a', 'A", 'p'
* or 'P' to pick. For a dialog using this view, see
* {@link android.app.TimePickerDialog}.
- *<p>
+ * <p>
* See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
* guide.
* </p>
*/
@Widget
public class TimePicker extends FrameLayout {
-
- private TimePickerDelegate mDelegate;
-
- private AttributeSet mAttrs;
- private int mDefStyleAttr;
- private int mDefStyleRes;
- private Context mContext;
+ private final TimePickerDelegate mDelegate;
/**
* The callback interface used to indicate the time has been adjusted.
@@ -84,50 +75,18 @@
public TimePicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mContext = context;
- mAttrs = attrs;
- mDefStyleAttr = defStyleAttr;
- mDefStyleRes = defStyleRes;
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TimePicker,
- mDefStyleAttr, mDefStyleRes);
-
- // Create the correct UI delegate. Legacy mode is used when API Levels is below L
- // release or when it is a TV UI
- final boolean isLegacyMode = a.getBoolean(
- R.styleable.TimePicker_legacyMode, isLegacyMode());
-
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
+ final boolean legacyMode = a.getBoolean(R.styleable.TimePicker_legacyMode, true);
a.recycle();
- setLegacyMode(isLegacyMode);
- }
-
- private boolean isLegacyMode() {
- UiModeManager uiModeManager =
- (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
- if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
- return true;
+ if (legacyMode) {
+ mDelegate = new LegacyTimePickerDelegate(
+ this, context, attrs, defStyleAttr, defStyleRes);
+ } else {
+ mDelegate = new android.widget.TimePickerDelegate(
+ this, context, attrs, defStyleAttr, defStyleRes);
}
- final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
- return targetSdkVersion < L;
- }
-
- private TimePickerDelegate createLegacyUIDelegate(Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- return new LegacyTimePickerDelegate(this, context, attrs, defStyleAttr, defStyleRes);
- }
-
- private TimePickerDelegate createNewUIDelegate(Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- return new android.widget.TimePickerDelegate(this, context, attrs, defStyleAttr,
- defStyleRes);
- }
-
- private void setLegacyMode(boolean isLegacyMode) {
- removeAllViewsInLayout();
- mDelegate = isLegacyMode ?
- createLegacyUIDelegate(mContext, mAttrs, mDefStyleAttr, mDefStyleRes) :
- createNewUIDelegate(mContext, mAttrs, mDefStyleAttr, mDefStyleRes);
}
/**
@@ -185,9 +144,6 @@
@Override
public void setEnabled(boolean enabled) {
- if (mDelegate.isEnabled() == enabled) {
- return;
- }
super.setEnabled(enabled);
mDelegate.setEnabled(enabled);
}
diff --git a/core/java/android/widget/TimePickerDelegate.java b/core/java/android/widget/TimePickerDelegate.java
index bf3971c..a9af2f9 100644
--- a/core/java/android/widget/TimePickerDelegate.java
+++ b/core/java/android/widget/TimePickerDelegate.java
@@ -23,6 +23,7 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.Color;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -30,7 +31,6 @@
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -79,9 +79,6 @@
// Duration in ms of the pulse animation
private static final int PULSE_ANIMATOR_DURATION = 544;
- private static int[] TEXT_APPEARANCE_TIME_LABEL_ATTR =
- new int[] { R.attr.timePickerHeaderTimeLabelTextAppearance };
-
private final View mMainView;
private TextView mHourView;
private TextView mMinuteView;
@@ -92,7 +89,7 @@
private ViewGroup mLayoutButtons;
private int mHeaderSelectedColor;
- private int mHeaderUnSelectedColor;
+ private int mHeaderUnselectedColor;
private String mAmText;
private String mPmText;
@@ -140,17 +137,14 @@
mSelectMinutes = res.getString(R.string.select_minutes);
mHeaderSelectedColor = a.getColor(R.styleable.TimePicker_headerSelectedTextColor,
- R.color.timepicker_default_selector_color_material);
+ res.getColor(R.color.timepicker_default_selector_color_material));
- mHeaderUnSelectedColor = getUnselectedColor(R.color.timepicker_default_text_color_material);
- if (mHeaderUnSelectedColor == -1) {
- mHeaderUnSelectedColor = a.getColor(R.styleable.TimePicker_headerUnselectedTextColor,
- R.color.timepicker_default_text_color_material);
- }
-
+ final int headerTimeTextAppearance = a.getResourceId(
+ R.styleable.TimePicker_headerTimeTextAppearance, 0);
+ final int headerAmPmTextAppearance = a.getResourceId(
+ R.styleable.TimePicker_headerAmPmTextAppearance, 0);
final int headerBackgroundColor = a.getColor(
- R.styleable.TimePicker_headerBackgroundColor, 0);
-
+ R.styleable.TimePicker_headerBackgroundColor, Color.TRANSPARENT);
final int layoutResourceId = a.getResourceId(
R.styleable.TimePicker_internalLayout, R.layout.time_picker_holo);
@@ -162,18 +156,32 @@
mMainView = inflater.inflate(layoutResourceId, null);
mDelegator.addView(mMainView);
- if (headerBackgroundColor != 0) {
- RelativeLayout header = (RelativeLayout) mMainView.findViewById(R.id.time_header);
- header.setBackgroundColor(headerBackgroundColor);
- }
-
mHourView = (TextView) mMainView.findViewById(R.id.hours);
+ mSeparatorView = (TextView) mMainView.findViewById(R.id.separator);
mMinuteView = (TextView) mMainView.findViewById(R.id.minutes);
mAmPmTextView = (TextView) mMainView.findViewById(R.id.ampm_label);
- mSeparatorView = (TextView) mMainView.findViewById(R.id.separator);
- mRadialTimePickerView = (RadialTimePickerView) mMainView.findViewById(R.id.radial_picker);
-
mLayoutButtons = (ViewGroup) mMainView.findViewById(R.id.layout_buttons);
+
+ // Set up text appearances from style.
+ if (headerTimeTextAppearance != 0) {
+ mHourView.setTextAppearance(context, headerTimeTextAppearance);
+ mSeparatorView.setTextAppearance(context, headerTimeTextAppearance);
+ mMinuteView.setTextAppearance(context, headerTimeTextAppearance);
+ }
+
+ if (headerAmPmTextAppearance != 0) {
+ mAmPmTextView.setTextAppearance(context, headerAmPmTextAppearance);
+ }
+
+ if (headerBackgroundColor != Color.TRANSPARENT) {
+ mLayoutButtons.setBackgroundColor(headerBackgroundColor);
+ mMainView.findViewById(R.id.time_header).setBackgroundColor(headerBackgroundColor);
+ }
+
+ // Load unselected header color from current state.
+ mHeaderUnselectedColor = mHourView.getCurrentTextColor();
+
+ mRadialTimePickerView = (RadialTimePickerView) mMainView.findViewById(R.id.radial_picker);
mDoneButton = (Button) mMainView.findViewById(R.id.done_button);
String[] amPmTexts = new DateFormatSymbols().getAmPmStrings();
@@ -198,25 +206,6 @@
initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX, false);
}
- private int getUnselectedColor(int defColor) {
- int result = -1;
- final Resources.Theme theme = mContext.getTheme();
- final TypedValue outValue = new TypedValue();
- theme.resolveAttribute(R.attr.timePickerHeaderTimeLabelTextAppearance, outValue, true);
- final int appearanceResId = outValue.resourceId;
- TypedArray appearance = null;
- if (appearanceResId != -1) {
- appearance = theme.obtainStyledAttributes(appearanceResId,
- com.android.internal.R.styleable.TextAppearance);
- }
- if (appearance != null) {
- result = appearance.getColor(
- com.android.internal.R.styleable.TextAppearance_textColor, defColor);
- appearance.recycle();
- }
- return result;
- }
-
private void initialize(int hourOfDay, int minute, boolean is24HourView, int index,
boolean showDoneButton) {
mInitialHourOfDay = hourOfDay;
@@ -292,11 +281,7 @@
private int computeMaxWidthOfNumbers(int max) {
TextView tempView = new TextView(mContext);
- TypedArray a = mContext.obtainStyledAttributes(TEXT_APPEARANCE_TIME_LABEL_ATTR);
- final int textAppearanceResId = a.getResourceId(0, 0);
- tempView.setTextAppearance(mContext, (textAppearanceResId != 0) ?
- textAppearanceResId : R.style.TextAppearance_Material_TimePicker_TimeLabel);
- a.recycle();
+ tempView.setTextAppearance(mContext, R.style.TextAppearance_Material_TimePicker_TimeLabel);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
tempView.setLayoutParams(lp);
@@ -799,6 +784,7 @@
separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1));
}
mSeparatorView.setText(separatorText);
+ mSeparatorView.setTextColor(mHeaderUnselectedColor);
}
static private int lastIndexOfAny(String str, char[] any) {
@@ -852,8 +838,8 @@
labelToAnimate = mMinuteView;
}
- int hourColor = (index == HOUR_INDEX) ? mHeaderSelectedColor : mHeaderUnSelectedColor;
- int minuteColor = (index == MINUTE_INDEX) ? mHeaderSelectedColor : mHeaderUnSelectedColor;
+ int hourColor = (index == HOUR_INDEX) ? mHeaderSelectedColor : mHeaderUnselectedColor;
+ int minuteColor = (index == MINUTE_INDEX) ? mHeaderSelectedColor : mHeaderUnselectedColor;
mHourView.setTextColor(hourColor);
mMinuteView.setTextColor(minuteColor);
@@ -1077,9 +1063,9 @@
String minuteStr = (values[1] == -1) ? mDoublePlaceholderText :
String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText);
mHourView.setText(hourStr);
- mHourView.setTextColor(mHeaderUnSelectedColor);
+ mHourView.setTextColor(mHeaderUnselectedColor);
mMinuteView.setText(minuteStr);
- mMinuteView.setTextColor(mHeaderUnSelectedColor);
+ mMinuteView.setTextColor(mHeaderUnselectedColor);
if (!mIs24HourView) {
updateAmPmDisplay(values[2]);
}
@@ -1389,8 +1375,8 @@
final Keyframe k2 = Keyframe.ofFloat(0.69f, increaseRatio);
final Keyframe k3 = Keyframe.ofFloat(1f, 1f);
- PropertyValuesHolder scaleX = PropertyValuesHolder.ofKeyframe("scaleX", k0, k1, k2, k3);
- PropertyValuesHolder scaleY = PropertyValuesHolder.ofKeyframe("scaleY", k0, k1, k2, k3);
+ PropertyValuesHolder scaleX = PropertyValuesHolder.ofKeyframe(View.SCALE_X, k0, k1, k2, k3);
+ PropertyValuesHolder scaleY = PropertyValuesHolder.ofKeyframe(View.SCALE_Y, k0, k1, k2, k3);
ObjectAnimator pulseAnimator =
ObjectAnimator.ofPropertyValuesHolder(labelToAnimate, scaleX, scaleY);
pulseAnimator.setDuration(PULSE_ANIMATOR_DURATION);
diff --git a/core/java/android/widget/YearPickerView.java b/core/java/android/widget/YearPickerView.java
new file mode 100644
index 0000000..bac9320
--- /dev/null
+++ b/core/java/android/widget/YearPickerView.java
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+package android.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+
+import java.util.Calendar;
+
+import com.android.internal.R;
+
+/**
+ * Displays a selectable list of years.
+ */
+class YearPickerView extends ListView implements AdapterView.OnItemClickListener,
+ OnDateChangedListener {
+ private static final String TAG = "YearPickerView";
+
+ private DatePickerController mController;
+ private YearAdapter mAdapter;
+ private int mViewSize;
+ private int mChildSize;
+ private int mSelectedPosition = -1;
+ private int mYearSelectedCircleColor;
+
+ public YearPickerView(Context context) {
+ this(context, null);
+ }
+
+ public YearPickerView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public YearPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public YearPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ ViewGroup.LayoutParams frame = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT,
+ LayoutParams.WRAP_CONTENT);
+ setLayoutParams(frame);
+
+ Resources res = context.getResources();
+ mViewSize = res.getDimensionPixelOffset(R.dimen.datepicker_view_animator_height);
+ mChildSize = res.getDimensionPixelOffset(R.dimen.datepicker_year_label_height);
+
+ setVerticalFadingEdgeEnabled(true);
+ setFadingEdgeLength(mChildSize / 3);
+
+ final int paddingTop = res.getDimensionPixelSize(
+ R.dimen.datepicker_year_picker_padding_top);
+ setPadding(0, paddingTop, 0, 0);
+
+ // Use Theme attributes if possible
+ final TypedArray a = context.obtainStyledAttributes(attrs,
+ R.styleable.DatePicker, defStyleAttr, defStyleRes);
+
+ final int colorResId = a.getResourceId(
+ R.styleable.DatePicker_dateSelectorYearListSelectedCircleColor,
+ R.color.datepicker_default_circle_background_color_holo_light);
+ mYearSelectedCircleColor = res.getColor(colorResId);
+
+ a.recycle();
+
+ setOnItemClickListener(this);
+ setDividerHeight(0);
+ }
+
+ public void init(DatePickerController controller) {
+ mController = controller;
+ mController.registerOnDateChangedListener(this);
+
+ mAdapter = new YearAdapter(getContext(), R.layout.year_label_text_view);
+ updateAdapterData();
+ setAdapter(mAdapter);
+
+ onDateChanged();
+ }
+
+ public void setYearSelectedCircleColor(int color) {
+ if (color != mYearSelectedCircleColor) {
+ mYearSelectedCircleColor = color;
+ }
+ requestLayout();
+ }
+
+ public int getYearSelectedCircleColor() {
+ return mYearSelectedCircleColor;
+ }
+
+ private void updateAdapterData() {
+ mAdapter.clear();
+ final int maxYear = mController.getMaxYear();
+ for (int year = mController.getMinYear(); year <= maxYear; year++) {
+ mAdapter.add(year);
+ }
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ mController.tryVibrate();
+ if (position != mSelectedPosition) {
+ mSelectedPosition = position;
+ mAdapter.notifyDataSetChanged();
+ }
+ mController.onYearSelected(mAdapter.getItem(position));
+ }
+
+ void setItemTextAppearance(int resId) {
+ mAdapter.setItemTextAppearance(resId);
+ }
+
+ private class YearAdapter extends ArrayAdapter<Integer> {
+ int mItemTextAppearanceResId;
+
+ public YearAdapter(Context context, int resource) {
+ super(context, resource);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextViewWithCircularIndicator v = (TextViewWithCircularIndicator)
+ super.getView(position, convertView, parent);
+ v.setTextAppearance(getContext(), mItemTextAppearanceResId);
+ v.requestLayout();
+ int year = getItem(position);
+ boolean selected = mController.getSelectedDay().get(Calendar.YEAR) == year;
+ v.setDrawIndicator(selected);
+ if (selected) {
+ v.setCircleColor(mYearSelectedCircleColor);
+ }
+ return v;
+ }
+
+ public void setItemTextAppearance(int resId) {
+ mItemTextAppearanceResId = resId;
+ }
+ }
+
+ public void postSetSelectionCentered(final int position) {
+ postSetSelectionFromTop(position, mViewSize / 2 - mChildSize / 2);
+ }
+
+ public void postSetSelectionFromTop(final int position, final int offset) {
+ post(new Runnable() {
+
+ @Override
+ public void run() {
+ setSelectionFromTop(position, offset);
+ requestLayout();
+ }
+ });
+ }
+
+ public int getFirstPositionOffset() {
+ final View firstChild = getChildAt(0);
+ if (firstChild == null) {
+ return 0;
+ }
+ return firstChild.getTop();
+ }
+
+ @Override
+ public void onDateChanged() {
+ updateAdapterData();
+ mAdapter.notifyDataSetChanged();
+ postSetSelectionCentered(
+ mController.getSelectedDay().get(Calendar.YEAR) - mController.getMinYear());
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ event.setFromIndex(0);
+ event.setToIndex(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 98a5843..901d6e6 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -47,6 +47,10 @@
void noteProcessStart(String name, int uid);
void noteProcessState(String name, int uid, int state);
void noteProcessFinish(String name, int uid);
+ void noteSyncStart(String name, int uid);
+ void noteSyncFinish(String name, int uid);
+ void noteJobStart(String name, int uid);
+ void noteJobFinish(String name, int uid);
void noteStartWakelock(int uid, int pid, String name, String historyName,
int type, boolean unimportantForLogging);
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index a866ca7..06fe3bf 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -16,6 +16,7 @@
package com.android.internal.app;
+import android.content.res.TypedArray;
import com.android.internal.R;
import android.app.ActivityManagerNative;
@@ -227,6 +228,12 @@
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
+
+ final int[] attrs = { android.R.attr.colorBackground };
+ final TypedArray a = getActivity().getTheme().obtainStyledAttributes(attrs);
+ getListView().setBackgroundColor(a.getColor(0, android.R.color.transparent));
+ a.recycle();
+
final ArrayAdapter<LocaleInfo> adapter = constructAdapter(getActivity(),
isInDeveloperMode());
setListAdapter(adapter);
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 8b56ceb..7e58351 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -56,7 +56,7 @@
public class LocalTransport extends BackupTransport {
private static final String TAG = "LocalTransport";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
private static final String TRANSPORT_DIR_NAME
= "com.android.internal.backup.LocalTransport";
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index 247c8fe..cfeca08 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -80,6 +80,15 @@
@Override
public int compareTo(BatterySipper other) {
+ // Over-counted always goes to the bottom.
+ if (drainType != other.drainType) {
+ if (drainType == DrainType.OVERCOUNTED) {
+ // This is "larger"
+ return 1;
+ } else if (other.drainType == DrainType.OVERCOUNTED) {
+ return -1;
+ }
+ }
// Return the flipped value because we want the items in descending order
return Double.compare(other.value, value);
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 023ba03..6c9b4b8 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -48,7 +48,6 @@
import java.util.Comparator;
import java.util.List;
import java.util.Map;
-import java.util.Arrays;
/**
* A helper class for retrieving the power usage information for all applications and services.
@@ -95,6 +94,7 @@
private long mStatsPeriod = 0;
private double mMaxPower = 1;
+ private double mMaxRealPower = 1;
private double mComputedPower;
private double mTotalPower;
private double mWifiPower;
@@ -208,6 +208,7 @@
getStats();
mMaxPower = 0;
+ mMaxRealPower = 0;
mComputedPower = 0;
mTotalPower = 0;
mWifiPower = 0;
@@ -542,6 +543,7 @@
} else {
mUsageList.add(app);
if (power > mMaxPower) mMaxPower = power;
+ if (power > mMaxRealPower) mMaxRealPower = power;
mComputedPower += power;
}
if (u.getUid() == 0) {
@@ -567,6 +569,7 @@
osApp.value += power;
osApp.values[0] += power;
if (osApp.value > mMaxPower) mMaxPower = osApp.value;
+ if (osApp.value > mMaxRealPower) mMaxRealPower = osApp.value;
mComputedPower += power;
}
}
@@ -806,6 +809,7 @@
private BatterySipper addEntry(DrainType drainType, long time, double power) {
mComputedPower += power;
+ if (power > mMaxRealPower) mMaxRealPower = power;
return addEntryNoTotal(drainType, time, power);
}
@@ -831,6 +835,8 @@
public double getMaxPower() { return mMaxPower; }
+ public double getMaxRealPower() { return mMaxRealPower; }
+
public double getTotalPower() { return mTotalPower; }
public double getComputedPower() { return mComputedPower; }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6ca048e..dec94f2 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -91,7 +91,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 109 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 112 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -2109,6 +2109,11 @@
return;
}
+ if (dataSize == 0) {
+ // The history is currently empty; we need it to start with a time stamp.
+ cur.currentTime = System.currentTimeMillis();
+ addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_RESET, cur);
+ }
addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.CMD_UPDATE, cur);
}
@@ -2362,6 +2367,50 @@
elapsedRealtime);
}
+ public void noteSyncStartLocked(String name, int uid) {
+ uid = mapUid(uid);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime);
+ if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) {
+ return;
+ }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid);
+ }
+
+ public void noteSyncFinishLocked(String name, int uid) {
+ uid = mapUid(uid);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime);
+ if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) {
+ return;
+ }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid);
+ }
+
+ public void noteJobStartLocked(String name, int uid) {
+ uid = mapUid(uid);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime);
+ if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) {
+ return;
+ }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid);
+ }
+
+ public void noteJobFinishLocked(String name, int uid) {
+ uid = mapUid(uid);
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime);
+ if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) {
+ return;
+ }
+ addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
+ }
+
private void requestWakelockCpuUpdate() {
if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
@@ -3833,6 +3882,16 @@
final ArrayMap<String, Wakelock> mWakelockStats = new ArrayMap<String, Wakelock>();
/**
+ * The statistics we have collected for this uid's syncs.
+ */
+ final ArrayMap<String, StopwatchTimer> mSyncStats = new ArrayMap<String, StopwatchTimer>();
+
+ /**
+ * The statistics we have collected for this uid's jobs.
+ */
+ final ArrayMap<String, StopwatchTimer> mJobStats = new ArrayMap<String, StopwatchTimer>();
+
+ /**
* The statistics we have collected for this uid's sensor activations.
*/
final SparseArray<Sensor> mSensorStats = new SparseArray<Sensor>();
@@ -3872,6 +3931,16 @@
}
@Override
+ public Map<String, ? extends BatteryStats.Timer> getSyncStats() {
+ return mSyncStats;
+ }
+
+ @Override
+ public Map<String, ? extends BatteryStats.Timer> getJobStats() {
+ return mJobStats;
+ }
+
+ @Override
public SparseArray<? extends BatteryStats.Uid.Sensor> getSensorStats() {
return mSensorStats;
}
@@ -4396,6 +4465,24 @@
active = true;
}
}
+ for (int is=mSyncStats.size()-1; is>=0; is--) {
+ StopwatchTimer timer = mSyncStats.valueAt(is);
+ if (timer.reset(false)) {
+ mSyncStats.removeAt(is);
+ timer.detach();
+ } else {
+ active = true;
+ }
+ }
+ for (int ij=mJobStats.size()-1; ij>=0; ij--) {
+ StopwatchTimer timer = mJobStats.valueAt(ij);
+ if (timer.reset(false)) {
+ mJobStats.removeAt(ij);
+ timer.detach();
+ } else {
+ active = true;
+ }
+ }
for (int ise=mSensorStats.size()-1; ise>=0; ise--) {
Sensor s = mSensorStats.valueAt(ise);
if (s.reset()) {
@@ -4497,6 +4584,22 @@
wakelock.writeToParcelLocked(out, elapsedRealtimeUs);
}
+ int NS = mSyncStats.size();
+ out.writeInt(NS);
+ for (int is=0; is<NS; is++) {
+ out.writeString(mSyncStats.keyAt(is));
+ StopwatchTimer timer = mSyncStats.valueAt(is);
+ Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
+ }
+
+ int NJ = mJobStats.size();
+ out.writeInt(NJ);
+ for (int ij=0; ij<NJ; ij++) {
+ out.writeString(mJobStats.keyAt(ij));
+ StopwatchTimer timer = mJobStats.valueAt(ij);
+ Timer.writeTimerToParcel(out, timer, elapsedRealtimeUs);
+ }
+
int NSE = mSensorStats.size();
out.writeInt(NSE);
for (int ise=0; ise<NSE; ise++) {
@@ -4618,6 +4721,25 @@
mWakelockStats.put(wakelockName, wakelock);
}
+ int numSyncs = in.readInt();
+ mSyncStats.clear();
+ for (int j = 0; j < numSyncs; j++) {
+ String syncName = in.readString();
+ if (in.readInt() != 0) {
+ mSyncStats.put(syncName,
+ new StopwatchTimer(Uid.this, SYNC, null, timeBase, in));
+ }
+ }
+
+ int numJobs = in.readInt();
+ mJobStats.clear();
+ for (int j = 0; j < numJobs; j++) {
+ String jobName = in.readString();
+ if (in.readInt() != 0) {
+ mJobStats.put(jobName, new StopwatchTimer(Uid.this, JOB, null, timeBase, in));
+ }
+ }
+
int numSensors = in.readInt();
mSensorStats.clear();
for (int k = 0; k < numSensors; k++) {
@@ -5670,6 +5792,38 @@
return ss;
}
+ public StopwatchTimer getSyncTimerLocked(String name) {
+ StopwatchTimer t = mSyncStats.get(name);
+ if (t == null) {
+ final int N = mSyncStats.size();
+ if (N > MAX_WAKELOCKS_PER_UID) {
+ name = BATCHED_WAKELOCK_NAME;
+ t = mSyncStats.get(name);
+ }
+ if (t == null) {
+ t = new StopwatchTimer(Uid.this, SYNC, null, mOnBatteryTimeBase);
+ mSyncStats.put(name, t);
+ }
+ }
+ return t;
+ }
+
+ public StopwatchTimer getJobTimerLocked(String name) {
+ StopwatchTimer t = mJobStats.get(name);
+ if (t == null) {
+ final int N = mJobStats.size();
+ if (N > MAX_WAKELOCKS_PER_UID) {
+ name = BATCHED_WAKELOCK_NAME;
+ t = mJobStats.get(name);
+ }
+ if (t == null) {
+ t = new StopwatchTimer(Uid.this, JOB, null, mOnBatteryTimeBase);
+ mJobStats.put(name, t);
+ }
+ }
+ return t;
+ }
+
public StopwatchTimer getWakeTimerLocked(String name, int type) {
Wakelock wl = mWakelockStats.get(name);
if (wl == null) {
@@ -5737,6 +5891,34 @@
return t;
}
+ public void noteStartSyncLocked(String name, long elapsedRealtimeMs) {
+ StopwatchTimer t = getSyncTimerLocked(name);
+ if (t != null) {
+ t.startRunningLocked(elapsedRealtimeMs);
+ }
+ }
+
+ public void noteStopSyncLocked(String name, long elapsedRealtimeMs) {
+ StopwatchTimer t = getSyncTimerLocked(name);
+ if (t != null) {
+ t.stopRunningLocked(elapsedRealtimeMs);
+ }
+ }
+
+ public void noteStartJobLocked(String name, long elapsedRealtimeMs) {
+ StopwatchTimer t = getJobTimerLocked(name);
+ if (t != null) {
+ t.startRunningLocked(elapsedRealtimeMs);
+ }
+ }
+
+ public void noteStopJobLocked(String name, long elapsedRealtimeMs) {
+ StopwatchTimer t = getJobTimerLocked(name);
+ if (t != null) {
+ t.stopRunningLocked(elapsedRealtimeMs);
+ }
+ }
+
public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
StopwatchTimer t = getWakeTimerLocked(name, type);
if (t != null) {
@@ -7170,7 +7352,7 @@
// the last run until samples in this run.
if (mHistoryBaseTime > 0) {
long oldnow = SystemClock.elapsedRealtime();
- mHistoryBaseTime = (mHistoryBaseTime - oldnow) + 60*1000;
+ mHistoryBaseTime = mHistoryBaseTime - oldnow + 1;
if (DEBUG_HISTORY) {
StringBuilder sb = new StringBuilder(128);
sb.append("****************** ADJUSTED mHistoryBaseTime: ");
@@ -7433,6 +7615,26 @@
}
}
+ int NS = in.readInt();
+ if (NS > 100) {
+ Slog.w(TAG, "File corrupt: too many syncs " + NS);
+ return;
+ }
+ for (int is = 0; is < NS; is++) {
+ String name = in.readString();
+ u.getSyncTimerLocked(name).readSummaryFromParcelLocked(in);
+ }
+
+ int NJ = in.readInt();
+ if (NJ > 100) {
+ Slog.w(TAG, "File corrupt: too many job timers " + NJ);
+ return;
+ }
+ for (int ij = 0; ij < NJ; ij++) {
+ String name = in.readString();
+ u.getJobTimerLocked(name).readSummaryFromParcelLocked(in);
+ }
+
int NP = in.readInt();
if (NP > 1000) {
Slog.w(TAG, "File corrupt: too many sensors " + NP);
@@ -7484,7 +7686,7 @@
String pkgName = in.readString();
Uid.Pkg p = u.getPackageStatsLocked(pkgName);
p.mWakeups = p.mLoadedWakeups = in.readInt();
- final int NS = in.readInt();
+ NS = in.readInt();
if (NS > 1000) {
Slog.w(TAG, "File corrupt: too many services " + NS);
return;
@@ -7717,6 +7919,20 @@
}
}
+ int NS = u.mSyncStats.size();
+ out.writeInt(NS);
+ for (int is=0; is<NS; is++) {
+ out.writeString(u.mSyncStats.keyAt(is));
+ u.mSyncStats.valueAt(is).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+ }
+
+ int NJ = u.mJobStats.size();
+ out.writeInt(NJ);
+ for (int ij=0; ij<NJ; ij++) {
+ out.writeString(u.mJobStats.keyAt(ij));
+ u.mJobStats.valueAt(ij).writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+ }
+
int NSE = u.mSensorStats.size();
out.writeInt(NSE);
for (int ise=0; ise<NSE; ise++) {
@@ -7760,7 +7976,7 @@
out.writeString(ent.getKey());
Uid.Pkg ps = ent.getValue();
out.writeInt(ps.mWakeups);
- final int NS = ps.mServiceStats.size();
+ NS = ps.mServiceStats.size();
out.writeInt(NS);
if (NS > 0) {
for (Map.Entry<String, BatteryStatsImpl.Uid.Pkg.Serv> sent
@@ -7786,7 +8002,7 @@
void readFromParcelLocked(Parcel in) {
int magic = in.readInt();
if (magic != MAGIC) {
- throw new ParcelFormatException("Bad magic number");
+ throw new ParcelFormatException("Bad magic number: #" + Integer.toHexString(magic));
}
readHistory(in, false);
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 7f6159d..3ed4d51 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -16,10 +16,14 @@
package com.android.internal.util;
+import android.util.ArraySet;
+
import dalvik.system.VMRuntime;
+
import libcore.util.EmptyArray;
import java.lang.reflect.Array;
+import java.util.ArrayList;
/**
* ArrayUtils contains some methods that you can call to find out
@@ -332,4 +336,52 @@
public static long[] cloneOrNull(long[] array) {
return (array != null) ? array.clone() : null;
}
+
+ public static <T> ArraySet<T> add(ArraySet<T> cur, T val) {
+ if (cur == null) {
+ cur = new ArraySet<>();
+ }
+ cur.add(val);
+ return cur;
+ }
+
+ public static <T> ArraySet<T> remove(ArraySet<T> cur, T val) {
+ if (cur == null) {
+ return null;
+ }
+ cur.remove(val);
+ if (cur.isEmpty()) {
+ return null;
+ } else {
+ return cur;
+ }
+ }
+
+ public static <T> boolean contains(ArraySet<T> cur, T val) {
+ return (cur != null) ? cur.contains(val) : false;
+ }
+
+ public static <T> ArrayList<T> add(ArrayList<T> cur, T val) {
+ if (cur == null) {
+ cur = new ArrayList<>();
+ }
+ cur.add(val);
+ return cur;
+ }
+
+ public static <T> ArrayList<T> remove(ArrayList<T> cur, T val) {
+ if (cur == null) {
+ return null;
+ }
+ cur.remove(val);
+ if (cur.isEmpty()) {
+ return null;
+ } else {
+ return cur;
+ }
+ }
+
+ public static <T> boolean contains(ArrayList<T> cur, T val) {
+ return (cur != null) ? cur.contains(val) : false;
+ }
}
diff --git a/core/java/com/android/internal/widget/AccessibleDateAnimator.java b/core/java/com/android/internal/widget/AccessibleDateAnimator.java
new file mode 100644
index 0000000..e91a55c
--- /dev/null
+++ b/core/java/com/android/internal/widget/AccessibleDateAnimator.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.widget;
+
+import android.content.Context;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.ViewAnimator;
+
+/**
+ * @hide
+ */
+public class AccessibleDateAnimator extends ViewAnimator {
+ private long mDateMillis;
+
+ public AccessibleDateAnimator(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setDateMillis(long dateMillis) {
+ mDateMillis = dateMillis;
+ }
+
+ /**
+ * Announce the currently-selected date when launched.
+ */
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+ // Clear the event's current text so that only the current date will be spoken.
+ event.getText().clear();
+ int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR |
+ DateUtils.FORMAT_SHOW_WEEKDAY;
+
+ String dateString = DateUtils.formatDateTime(getContext(), mDateMillis, flags);
+ event.getText().add(dateString);
+ return true;
+ }
+ return super.dispatchPopulateAccessibilityEvent(event);
+ }
+}
diff --git a/core/java/com/android/internal/widget/ExploreByTouchHelper.java b/core/java/com/android/internal/widget/ExploreByTouchHelper.java
new file mode 100644
index 0000000..11c4ca1
--- /dev/null
+++ b/core/java/com/android/internal/widget/ExploreByTouchHelper.java
@@ -0,0 +1,719 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.accessibility.*;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeProvider;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * ExploreByTouchHelper is a utility class for implementing accessibility
+ * support in custom {@link android.view.View}s that represent a collection of View-like
+ * logical items. It extends {@link android.view.accessibility.AccessibilityNodeProvider} and
+ * simplifies many aspects of providing information to accessibility services
+ * and managing accessibility focus. This class does not currently support
+ * hierarchies of logical items.
+ * <p>
+ * This should be applied to the parent view using
+ * {@link android.view.View#setAccessibilityDelegate}:
+ *
+ * <pre>
+ * mAccessHelper = ExploreByTouchHelper.create(someView, mAccessHelperCallback);
+ * ViewCompat.setAccessibilityDelegate(someView, mAccessHelper);
+ * </pre>
+ */
+public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
+ /** Virtual node identifier value for invalid nodes. */
+ public static final int INVALID_ID = Integer.MIN_VALUE;
+
+ /** Default class name used for virtual views. */
+ private static final String DEFAULT_CLASS_NAME = View.class.getName();
+
+ // Temporary, reusable data structures.
+ private final Rect mTempScreenRect = new Rect();
+ private final Rect mTempParentRect = new Rect();
+ private final Rect mTempVisibleRect = new Rect();
+ private final int[] mTempGlobalRect = new int[2];
+
+ /** View's context **/
+ private Context mContext;
+
+ /** System accessibility manager, used to check state and send events. */
+ private final AccessibilityManager mManager;
+
+ /** View whose internal structure is exposed through this helper. */
+ private final View mView;
+
+ /** Node provider that handles creating nodes and performing actions. */
+ private ExploreByTouchNodeProvider mNodeProvider;
+
+ /** Virtual view id for the currently focused logical item. */
+ private int mFocusedVirtualViewId = INVALID_ID;
+
+ /** Virtual view id for the currently hovered logical item. */
+ private int mHoveredVirtualViewId = INVALID_ID;
+
+ /**
+ * Factory method to create a new {@link ExploreByTouchHelper}.
+ *
+ * @param forView View whose logical children are exposed by this helper.
+ */
+ public ExploreByTouchHelper(View forView) {
+ if (forView == null) {
+ throw new IllegalArgumentException("View may not be null");
+ }
+
+ mView = forView;
+ mContext = forView.getContext();
+ mManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ }
+
+ /**
+ * Returns the {@link android.view.accessibility.AccessibilityNodeProvider} for this helper.
+ *
+ * @param host View whose logical children are exposed by this helper.
+ * @return The accessibility node provider for this helper.
+ */
+ @Override
+ public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
+ if (mNodeProvider == null) {
+ mNodeProvider = new ExploreByTouchNodeProvider();
+ }
+ return mNodeProvider;
+ }
+
+ /**
+ * Dispatches hover {@link android.view.MotionEvent}s to the virtual view hierarchy when
+ * the Explore by Touch feature is enabled.
+ * <p>
+ * This method should be called by overriding
+ * {@link View#dispatchHoverEvent}:
+ *
+ * <pre>@Override
+ * public boolean dispatchHoverEvent(MotionEvent event) {
+ * if (mHelper.dispatchHoverEvent(this, event) {
+ * return true;
+ * }
+ * return super.dispatchHoverEvent(event);
+ * }
+ * </pre>
+ *
+ * @param event The hover event to dispatch to the virtual view hierarchy.
+ * @return Whether the hover event was handled.
+ */
+ public boolean dispatchHoverEvent(MotionEvent event) {
+ if (!mManager.isEnabled() || !mManager.isTouchExplorationEnabled()) {
+ return false;
+ }
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_MOVE:
+ case MotionEvent.ACTION_HOVER_ENTER:
+ final int virtualViewId = getVirtualViewAt(event.getX(), event.getY());
+ updateHoveredVirtualView(virtualViewId);
+ return (virtualViewId != INVALID_ID);
+ case MotionEvent.ACTION_HOVER_EXIT:
+ if (mFocusedVirtualViewId != INVALID_ID) {
+ updateHoveredVirtualView(INVALID_ID);
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Populates an event of the specified type with information about an item
+ * and attempts to send it up through the view hierarchy.
+ * <p>
+ * You should call this method after performing a user action that normally
+ * fires an accessibility event, such as clicking on an item.
+ *
+ * <pre>public void performItemClick(T item) {
+ * ...
+ * sendEventForVirtualViewId(item.id, AccessibilityEvent.TYPE_VIEW_CLICKED);
+ * }
+ * </pre>
+ *
+ * @param virtualViewId The virtual view id for which to send an event.
+ * @param eventType The type of event to send.
+ * @return true if the event was sent successfully.
+ */
+ public boolean sendEventForVirtualView(int virtualViewId, int eventType) {
+ if ((virtualViewId == INVALID_ID) || !mManager.isEnabled()) {
+ return false;
+ }
+
+ final ViewParent parent = mView.getParent();
+ if (parent == null) {
+ return false;
+ }
+
+ final AccessibilityEvent event = createEvent(virtualViewId, eventType);
+ return parent.requestSendAccessibilityEvent(mView, event);
+ }
+
+ /**
+ * Notifies the accessibility framework that the properties of the parent
+ * view have changed.
+ * <p>
+ * You <b>must</b> call this method after adding or removing items from the
+ * parent view.
+ */
+ public void invalidateRoot() {
+ invalidateVirtualView(View.NO_ID);
+ }
+
+ /**
+ * Notifies the accessibility framework that the properties of a particular
+ * item have changed.
+ * <p>
+ * You <b>must</b> call this method after changing any of the properties set
+ * in {@link #onPopulateNodeForVirtualView}.
+ *
+ * @param virtualViewId The virtual view id to invalidate.
+ */
+ public void invalidateVirtualView(int virtualViewId) {
+ sendEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ }
+
+ /**
+ * Returns the virtual view id for the currently focused item,
+ *
+ * @return A virtual view id, or {@link #INVALID_ID} if no item is
+ * currently focused.
+ */
+ public int getFocusedVirtualView() {
+ return mFocusedVirtualViewId;
+ }
+
+ /**
+ * Sets the currently hovered item, sending hover accessibility events as
+ * necessary to maintain the correct state.
+ *
+ * @param virtualViewId The virtual view id for the item currently being
+ * hovered, or {@link #INVALID_ID} if no item is hovered within
+ * the parent view.
+ */
+ private void updateHoveredVirtualView(int virtualViewId) {
+ if (mHoveredVirtualViewId == virtualViewId) {
+ return;
+ }
+
+ final int previousVirtualViewId = mHoveredVirtualViewId;
+ mHoveredVirtualViewId = virtualViewId;
+
+ // Stay consistent with framework behavior by sending ENTER/EXIT pairs
+ // in reverse order. This is accurate as of API 18.
+ sendEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
+ sendEventForVirtualView(previousVirtualViewId, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
+ }
+
+ /**
+ * Constructs and returns an {@link AccessibilityEvent} for the specified
+ * virtual view id, which includes the host view ({@link View#NO_ID}).
+ *
+ * @param virtualViewId The virtual view id for the item for which to
+ * construct an event.
+ * @param eventType The type of event to construct.
+ * @return An {@link AccessibilityEvent} populated with information about
+ * the specified item.
+ */
+ private AccessibilityEvent createEvent(int virtualViewId, int eventType) {
+ switch (virtualViewId) {
+ case View.NO_ID:
+ return createEventForHost(eventType);
+ default:
+ return createEventForChild(virtualViewId, eventType);
+ }
+ }
+
+ /**
+ * Constructs and returns an {@link AccessibilityEvent} for the host node.
+ *
+ * @param eventType The type of event to construct.
+ * @return An {@link AccessibilityEvent} populated with information about
+ * the specified item.
+ */
+ private AccessibilityEvent createEventForHost(int eventType) {
+ final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+ onInitializeAccessibilityEvent(mView, event);
+ return event;
+ }
+
+ /**
+ * Constructs and returns an {@link AccessibilityEvent} populated with
+ * information about the specified item.
+ *
+ * @param virtualViewId The virtual view id for the item for which to
+ * construct an event.
+ * @param eventType The type of event to construct.
+ * @return An {@link AccessibilityEvent} populated with information about
+ * the specified item.
+ */
+ private AccessibilityEvent createEventForChild(int virtualViewId, int eventType) {
+ final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
+ event.setEnabled(true);
+ event.setClassName(DEFAULT_CLASS_NAME);
+
+ // Allow the client to populate the event.
+ onPopulateEventForVirtualView(virtualViewId, event);
+
+ // Make sure the developer is following the rules.
+ if (event.getText().isEmpty() && (event.getContentDescription() == null)) {
+ throw new RuntimeException("Callbacks must add text or a content description in "
+ + "populateEventForVirtualViewId()");
+ }
+
+ // Don't allow the client to override these properties.
+ event.setPackageName(mView.getContext().getPackageName());
+ event.setSource(mView, virtualViewId);
+
+ return event;
+ }
+
+ /**
+ * Constructs and returns an {@link android.view.accessibility.AccessibilityNodeInfo} for the
+ * specified virtual view id, which includes the host view
+ * ({@link View#NO_ID}).
+ *
+ * @param virtualViewId The virtual view id for the item for which to
+ * construct a node.
+ * @return An {@link android.view.accessibility.AccessibilityNodeInfo} populated with information
+ * about the specified item.
+ */
+ private AccessibilityNodeInfo createNode(int virtualViewId) {
+ switch (virtualViewId) {
+ case View.NO_ID:
+ return createNodeForHost();
+ default:
+ return createNodeForChild(virtualViewId);
+ }
+ }
+
+ /**
+ * Constructs and returns an {@link AccessibilityNodeInfo} for the
+ * host view populated with its virtual descendants.
+ *
+ * @return An {@link AccessibilityNodeInfo} for the parent node.
+ */
+ private AccessibilityNodeInfo createNodeForHost() {
+ final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain(mView);
+ onInitializeAccessibilityNodeInfo(mView, node);
+
+ // Add the virtual descendants.
+ final LinkedList<Integer> virtualViewIds = new LinkedList<Integer>();
+ getVisibleVirtualViews(virtualViewIds);
+
+ for (Integer childVirtualViewId : virtualViewIds) {
+ node.addChild(mView, childVirtualViewId);
+ }
+
+ return node;
+ }
+
+ /**
+ * Constructs and returns an {@link AccessibilityNodeInfo} for the
+ * specified item. Automatically manages accessibility focus actions.
+ * <p>
+ * Allows the implementing class to specify most node properties, but
+ * overrides the following:
+ * <ul>
+ * <li>{@link AccessibilityNodeInfo#setPackageName}
+ * <li>{@link AccessibilityNodeInfo#setClassName}
+ * <li>{@link AccessibilityNodeInfo#setParent(View)}
+ * <li>{@link AccessibilityNodeInfo#setSource(View, int)}
+ * <li>{@link AccessibilityNodeInfo#setVisibleToUser}
+ * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)}
+ * </ul>
+ * <p>
+ * Uses the bounds of the parent view and the parent-relative bounding
+ * rectangle specified by
+ * {@link AccessibilityNodeInfo#getBoundsInParent} to automatically
+ * update the following properties:
+ * <ul>
+ * <li>{@link AccessibilityNodeInfo#setVisibleToUser}
+ * <li>{@link AccessibilityNodeInfo#setBoundsInParent}
+ * </ul>
+ *
+ * @param virtualViewId The virtual view id for item for which to construct
+ * a node.
+ * @return An {@link AccessibilityNodeInfo} for the specified item.
+ */
+ private AccessibilityNodeInfo createNodeForChild(int virtualViewId) {
+ final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain();
+
+ // Ensure the client has good defaults.
+ node.setEnabled(true);
+ node.setClassName(DEFAULT_CLASS_NAME);
+
+ // Allow the client to populate the node.
+ onPopulateNodeForVirtualView(virtualViewId, node);
+
+ // Make sure the developer is following the rules.
+ if ((node.getText() == null) && (node.getContentDescription() == null)) {
+ throw new RuntimeException("Callbacks must add text or a content description in "
+ + "populateNodeForVirtualViewId()");
+ }
+
+ node.getBoundsInParent(mTempParentRect);
+ if (mTempParentRect.isEmpty()) {
+ throw new RuntimeException("Callbacks must set parent bounds in "
+ + "populateNodeForVirtualViewId()");
+ }
+
+ final int actions = node.getActions();
+ if ((actions & AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) != 0) {
+ throw new RuntimeException("Callbacks must not add ACTION_ACCESSIBILITY_FOCUS in "
+ + "populateNodeForVirtualViewId()");
+ }
+ if ((actions & AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS) != 0) {
+ throw new RuntimeException("Callbacks must not add ACTION_CLEAR_ACCESSIBILITY_FOCUS in "
+ + "populateNodeForVirtualViewId()");
+ }
+
+ // Don't allow the client to override these properties.
+ node.setPackageName(mView.getContext().getPackageName());
+ node.setSource(mView, virtualViewId);
+ node.setParent(mView);
+
+ // Manage internal accessibility focus state.
+ if (mFocusedVirtualViewId == virtualViewId) {
+ node.setAccessibilityFocused(true);
+ node.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+ } else {
+ node.setAccessibilityFocused(false);
+ node.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
+ }
+
+ // Set the visibility based on the parent bound.
+ if (intersectVisibleToUser(mTempParentRect)) {
+ node.setVisibleToUser(true);
+ node.setBoundsInParent(mTempParentRect);
+ }
+
+ // Calculate screen-relative bound.
+ mView.getLocationOnScreen(mTempGlobalRect);
+ final int offsetX = mTempGlobalRect[0];
+ final int offsetY = mTempGlobalRect[1];
+ mTempScreenRect.set(mTempParentRect);
+ mTempScreenRect.offset(offsetX, offsetY);
+ node.setBoundsInScreen(mTempScreenRect);
+
+ return node;
+ }
+
+ private boolean performAction(int virtualViewId, int action, Bundle arguments) {
+ switch (virtualViewId) {
+ case View.NO_ID:
+ return performActionForHost(action, arguments);
+ default:
+ return performActionForChild(virtualViewId, action, arguments);
+ }
+ }
+
+ private boolean performActionForHost(int action, Bundle arguments) {
+ return performAccessibilityAction(mView, action, arguments);
+ }
+
+ private boolean performActionForChild(int virtualViewId, int action, Bundle arguments) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
+ case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
+ return manageFocusForChild(virtualViewId, action, arguments);
+ default:
+ return onPerformActionForVirtualView(virtualViewId, action, arguments);
+ }
+ }
+
+ private boolean manageFocusForChild(int virtualViewId, int action, Bundle arguments) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
+ return requestAccessibilityFocus(virtualViewId);
+ case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
+ return clearAccessibilityFocus(virtualViewId);
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Computes whether the specified {@link Rect} intersects with the visible
+ * portion of its parent {@link View}. Modifies {@code localRect} to contain
+ * only the visible portion.
+ *
+ * @param localRect A rectangle in local (parent) coordinates.
+ * @return Whether the specified {@link Rect} is visible on the screen.
+ */
+ private boolean intersectVisibleToUser(Rect localRect) {
+ // Missing or empty bounds mean this view is not visible.
+ if ((localRect == null) || localRect.isEmpty()) {
+ return false;
+ }
+
+ // Attached to invisible window means this view is not visible.
+ if (mView.getWindowVisibility() != View.VISIBLE) {
+ return false;
+ }
+
+ // An invisible predecessor means that this view is not visible.
+ ViewParent viewParent = mView.getParent();
+ while (viewParent instanceof View) {
+ final View view = (View) viewParent;
+ if ((view.getAlpha() <= 0) || (view.getVisibility() != View.VISIBLE)) {
+ return false;
+ }
+ viewParent = view.getParent();
+ }
+
+ // A null parent implies the view is not visible.
+ if (viewParent == null) {
+ return false;
+ }
+
+ // If no portion of the parent is visible, this view is not visible.
+ if (!mView.getLocalVisibleRect(mTempVisibleRect)) {
+ return false;
+ }
+
+ // Check if the view intersects the visible portion of the parent.
+ return localRect.intersect(mTempVisibleRect);
+ }
+
+ /**
+ * Returns whether this virtual view is accessibility focused.
+ *
+ * @return True if the view is accessibility focused.
+ */
+ private boolean isAccessibilityFocused(int virtualViewId) {
+ return (mFocusedVirtualViewId == virtualViewId);
+ }
+
+ /**
+ * Attempts to give accessibility focus to a virtual view.
+ * <p>
+ * A virtual view will not actually take focus if
+ * {@link AccessibilityManager#isEnabled()} returns false,
+ * {@link AccessibilityManager#isTouchExplorationEnabled()} returns false,
+ * or the view already has accessibility focus.
+ *
+ * @param virtualViewId The id of the virtual view on which to place
+ * accessibility focus.
+ * @return Whether this virtual view actually took accessibility focus.
+ */
+ private boolean requestAccessibilityFocus(int virtualViewId) {
+ final AccessibilityManager accessibilityManager =
+ (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+
+ if (!mManager.isEnabled()
+ || !accessibilityManager.isTouchExplorationEnabled()) {
+ return false;
+ }
+ // TODO: Check virtual view visibility.
+ if (!isAccessibilityFocused(virtualViewId)) {
+ mFocusedVirtualViewId = virtualViewId;
+ // TODO: Only invalidate virtual view bounds.
+ mView.invalidate();
+ sendEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to clear accessibility focus from a virtual view.
+ *
+ * @param virtualViewId The id of the virtual view from which to clear
+ * accessibility focus.
+ * @return Whether this virtual view actually cleared accessibility focus.
+ */
+ private boolean clearAccessibilityFocus(int virtualViewId) {
+ if (isAccessibilityFocused(virtualViewId)) {
+ mFocusedVirtualViewId = INVALID_ID;
+ mView.invalidate();
+ sendEventForVirtualView(virtualViewId,
+ AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Provides a mapping between view-relative coordinates and logical
+ * items.
+ *
+ * @param x The view-relative x coordinate
+ * @param y The view-relative y coordinate
+ * @return virtual view identifier for the logical item under
+ * coordinates (x,y)
+ */
+ protected abstract int getVirtualViewAt(float x, float y);
+
+ /**
+ * Populates a list with the view's visible items. The ordering of items
+ * within {@code virtualViewIds} specifies order of accessibility focus
+ * traversal.
+ *
+ * @param virtualViewIds The list to populate with visible items
+ */
+ protected abstract void getVisibleVirtualViews(List<Integer> virtualViewIds);
+
+ /**
+ * Populates an {@link AccessibilityEvent} with information about the
+ * specified item.
+ * <p>
+ * Implementations <b>must</b> populate the following required fields:
+ * <ul>
+ * <li>event text, see {@link AccessibilityEvent#getText} or
+ * {@link AccessibilityEvent#setContentDescription}
+ * </ul>
+ * <p>
+ * The helper class automatically populates the following fields with
+ * default values, but implementations may optionally override them:
+ * <ul>
+ * <li>item class name, set to android.view.View, see
+ * {@link AccessibilityEvent#setClassName}
+ * </ul>
+ * <p>
+ * The following required fields are automatically populated by the
+ * helper class and may not be overridden:
+ * <ul>
+ * <li>package name, set to the package of the host view's
+ * {@link Context}, see {@link AccessibilityEvent#setPackageName}
+ * <li>event source, set to the host view and virtual view identifier,
+ * see {@link AccessibilityRecord#setSource(View, int)}
+ * </ul>
+ *
+ * @param virtualViewId The virtual view id for the item for which to
+ * populate the event
+ * @param event The event to populate
+ */
+ protected abstract void onPopulateEventForVirtualView(
+ int virtualViewId, AccessibilityEvent event);
+
+ /**
+ * Populates an {@link AccessibilityNodeInfo} with information
+ * about the specified item.
+ * <p>
+ * Implementations <b>must</b> populate the following required fields:
+ * <ul>
+ * <li>event text, see {@link AccessibilityNodeInfo#setText} or
+ * {@link AccessibilityNodeInfo#setContentDescription}
+ * <li>bounds in parent coordinates, see
+ * {@link AccessibilityNodeInfo#setBoundsInParent}
+ * </ul>
+ * <p>
+ * The helper class automatically populates the following fields with
+ * default values, but implementations may optionally override them:
+ * <ul>
+ * <li>enabled state, set to true, see
+ * {@link AccessibilityNodeInfo#setEnabled}
+ * <li>item class name, identical to the class name set by
+ * {@link #onPopulateEventForVirtualView}, see
+ * {@link AccessibilityNodeInfo#setClassName}
+ * </ul>
+ * <p>
+ * The following required fields are automatically populated by the
+ * helper class and may not be overridden:
+ * <ul>
+ * <li>package name, identical to the package name set by
+ * {@link #onPopulateEventForVirtualView}, see
+ * {@link AccessibilityNodeInfo#setPackageName}
+ * <li>node source, identical to the event source set in
+ * {@link #onPopulateEventForVirtualView}, see
+ * {@link AccessibilityNodeInfo#setSource(View, int)}
+ * <li>parent view, set to the host view, see
+ * {@link AccessibilityNodeInfo#setParent(View)}
+ * <li>visibility, computed based on parent-relative bounds, see
+ * {@link AccessibilityNodeInfo#setVisibleToUser}
+ * <li>accessibility focus, computed based on internal helper state, see
+ * {@link AccessibilityNodeInfo#setAccessibilityFocused}
+ * <li>bounds in screen coordinates, computed based on host view bounds,
+ * see {@link AccessibilityNodeInfo#setBoundsInScreen}
+ * </ul>
+ * <p>
+ * Additionally, the helper class automatically handles accessibility
+ * focus management by adding the appropriate
+ * {@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS} or
+ * {@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
+ * action. Implementations must <b>never</b> manually add these actions.
+ * <p>
+ * The helper class also automatically modifies parent- and
+ * screen-relative bounds to reflect the portion of the item visible
+ * within its parent.
+ *
+ * @param virtualViewId The virtual view identifier of the item for
+ * which to populate the node
+ * @param node The node to populate
+ */
+ protected abstract void onPopulateNodeForVirtualView(
+ int virtualViewId, AccessibilityNodeInfo node);
+
+ /**
+ * Performs the specified accessibility action on the item associated
+ * with the virtual view identifier. See
+ * {@link AccessibilityNodeInfo#performAction(int, Bundle)} for
+ * more information.
+ * <p>
+ * Implementations <b>must</b> handle any actions added manually in
+ * {@link #onPopulateNodeForVirtualView}.
+ * <p>
+ * The helper class automatically handles focus management resulting
+ * from {@link AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS}
+ * and
+ * {@link AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
+ * actions.
+ *
+ * @param virtualViewId The virtual view identifier of the item on which
+ * to perform the action
+ * @param action The accessibility action to perform
+ * @param arguments (Optional) A bundle with additional arguments, or
+ * null
+ * @return true if the action was performed
+ */
+ protected abstract boolean onPerformActionForVirtualView(
+ int virtualViewId, int action, Bundle arguments);
+
+ /**
+ * Exposes a virtual view hierarchy to the accessibility framework. Only
+ * used in API 16+.
+ */
+ private class ExploreByTouchNodeProvider extends AccessibilityNodeProvider {
+ @Override
+ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
+ return ExploreByTouchHelper.this.createNode(virtualViewId);
+ }
+
+ @Override
+ public boolean performAction(int virtualViewId, int action, Bundle arguments) {
+ return ExploreByTouchHelper.this.performAction(virtualViewId, action, arguments);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f40b84c..cc481e1 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -57,6 +57,7 @@
public class LockPatternUtils {
private static final String TAG = "LockPatternUtils";
+ private static final boolean DEBUG = false;
/**
* The maximum number of incorrect attempts before the user is prevented
@@ -1046,8 +1047,11 @@
return false;
}
-
- return true;
+ // TODO: If we decide not to proceed with Face Unlock as a trustlet, this must be changed
+ // back to returning true. If we become certain that Face Unlock will be a trustlet, this
+ // entire function and a lot of other code can be removed.
+ if (DEBUG) Log.d(TAG, "Forcing isBiometricWeakInstalled() to return false to disable it");
+ return false;
}
/**
diff --git a/core/java/com/android/server/net/NetlinkTracker.java b/core/java/com/android/server/net/NetlinkTracker.java
index ff905bb..0dde465 100644
--- a/core/java/com/android/server/net/NetlinkTracker.java
+++ b/core/java/com/android/server/net/NetlinkTracker.java
@@ -79,7 +79,7 @@
private final LinkProperties mLinkProperties;
private DnsServerRepository mDnsServerRepository;
- private static final boolean DBG = true;
+ private static final boolean DBG = false;
public NetlinkTracker(String iface, Callback callback) {
TAG = "NetlinkTracker/" + iface;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 0e22174..f65aab5 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -90,12 +90,12 @@
android_util_Process.cpp \
android_util_StringBlock.cpp \
android_util_XmlBlock.cpp \
+ android_graphics_Canvas.cpp \
android_graphics_Picture.cpp \
android/graphics/AutoDecodeCancel.cpp \
android/graphics/Bitmap.cpp \
android/graphics/BitmapFactory.cpp \
android/graphics/Camera.cpp \
- android/graphics/Canvas.cpp \
android/graphics/CanvasProperty.cpp \
android/graphics/ColorFilter.cpp \
android/graphics/DrawFilter.cpp \
@@ -122,6 +122,7 @@
android/graphics/Rasterizer.cpp \
android/graphics/Region.cpp \
android/graphics/Shader.cpp \
+ android/graphics/SkiaCanvas.cpp \
android/graphics/SurfaceTexture.cpp \
android/graphics/Typeface.cpp \
android/graphics/TypefaceImpl.cpp \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index b8fcff6..a890eb4 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -39,14 +39,12 @@
jfieldID gOptions_mimeFieldID;
jfieldID gOptions_mCancelID;
jfieldID gOptions_bitmapFieldID;
-jfieldID gBitmap_nativeBitmapFieldID;
-jfieldID gBitmap_layoutBoundsFieldID;
-#if 0
- #define TRACE_BITMAP(code) code
-#else
- #define TRACE_BITMAP(code)
-#endif
+jfieldID gBitmap_nativeBitmapFieldID;
+jfieldID gBitmap_ninePatchInsetsFieldID;
+
+jclass gInsetStruct_class;
+jmethodID gInsetStruct_constructorMethodID;
using namespace android;
@@ -195,8 +193,7 @@
const unsigned int mSize;
};
-static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding,
- jobject options) {
+static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) {
int sampleSize = 1;
@@ -331,12 +328,12 @@
}
jbyteArray ninePatchChunk = NULL;
- if (peeker.fPatch != NULL) {
+ if (peeker.mPatch != NULL) {
if (willScale) {
- scaleNinePatchChunk(peeker.fPatch, scale);
+ scaleNinePatchChunk(peeker.mPatch, scale);
}
- size_t ninePatchArraySize = peeker.fPatch->serializedSize();
+ size_t ninePatchArraySize = peeker.mPatch->serializedSize();
ninePatchChunk = env->NewByteArray(ninePatchArraySize);
if (ninePatchChunk == NULL) {
return nullObjectReturn("ninePatchChunk == null");
@@ -347,28 +344,18 @@
return nullObjectReturn("primitive array == null");
}
- memcpy(array, peeker.fPatch, peeker.fPatchSize);
+ memcpy(array, peeker.mPatch, peeker.mPatchSize);
env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0);
}
- jintArray layoutBounds = NULL;
- if (peeker.fLayoutBounds != NULL) {
- layoutBounds = env->NewIntArray(4);
- if (layoutBounds == NULL) {
- return nullObjectReturn("layoutBounds == null");
- }
-
- jint scaledBounds[4];
- if (willScale) {
- for (int i=0; i<4; i++) {
- scaledBounds[i] = (jint)((((jint*)peeker.fLayoutBounds)[i]*scale) + .5f);
- }
- } else {
- memcpy(scaledBounds, (jint*)peeker.fLayoutBounds, sizeof(scaledBounds));
- }
- env->SetIntArrayRegion(layoutBounds, 0, 4, scaledBounds);
+ jobject ninePatchInsets = NULL;
+ if (peeker.mHasInsets) {
+ ninePatchInsets = env->NewObject(gInsetStruct_class, gInsetStruct_constructorMethodID,
+ peeker.mOpticalInsets[0], peeker.mOpticalInsets[1], peeker.mOpticalInsets[2], peeker.mOpticalInsets[3],
+ peeker.mOutlineInsets[0], peeker.mOutlineInsets[1], peeker.mOutlineInsets[2], peeker.mOutlineInsets[3],
+ peeker.mOutlineRadius, peeker.mOutlineFilled, scale);
if (javaBitmap != NULL) {
- env->SetObjectField(javaBitmap, gBitmap_layoutBoundsFieldID, layoutBounds);
+ env->SetObjectField(javaBitmap, gBitmap_ninePatchInsetsFieldID, ninePatchInsets);
}
}
@@ -409,10 +396,10 @@
}
if (padding) {
- if (peeker.fPatch != NULL) {
+ if (peeker.mPatch != NULL) {
GraphicsJNI::set_jrect(env, padding,
- peeker.fPatch->paddingLeft, peeker.fPatch->paddingTop,
- peeker.fPatch->paddingRight, peeker.fPatch->paddingBottom);
+ peeker.mPatch->paddingLeft, peeker.mPatch->paddingTop,
+ peeker.mPatch->paddingRight, peeker.mPatch->paddingBottom);
} else {
GraphicsJNI::set_jrect(env, padding, -1, -1, -1, -1);
}
@@ -446,7 +433,7 @@
// now create the java bitmap
return GraphicsJNI::createBitmap(env, outputBitmap, javaAllocator.getStorageObj(),
- bitmapCreateFlags, ninePatchChunk, layoutBounds, -1);
+ bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1);
}
// Need to buffer enough input to be able to rewind as much as might be read by a decoder
@@ -576,7 +563,7 @@
jclass options_class = env->FindClass("android/graphics/BitmapFactory$Options");
SkASSERT(options_class);
gOptions_bitmapFieldID = getFieldIDCheck(env, options_class, "inBitmap",
- "Landroid/graphics/Bitmap;");
+ "Landroid/graphics/Bitmap;");
gOptions_justBoundsFieldID = getFieldIDCheck(env, options_class, "inJustDecodeBounds", "Z");
gOptions_sampleSizeFieldID = getFieldIDCheck(env, options_class, "inSampleSize", "I");
gOptions_configFieldID = getFieldIDCheck(env, options_class, "inPreferredConfig",
@@ -598,7 +585,12 @@
jclass bitmap_class = env->FindClass("android/graphics/Bitmap");
SkASSERT(bitmap_class);
gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, bitmap_class, "mNativeBitmap", "J");
- gBitmap_layoutBoundsFieldID = getFieldIDCheck(env, bitmap_class, "mOpticalInsets", "[I");
+ gBitmap_ninePatchInsetsFieldID = getFieldIDCheck(env, bitmap_class, "mNinePatchInsets",
+ "Landroid/graphics/NinePatch$InsetStruct;");
+
+ gInsetStruct_class = (jclass) env->NewGlobalRef(env->FindClass("android/graphics/NinePatch$InsetStruct"));
+ gInsetStruct_constructorMethodID = env->GetMethodID(gInsetStruct_class, "<init>", "(IIIIIIIIFZF)V");
+
int ret = AndroidRuntime::registerNativeMethods(env,
"android/graphics/BitmapFactory$Options",
gOptionsMethods,
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index d17f46c..9f832b0 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -3,6 +3,7 @@
#include "SkCamera.h"
+#include "Canvas.h"
#include "GraphicsJNI.h"
static jfieldID gNativeInstanceFieldID;
@@ -95,10 +96,10 @@
}
static void Camera_applyToCanvas(JNIEnv* env, jobject obj, jlong canvasHandle) {
- SkCanvas* native_canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
+ SkCanvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
- v->applyToCanvas((SkCanvas*)native_canvas);
+ v->applyToCanvas(canvas);
}
static jfloat Camera_dotWithNormal(JNIEnv* env, jobject obj,
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
deleted file mode 100644
index 6254f3d..0000000
--- a/core/jni/android/graphics/Canvas.cpp
+++ /dev/null
@@ -1,1330 +0,0 @@
-/*
- * Copyright (C) 2006-2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "jni.h"
-#include "GraphicsJNI.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include "SkCanvas.h"
-#include "SkClipStack.h"
-#include "SkDevice.h"
-#include "SkDeque.h"
-#include "SkDrawFilter.h"
-#include "SkGraphics.h"
-#include <SkImageInfo.h>
-#include "SkPorterDuff.h"
-#include "SkShader.h"
-#include "SkTArray.h"
-#include "SkTemplates.h"
-
-#include <minikin/Layout.h>
-#include "MinikinSkia.h"
-#include "MinikinUtils.h"
-
-#include "TypefaceImpl.h"
-
-#include "unicode/ubidi.h"
-#include "unicode/ushape.h"
-
-#include <utils/Log.h>
-
-namespace android {
-
-class ClipCopier : public SkCanvas::ClipVisitor {
-public:
- ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
-
- virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
- m_dstCanvas->clipRect(rect, op, antialias);
- }
- virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
- m_dstCanvas->clipRRect(rrect, op, antialias);
- }
- virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
- m_dstCanvas->clipPath(path, op, antialias);
- }
-
-private:
- SkCanvas* m_dstCanvas;
-};
-
-// Holds an SkCanvas reference plus additional native data.
-class NativeCanvasWrapper {
-private:
- struct SaveRec {
- int saveCount;
- SkCanvas::SaveFlags saveFlags;
- };
-
-public:
- NativeCanvasWrapper(SkCanvas* canvas)
- : mCanvas(canvas)
- , mSaveStack(NULL) {
- SkASSERT(canvas);
- }
-
- ~NativeCanvasWrapper() {
- delete mSaveStack;
- }
-
- SkCanvas* getCanvas() const {
- return mCanvas.get();
- }
-
- void setCanvas(SkCanvas* canvas) {
- SkASSERT(canvas);
- mCanvas.reset(canvas);
-
- delete mSaveStack;
- mSaveStack = NULL;
- }
-
- int save(SkCanvas::SaveFlags flags) {
- int count = mCanvas->save();
- recordPartialSave(flags);
- return count;
- }
-
- int saveLayer(const SkRect* bounds, const SkPaint* paint,
- SkCanvas::SaveFlags flags) {
- int count = mCanvas->saveLayer(bounds, paint,
- static_cast<SkCanvas::SaveFlags>(flags | SkCanvas::kMatrixClip_SaveFlag));
- recordPartialSave(flags);
- return count;
- }
-
- int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
- SkCanvas::SaveFlags flags) {
- int count = mCanvas->saveLayerAlpha(bounds, alpha,
- static_cast<SkCanvas::SaveFlags>(flags | SkCanvas::kMatrixClip_SaveFlag));
- recordPartialSave(flags);
- return count;
- }
-
- void restore() {
- const SaveRec* rec = (NULL == mSaveStack)
- ? NULL
- : static_cast<SaveRec*>(mSaveStack->back());
- int currentSaveCount = mCanvas->getSaveCount() - 1;
- SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount);
-
- if (NULL == rec || rec->saveCount != currentSaveCount) {
- // Fast path - no record for this frame.
- mCanvas->restore();
- return;
- }
-
- bool preserveMatrix = !(rec->saveFlags & SkCanvas::kMatrix_SaveFlag);
- bool preserveClip = !(rec->saveFlags & SkCanvas::kClip_SaveFlag);
-
- SkMatrix savedMatrix;
- if (preserveMatrix) {
- savedMatrix = mCanvas->getTotalMatrix();
- }
-
- SkTArray<SkClipStack::Element> savedClips;
- if (preserveClip) {
- saveClipsForFrame(savedClips, currentSaveCount);
- }
-
- mCanvas->restore();
-
- if (preserveMatrix) {
- mCanvas->setMatrix(savedMatrix);
- }
-
- if (preserveClip && !savedClips.empty()) {
- applyClips(savedClips);
- }
-
- mSaveStack->pop_back();
- }
-
-private:
- void recordPartialSave(SkCanvas::SaveFlags flags) {
- // A partial save is a save operation which doesn't capture the full canvas state.
- // (either kMatrix_SaveFlags or kClip_SaveFlag is missing).
-
- // Mask-out non canvas state bits.
- flags = static_cast<SkCanvas::SaveFlags>(flags & SkCanvas::kMatrixClip_SaveFlag);
-
- if (SkCanvas::kMatrixClip_SaveFlag == flags) {
- // not a partial save.
- return;
- }
-
- if (NULL == mSaveStack) {
- mSaveStack = new SkDeque(sizeof(struct SaveRec), 8);
- }
-
- SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
- // Store the save counter in the SkClipStack domain.
- // (0-based, equal to the number of save ops on the stack).
- rec->saveCount = mCanvas->getSaveCount() - 1;
- rec->saveFlags = flags;
- }
-
- void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips,
- int frameSaveCount) {
- SkClipStack::Iter clipIterator(*mCanvas->getClipStack(),
- SkClipStack::Iter::kTop_IterStart);
- while (const SkClipStack::Element* elem = clipIterator.next()) {
- if (elem->getSaveCount() < frameSaveCount) {
- // done with the current frame.
- break;
- }
- SkASSERT(elem->getSaveCount() == frameSaveCount);
- clips.push_back(*elem);
- }
- }
-
- void applyClips(const SkTArray<SkClipStack::Element>& clips) {
- ClipCopier clipCopier(mCanvas);
-
- // The clip stack stores clips in device space.
- SkMatrix origMatrix = mCanvas->getTotalMatrix();
- mCanvas->resetMatrix();
-
- // We pushed the clips in reverse order.
- for (int i = clips.count() - 1; i >= 0; --i) {
- clips[i].replay(&clipCopier);
- }
-
- mCanvas->setMatrix(origMatrix);
- }
-
- SkAutoTUnref<SkCanvas> mCanvas;
- SkDeque* mSaveStack; // lazily allocated, tracks partial saves.
-};
-
-// Returns true if the SkCanvas's clip is non-empty.
-static jboolean hasNonEmptyClip(const SkCanvas& canvas) {
- bool emptyClip = canvas.isClipEmpty();
- return emptyClip ? JNI_FALSE : JNI_TRUE;
-}
-
-class SkCanvasGlue {
-public:
- // Get the native wrapper for a given handle.
- static inline NativeCanvasWrapper* getNativeWrapper(jlong nativeHandle) {
- SkASSERT(nativeHandle);
- return reinterpret_cast<NativeCanvasWrapper*>(nativeHandle);
- }
-
- // Get the SkCanvas for a given native handle.
- static inline SkCanvas* getNativeCanvas(jlong nativeHandle) {
- NativeCanvasWrapper* wrapper = getNativeWrapper(nativeHandle);
- SkCanvas* canvas = wrapper->getCanvas();
- SkASSERT(canvas);
-
- return canvas;
- }
-
- // Construct an SkCanvas from the bitmap.
- static SkCanvas* createCanvas(SkBitmap* bitmap) {
- if (bitmap) {
- return SkNEW_ARGS(SkCanvas, (*bitmap));
- }
-
- // Create an empty bitmap device to prevent callers from crashing
- // if they attempt to draw into this canvas.
- SkBitmap emptyBitmap;
- return new SkCanvas(emptyBitmap);
- }
-
- // Copy the canvas matrix & clip state.
- static void copyCanvasState(SkCanvas* srcCanvas, SkCanvas* dstCanvas) {
- if (srcCanvas && dstCanvas) {
- dstCanvas->setMatrix(srcCanvas->getTotalMatrix());
- if (NULL != srcCanvas->getDevice() && NULL != dstCanvas->getDevice()) {
- ClipCopier copier(dstCanvas);
- srcCanvas->replayClips(&copier);
- }
- }
- }
-
- // Native JNI handlers
- static void finalizer(JNIEnv* env, jobject clazz, jlong nativeHandle) {
- NativeCanvasWrapper* wrapper = reinterpret_cast<NativeCanvasWrapper*>(nativeHandle);
- delete wrapper;
- }
-
- // Native wrapper constructor used by Canvas(Bitmap)
- static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
- // No check - 0 is a valid bitmapHandle.
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkCanvas* canvas = createCanvas(bitmap);
-
- return reinterpret_cast<jlong>(new NativeCanvasWrapper(canvas));
- }
-
- // Native wrapper constructor used by Canvas(native_canvas)
- static jlong initCanvas(JNIEnv* env, jobject, jlong canvasHandle) {
- SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
- return reinterpret_cast<jlong>(new NativeCanvasWrapper(canvas));
- }
-
- // Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
- // optionally copying canvas matrix & clip state.
- static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
- jboolean copyState) {
- NativeCanvasWrapper* wrapper = reinterpret_cast<NativeCanvasWrapper*>(canvasHandle);
- SkCanvas* newCanvas = createCanvas(reinterpret_cast<SkBitmap*>(bitmapHandle));
- NPE_CHECK_RETURN_VOID(env, newCanvas);
-
- if (copyState == JNI_TRUE) {
- copyCanvasState(wrapper->getCanvas(), newCanvas);
- }
-
- // setCanvas() unrefs the old canvas.
- wrapper->setCanvas(newCanvas);
- }
-
- static void freeCaches(JNIEnv* env, jobject) {
- SkGraphics::PurgeFontCache();
- }
-
- static void freeTextLayoutCaches(JNIEnv* env, jobject) {
- Layout::purgeCaches();
- }
-
- static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- bool result = canvas->getDevice()->accessBitmap(false).isOpaque();
- return result ? JNI_TRUE : JNI_FALSE;
- }
-
- static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- int width = canvas->getDevice()->accessBitmap(false).width();
- return static_cast<jint>(width);
- }
-
- static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- int height = canvas->getDevice()->accessBitmap(false).height();
- return static_cast<jint>(height);
- }
-
- static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
- NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
- SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
- return static_cast<jint>(wrapper->save(flags));
- }
-
- static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat l, jfloat t, jfloat r, jfloat b,
- jlong paintHandle, jint flagsHandle) {
- NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
- SkRect bounds;
- bounds.set(l, t, r, b);
- return static_cast<jint>(wrapper->saveLayer(&bounds, paint, flags));
- }
-
- static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat l, jfloat t, jfloat r, jfloat b,
- jint alpha, jint flagsHandle) {
- NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
- SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
- SkRect bounds;
- bounds.set(l, t, r, b);
- return static_cast<jint>(wrapper->saveLayerAlpha(&bounds, alpha, flags));
- }
-
- static void restore(JNIEnv* env, jobject, jlong canvasHandle) {
- NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
- if (wrapper->getCanvas()->getSaveCount() <= 1) { // cannot restore anymore
- doThrowISE(env, "Underflow in restore");
- return;
- }
- wrapper->restore();
- }
-
- static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
- return static_cast<jint>(getNativeCanvas(canvasHandle)->getSaveCount());
- }
-
- static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle,
- jint restoreCount) {
- NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
- if (restoreCount < 1) {
- doThrowIAE(env, "Underflow in restoreToCount");
- return;
- }
-
- while (wrapper->getCanvas()->getSaveCount() > restoreCount) {
- wrapper->restore();
- }
- }
-
- static void translate(JNIEnv*, jobject, jlong canvasHandle,
- jfloat dx, jfloat dy) {
- getNativeCanvas(canvasHandle)->translate(dx, dy);
- }
-
- static void scale__FF(JNIEnv*, jobject, jlong canvasHandle,
- jfloat sx, jfloat sy) {
- getNativeCanvas(canvasHandle)->scale(sx, sy);
- }
-
- static void rotate__F(JNIEnv*, jobject, jlong canvasHandle,
- jfloat degrees) {
- getNativeCanvas(canvasHandle)->rotate(degrees);
- }
-
- static void skew__FF(JNIEnv*, jobject, jlong canvasHandle,
- jfloat sx, jfloat sy) {
- getNativeCanvas(canvasHandle)->skew(sx, sy);
- }
-
- static void concat(JNIEnv* env, jobject, jlong canvasHandle,
- jlong matrixHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- canvas->concat(*matrix);
- }
-
- static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle,
- jlong matrixHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- if (NULL == matrix) {
- canvas->resetMatrix();
- } else {
- canvas->setMatrix(*matrix);
- }
- }
-
- static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle,
- jfloat left, jfloat top, jfloat right,
- jfloat bottom, jint op) {
- SkRect r;
- r.set(left, top, right, bottom);
- SkCanvas* c = getNativeCanvas(canvasHandle);
- c->clipRect(r, static_cast<SkRegion::Op>(op));
- return hasNonEmptyClip(*c);
- }
-
- static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
- jlong pathHandle, jint op) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
- static_cast<SkRegion::Op>(op));
- return hasNonEmptyClip(*canvas);
- }
-
- static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle,
- jlong deviceRgnHandle, jint op) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
- SkPath rgnPath;
- if (deviceRgn->getBoundaryPath(&rgnPath)) {
- // The region is specified in device space.
- SkMatrix savedMatrix = canvas->getTotalMatrix();
- canvas->resetMatrix();
- canvas->clipPath(rgnPath, static_cast<SkRegion::Op>(op));
- canvas->setMatrix(savedMatrix);
- } else {
- canvas->clipRect(SkRect::MakeEmpty(), static_cast<SkRegion::Op>(op));
- }
- return hasNonEmptyClip(*canvas);
- }
-
- static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
- jlong filterHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
- }
-
- static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
- jlong pathHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- bool result = canvas->quickReject(*reinterpret_cast<SkPath*>(pathHandle));
- return result ? JNI_TRUE : JNI_FALSE;
- }
-
- static jboolean quickReject__FFFF(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat left, jfloat top, jfloat right,
- jfloat bottom) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkRect r;
- r.set(left, top, right, bottom);
- bool result = canvas->quickReject(r);
- return result ? JNI_TRUE : JNI_FALSE;
- }
-
- static void drawRGB(JNIEnv* env, jobject, jlong canvasHandle,
- jint r, jint g, jint b) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- canvas->drawARGB(0xFF, r, g, b);
- }
-
- static void drawARGB(JNIEnv* env, jobject, jlong canvasHandle,
- jint a, jint r, jint g, jint b) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- canvas->drawARGB(a, r, g, b);
- }
-
- static void drawColor__I(JNIEnv* env, jobject, jlong canvasHandle,
- jint color) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- canvas->drawColor(color);
- }
-
- static void drawColor__II(JNIEnv* env, jobject, jlong canvasHandle,
- jint color, jint modeHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
- canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
- }
-
- static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle,
- jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- canvas->drawPaint(*paint);
- }
-
- static void doPoints(JNIEnv* env, jlong canvasHandle,
- jfloatArray jptsArray, jint offset, jint count,
- jlong paintHandle, jint modeHandle) {
- NPE_CHECK_RETURN_VOID(env, jptsArray);
- SkCanvas::PointMode mode = static_cast<SkCanvas::PointMode>(modeHandle);
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-
- AutoJavaFloatArray autoPts(env, jptsArray);
- float* floats = autoPts.ptr();
- const int length = autoPts.length();
-
- if ((offset | count) < 0 || offset + count > length) {
- doThrowAIOOBE(env);
- return;
- }
-
- // now convert the floats into SkPoints
- count >>= 1; // now it is the number of points
- SkAutoSTMalloc<32, SkPoint> storage(count);
- SkPoint* pts = storage.get();
- const float* src = floats + offset;
- for (int i = 0; i < count; i++) {
- pts[i].set(src[0], src[1]);
- src += 2;
- }
- canvas->drawPoints(mode, count, pts, *paint);
- }
-
- static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle,
- jfloatArray jptsArray, jint offset,
- jint count, jlong paintHandle) {
- doPoints(env, canvasHandle, jptsArray, offset, count, paintHandle,
- SkCanvas::kPoints_PointMode);
- }
-
- static void drawLines(JNIEnv* env, jobject, jlong canvasHandle,
- jfloatArray jptsArray, jint offset, jint count,
- jlong paintHandle) {
- doPoints(env, canvasHandle, jptsArray, offset, count, paintHandle,
- SkCanvas::kLines_PointMode);
- }
-
- static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
- jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- canvas->drawPoint(x, y, *paint);
- }
-
- static void drawLine__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat startX, jfloat startY, jfloat stopX,
- jfloat stopY, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- canvas->drawLine(startX, startY, stopX, stopY, *paint);
- }
-
- static void drawRect__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat left, jfloat top, jfloat right,
- jfloat bottom, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- canvas->drawRectCoords(left, top, right, bottom, *paint);
- }
-
- static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
- jfloat right, jfloat bottom, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
- canvas->drawOval(oval, *paint);
- }
-
- static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx,
- jfloat cy, jfloat radius, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- canvas->drawCircle(cx, cy, radius, *paint);
- }
-
- static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
- jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, jboolean useCenter,
- jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
- canvas->drawArc(oval, startAngle, sweepAngle, useCenter, *paint);
- }
-
- static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat rx, jfloat ry,
- jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
- canvas->drawRoundRect(rect, rx, ry, *paint);
- }
-
- static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
- jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- canvas->drawPath(*path, *paint);
- }
-
- static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
- jlong canvasHandle, jlong bitmapHandle,
- jfloat left, jfloat top,
- jlong paintHandle, jint canvasDensity,
- jint screenDensity, jint bitmapDensity) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-
- if (canvasDensity == bitmapDensity || canvasDensity == 0
- || bitmapDensity == 0) {
- if (screenDensity != 0 && screenDensity != bitmapDensity) {
- SkPaint filteredPaint;
- if (paint) {
- filteredPaint = *paint;
- }
- filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
- canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
- } else {
- canvas->drawBitmap(*bitmap, left, top, paint);
- }
- } else {
- canvas->save();
- SkScalar scale = canvasDensity / (float)bitmapDensity;
- canvas->translate(left, top);
- canvas->scale(scale, scale);
-
- SkPaint filteredPaint;
- if (paint) {
- filteredPaint = *paint;
- }
- filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
-
- canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
-
- canvas->restore();
- }
- }
-
- static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
- jobject srcIRect, const SkRect& dst, SkPaint* paint,
- jint screenDensity, jint bitmapDensity) {
- SkIRect src, *srcPtr = NULL;
-
- if (NULL != srcIRect) {
- GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
- srcPtr = &src;
- }
-
- if (screenDensity != 0 && screenDensity != bitmapDensity) {
- SkPaint filteredPaint;
- if (paint) {
- filteredPaint = *paint;
- }
- filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
- canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
- } else {
- canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
- }
- }
-
- static void drawBitmapRF(JNIEnv* env, jobject, jlong canvasHandle,
- jlong bitmapHandle, jobject srcIRect,
- jobject dstRectF, jlong paintHandle,
- jint screenDensity, jint bitmapDensity) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect dst;
- GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
- doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
- screenDensity, bitmapDensity);
- }
-
- static void drawBitmapRR(JNIEnv* env, jobject, jlong canvasHandle,
- jlong bitmapHandle, jobject srcIRect,
- jobject dstRect, jlong paintHandle,
- jint screenDensity, jint bitmapDensity) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect dst;
- GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
- doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
- screenDensity, bitmapDensity);
- }
-
- static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
- jintArray jcolors, jint offset, jint stride,
- jfloat x, jfloat y, jint width, jint height,
- jboolean hasAlpha, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
- // correct the alphaType to kOpaque_SkAlphaType.
- SkImageInfo info = SkImageInfo::Make(width, height,
- hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
- kPremul_SkAlphaType);
- SkBitmap bitmap;
- if (!bitmap.allocPixels(info)) {
- return;
- }
-
- if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
- 0, 0, width, height, bitmap)) {
- return;
- }
-
- canvas->drawBitmap(bitmap, x, y, paint);
- }
-
- static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle,
- jlong bitmapHandle, jlong matrixHandle,
- jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
- }
-
- static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle,
- jlong bitmapHandle, jint meshWidth, jint meshHeight,
- jfloatArray jverts, jint vertIndex, jintArray jcolors,
- jint colorIndex, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-
- const int ptCount = (meshWidth + 1) * (meshHeight + 1);
- const int indexCount = meshWidth * meshHeight * 6;
-
- AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
- AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
-
- /* Our temp storage holds 2 or 3 arrays.
- texture points [ptCount * sizeof(SkPoint)]
- optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
- copy to convert from float to fixed
- indices [ptCount * sizeof(uint16_t)]
- */
- ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
- storageSize += indexCount * sizeof(uint16_t); // indices[]
-
- SkAutoMalloc storage(storageSize);
- SkPoint* texs = (SkPoint*)storage.get();
- SkPoint* verts;
- uint16_t* indices;
-#ifdef SK_SCALAR_IS_FLOAT
- verts = (SkPoint*)(vertA.ptr() + vertIndex);
- indices = (uint16_t*)(texs + ptCount);
-#else
- SkASSERT(false);
-#endif
-
- // cons up texture coordinates and indices
- {
- const SkScalar w = SkIntToScalar(bitmap->width());
- const SkScalar h = SkIntToScalar(bitmap->height());
- const SkScalar dx = w / meshWidth;
- const SkScalar dy = h / meshHeight;
-
- SkPoint* texsPtr = texs;
- SkScalar y = 0;
- for (int i = 0; i <= meshHeight; i++) {
- if (i == meshHeight) {
- y = h; // to ensure numerically we hit h exactly
- }
- SkScalar x = 0;
- for (int j = 0; j < meshWidth; j++) {
- texsPtr->set(x, y);
- texsPtr += 1;
- x += dx;
- }
- texsPtr->set(w, y);
- texsPtr += 1;
- y += dy;
- }
- SkASSERT(texsPtr - texs == ptCount);
- }
-
- // cons up indices
- {
- uint16_t* indexPtr = indices;
- int index = 0;
- for (int i = 0; i < meshHeight; i++) {
- for (int j = 0; j < meshWidth; j++) {
- // lower-left triangle
- *indexPtr++ = index;
- *indexPtr++ = index + meshWidth + 1;
- *indexPtr++ = index + meshWidth + 2;
- // upper-right triangle
- *indexPtr++ = index;
- *indexPtr++ = index + meshWidth + 2;
- *indexPtr++ = index + 1;
- // bump to the next cell
- index += 1;
- }
- // bump to the next row
- index += 1;
- }
- SkASSERT(indexPtr - indices == indexCount);
- SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
- }
-
- // double-check that we have legal indices
-#ifdef SK_DEBUG
- {
- for (int i = 0; i < indexCount; i++) {
- SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
- }
- }
-#endif
-
- // cons-up a shader for the bitmap
- SkPaint tmpPaint;
- if (paint) {
- tmpPaint = *paint;
- }
- SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
- SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
- SkSafeUnref(tmpPaint.setShader(shader));
-
- canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
- texs, (const SkColor*)colorA.ptr(), NULL, indices,
- indexCount, tmpPaint);
- }
-
- static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
- jint modeHandle, jint vertexCount,
- jfloatArray jverts, jint vertIndex,
- jfloatArray jtexs, jint texIndex,
- jintArray jcolors, jint colorIndex,
- jshortArray jindices, jint indexIndex,
- jint indexCount, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-
- AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
- AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
- AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
- AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
-
- const int ptCount = vertexCount >> 1;
-
- SkPoint* verts;
- SkPoint* texs = NULL;
-#ifdef SK_SCALAR_IS_FLOAT
- verts = (SkPoint*)(vertA.ptr() + vertIndex);
- if (jtexs != NULL) {
- texs = (SkPoint*)(texA.ptr() + texIndex);
- }
-#else
- SkASSERT(false);
-#endif
-
- const SkColor* colors = NULL;
- const uint16_t* indices = NULL;
- if (jcolors != NULL) {
- colors = (const SkColor*)(colorA.ptr() + colorIndex);
- }
- if (jindices != NULL) {
- indices = (const uint16_t*)(indexA.ptr() + indexIndex);
- }
-
- canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
- indices, indexCount, *paint);
- }
-
-
- static void drawText___CIIFFIPaintTypeface(JNIEnv* env, jobject, jlong canvasHandle,
- jcharArray text, jint index, jint count,
- jfloat x, jfloat y, jint bidiFlags,
- jlong paintHandle, jlong typefaceHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
- jchar* textArray = env->GetCharArrayElements(text, NULL);
- drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, bidiFlags, paint, typeface);
- env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
- }
-
- static void drawText__StringIIFFIPaintTypeface(JNIEnv* env, jobject,
- jlong canvasHandle, jstring text,
- jint start, jint end,
- jfloat x, jfloat y, jint bidiFlags,
- jlong paintHandle, jlong typefaceHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
- const jchar* textArray = env->GetStringChars(text, NULL);
- drawTextWithGlyphs(canvas, textArray, start, end, x, y, bidiFlags, paint, typeface);
- env->ReleaseStringChars(text, textArray);
- }
-
- class DrawTextFunctor {
- public:
- DrawTextFunctor(const Layout& layout, SkCanvas* canvas, jfloat x, jfloat y, SkPaint* paint,
- uint16_t* glyphs, SkPoint* pos)
- : layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
- pos(pos) { }
-
- void operator()(size_t start, size_t end) {
- for (size_t i = start; i < end; i++) {
- glyphs[i] = layout.getGlyphId(i);
- pos[i].fX = x + layout.getX(i);
- pos[i].fY = y + layout.getY(i);
- }
- canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
- }
- private:
- const Layout& layout;
- SkCanvas* canvas;
- jfloat x;
- jfloat y;
- SkPaint* paint;
- uint16_t* glyphs;
- SkPoint* pos;
- };
-
- static void drawGlyphsToSkia(SkCanvas* canvas, SkPaint* paint, const Layout& layout, float x, float y) {
- size_t nGlyphs = layout.nGlyphs();
- uint16_t* glyphs = new uint16_t[nGlyphs];
- SkPoint* pos = new SkPoint[nGlyphs];
-
- x += MinikinUtils::xOffsetForTextAlign(paint, layout);
- SkPaint::Align align = paint->getTextAlign();
- paint->setTextAlign(SkPaint::kLeft_Align);
- paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- DrawTextFunctor f(layout, canvas, x, y, paint, glyphs, pos);
- MinikinUtils::forFontRun(layout, paint, f);
- doDrawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
- paint->setTextAlign(align);
- delete[] glyphs;
- delete[] pos;
- }
-
- static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
- int start, int end,
- jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
-
- jint count = end - start;
- drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, bidiFlags, paint,
- typeface);
- }
-
- static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
- int start, int count, int contextCount,
- jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
-
- Layout layout;
- std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
- layout.doLayout(textArray, start, count, contextCount, css);
- drawGlyphsToSkia(canvas, paint, layout, x, y);
- }
-
-// Same values used by Skia
-#define kStdStrikeThru_Offset (-6.0f / 21.0f)
-#define kStdUnderline_Offset (1.0f / 9.0f)
-#define kStdUnderline_Thickness (1.0f / 18.0f)
-
- static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length,
- SkPaint* paint) {
- uint32_t flags;
- SkDrawFilter* drawFilter = canvas->getDrawFilter();
- if (drawFilter) {
- SkPaint paintCopy(*paint);
- drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
- flags = paintCopy.getFlags();
- } else {
- flags = paint->getFlags();
- }
- if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
- SkScalar left = x;
- SkScalar right = x + length;
- float textSize = paint->getTextSize();
- float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
- if (flags & SkPaint::kUnderlineText_Flag) {
- SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
- SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
- canvas->drawRectCoords(left, top, right, bottom, *paint);
- }
- if (flags & SkPaint::kStrikeThruText_Flag) {
- SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
- SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
- canvas->drawRectCoords(left, top, right, bottom, *paint);
- }
- }
- }
-
- static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
- int index, int count, jfloat x, jfloat y, SkPaint* paint) {
- SkPoint* posPtr = new SkPoint[count];
- for (int indx = 0; indx < count; indx++) {
- posPtr[indx].fX = x + posArray[indx * 2];
- posPtr[indx].fY = y + posArray[indx * 2 + 1];
- }
- canvas->drawPosText(glyphArray, count << 1, posPtr, *paint);
- delete[] posPtr;
- }
-
- static void drawTextRun___CIIIIFFZPaintTypeface(
- JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
- jint count, jint contextIndex, jint contextCount,
- jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
-
- int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
- jchar* chars = env->GetCharArrayElements(text, NULL);
- drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
- count, contextCount, x, y, bidiFlags, paint, typeface);
- env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
- }
-
- static void drawTextRun__StringIIIIFFZPaintTypeface(
- JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, jint start,
- jint end, jint contextStart, jint contextEnd,
- jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
-
- int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
- jint count = end - start;
- jint contextCount = contextEnd - contextStart;
- const jchar* chars = env->GetStringChars(text, NULL);
- drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
- count, contextCount, x, y, bidiFlags, paint, typeface);
- env->ReleaseStringChars(text, chars);
- }
-
- static void drawPosText___CII_FPaint(JNIEnv* env, jobject, jlong canvasHandle,
- jcharArray text, jint index, jint count,
- jfloatArray pos, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
- jsize textCount = text ? env->GetArrayLength(text) : NULL;
- float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
- int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
- SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
- int indx;
- for (indx = 0; indx < posCount; indx++) {
- posPtr[indx].fX = posArray[indx << 1];
- posPtr[indx].fY = posArray[(indx << 1) + 1];
- }
-
- SkPaint::TextEncoding encoding = paint->getTextEncoding();
- paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
- canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
- paint->setTextEncoding(encoding);
-
- if (text) {
- env->ReleaseCharArrayElements(text, textArray, 0);
- }
- if (pos) {
- env->ReleaseFloatArrayElements(pos, posArray, 0);
- }
- delete[] posPtr;
- }
-
- static void drawPosText__String_FPaint(JNIEnv* env, jobject,
- jlong canvasHandle, jstring text,
- jfloatArray pos,
- jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
- int byteLength = text ? env->GetStringLength(text) : 0;
- float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
- int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
- SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
-
- for (int indx = 0; indx < posCount; indx++) {
- posPtr[indx].fX = posArray[indx << 1];
- posPtr[indx].fY = posArray[(indx << 1) + 1];
- }
-
- SkPaint::TextEncoding encoding = paint->getTextEncoding();
- paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
- canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
- paint->setTextEncoding(encoding);
-
- if (text) {
- env->ReleaseStringChars(text, (const jchar*) text_);
- }
- if (pos) {
- env->ReleaseFloatArrayElements(pos, posArray, 0);
- }
- delete[] posPtr;
- }
-
- class DrawTextOnPathFunctor {
- public:
- DrawTextOnPathFunctor(const Layout& layout, SkCanvas* canvas, float hOffset,
- float vOffset, SkPaint* paint, SkPath* path)
- : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
- paint(paint), path(path) {
- }
- void operator()(size_t start, size_t end) {
- uint16_t glyphs[1];
- for (size_t i = start; i < end; i++) {
- glyphs[0] = layout.getGlyphId(i);
- float x = hOffset + layout.getX(i);
- float y = vOffset + layout.getY(i);
- canvas->drawTextOnPathHV(glyphs, sizeof(glyphs), *path, x, y, *paint);
- }
- }
- private:
- const Layout& layout;
- SkCanvas* canvas;
- float hOffset;
- float vOffset;
- SkPaint* paint;
- SkPath* path;
- };
-
- static void doDrawTextOnPath(SkPaint* paint, const jchar* text, int count, int bidiFlags,
- float hOffset, float vOffset, SkPath* path, SkCanvas* canvas, TypefaceImpl* typeface) {
- Layout layout;
- std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
- layout.doLayout(text, 0, count, count, css);
- hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
- // Set align to left for drawing, as we don't want individual
- // glyphs centered or right-aligned; the offset above takes
- // care of all alignment.
- SkPaint::Align align = paint->getTextAlign();
- paint->setTextAlign(SkPaint::kLeft_Align);
-
- DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paint, path);
- MinikinUtils::forFontRun(layout, paint, f);
- paint->setTextAlign(align);
- }
-
- static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
- jlong canvasHandle, jcharArray text, jint index, jint count,
- jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle,
- jlong typefaceHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
-
- jchar* textArray = env->GetCharArrayElements(text, NULL);
- doDrawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
- path, canvas, typeface);
- env->ReleaseCharArrayElements(text, textArray, 0);
- }
-
- static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
- jlong canvasHandle, jstring text, jlong pathHandle,
- jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle,
- jlong typefaceHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
-
- const jchar* text_ = env->GetStringChars(text, NULL);
- int count = env->GetStringLength(text);
- doDrawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
- path, canvas, typeface);
- env->ReleaseStringChars(text, text_);
- }
-
-
- // This function is a mirror of SkCanvas::getClipBounds except that it does
- // not outset the edge of the clip to account for anti-aliasing. There is
- // a skia bug to investigate pushing this logic into back into skia.
- // (see https://code.google.com/p/skia/issues/detail?id=1303)
- static bool getHardClipBounds(SkCanvas* canvas, SkRect* bounds) {
- SkIRect ibounds;
- if (!canvas->getClipDeviceBounds(&ibounds)) {
- return false;
- }
-
- SkMatrix inverse;
- // if we can't invert the CTM, we can't return local clip bounds
- if (!canvas->getTotalMatrix().invert(&inverse)) {
- if (bounds) {
- bounds->setEmpty();
- }
- return false;
- }
-
- if (NULL != bounds) {
- SkRect r = SkRect::Make(ibounds);
- inverse.mapRect(bounds, r);
- }
- return true;
- }
-
- static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle,
- jobject bounds) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkRect r;
- SkIRect ir;
- bool result = getHardClipBounds(canvas, &r);
-
- if (!result) {
- r.setEmpty();
- }
- r.round(&ir);
-
- (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
- return result ? JNI_TRUE : JNI_FALSE;
- }
-
- static void getCTM(JNIEnv* env, jobject, jlong canvasHandle,
- jlong matrixHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- *matrix = canvas->getTotalMatrix();
- }
-};
-
-static JNINativeMethod gCanvasMethods[] = {
- {"finalizer", "(J)V", (void*) SkCanvasGlue::finalizer},
- {"initRaster", "(J)J", (void*) SkCanvasGlue::initRaster},
- {"initCanvas", "(J)J", (void*) SkCanvasGlue::initCanvas},
- {"native_setBitmap", "(JJZ)V", (void*) SkCanvasGlue::setBitmap},
- {"native_isOpaque","(J)Z", (void*) SkCanvasGlue::isOpaque},
- {"native_getWidth","(J)I", (void*) SkCanvasGlue::getWidth},
- {"native_getHeight","(J)I", (void*) SkCanvasGlue::getHeight},
- {"native_save","(JI)I", (void*) SkCanvasGlue::save},
- {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer},
- {"native_saveLayerAlpha","(JFFFFII)I", (void*) SkCanvasGlue::saveLayerAlpha},
- {"native_restore","(J)V", (void*) SkCanvasGlue::restore},
- {"native_getSaveCount","(J)I", (void*) SkCanvasGlue::getSaveCount},
- {"native_restoreToCount","(JI)V", (void*) SkCanvasGlue::restoreToCount},
- {"native_translate","(JFF)V", (void*) SkCanvasGlue::translate},
- {"native_scale","(JFF)V", (void*) SkCanvasGlue::scale__FF},
- {"native_rotate","(JF)V", (void*) SkCanvasGlue::rotate__F},
- {"native_skew","(JFF)V", (void*) SkCanvasGlue::skew__FF},
- {"native_concat","(JJ)V", (void*) SkCanvasGlue::concat},
- {"native_setMatrix","(JJ)V", (void*) SkCanvasGlue::setMatrix},
- {"native_clipRect","(JFFFFI)Z", (void*) SkCanvasGlue::clipRect},
- {"native_clipPath","(JJI)Z", (void*) SkCanvasGlue::clipPath},
- {"native_clipRegion","(JJI)Z", (void*) SkCanvasGlue::clipRegion},
- {"nativeSetDrawFilter", "(JJ)V", (void*) SkCanvasGlue::setDrawFilter},
- {"native_getClipBounds","(JLandroid/graphics/Rect;)Z",
- (void*) SkCanvasGlue::getClipBounds},
- {"native_getCTM", "(JJ)V", (void*)SkCanvasGlue::getCTM},
- {"native_quickReject","(JJ)Z", (void*) SkCanvasGlue::quickReject__Path},
- {"native_quickReject","(JFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
- {"native_drawRGB","(JIII)V", (void*) SkCanvasGlue::drawRGB},
- {"native_drawARGB","(JIIII)V", (void*) SkCanvasGlue::drawARGB},
- {"native_drawColor","(JI)V", (void*) SkCanvasGlue::drawColor__I},
- {"native_drawColor","(JII)V", (void*) SkCanvasGlue::drawColor__II},
- {"native_drawPaint","(JJ)V", (void*) SkCanvasGlue::drawPaint},
- {"native_drawPoint", "(JFFJ)V", (void*) SkCanvasGlue::drawPoint},
- {"native_drawPoints", "(J[FIIJ)V", (void*) SkCanvasGlue::drawPoints},
- {"native_drawLines", "(J[FIIJ)V", (void*) SkCanvasGlue::drawLines},
- {"native_drawLine","(JFFFFJ)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
- {"native_drawRect","(JFFFFJ)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
- {"native_drawOval","(JFFFFJ)V", (void*) SkCanvasGlue::drawOval},
- {"native_drawCircle","(JFFFJ)V", (void*) SkCanvasGlue::drawCircle},
- {"native_drawArc","(JFFFFFFZJ)V", (void*) SkCanvasGlue::drawArc},
- {"native_drawRoundRect","(JFFFFFFJ)V",
- (void*) SkCanvasGlue::drawRoundRect},
- {"native_drawPath","(JJJ)V", (void*) SkCanvasGlue::drawPath},
- {"native_drawBitmap","(JJFFJIII)V",
- (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
- {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/RectF;JII)V",
- (void*) SkCanvasGlue::drawBitmapRF},
- {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/Rect;JII)V",
- (void*) SkCanvasGlue::drawBitmapRR},
- {"native_drawBitmap", "(J[IIIFFIIZJ)V",
- (void*)SkCanvasGlue::drawBitmapArray},
- {"nativeDrawBitmapMatrix", "(JJJJ)V",
- (void*)SkCanvasGlue::drawBitmapMatrix},
- {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V",
- (void*)SkCanvasGlue::drawBitmapMesh},
- {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V",
- (void*)SkCanvasGlue::drawVertices},
- {"native_drawText","(J[CIIFFIJJ)V",
- (void*) SkCanvasGlue::drawText___CIIFFIPaintTypeface},
- {"native_drawText","(JLjava/lang/String;IIFFIJJ)V",
- (void*) SkCanvasGlue::drawText__StringIIFFIPaintTypeface},
- {"native_drawTextRun","(J[CIIIIFFZJJ)V",
- (void*) SkCanvasGlue::drawTextRun___CIIIIFFZPaintTypeface},
- {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V",
- (void*) SkCanvasGlue::drawTextRun__StringIIIIFFZPaintTypeface},
- {"native_drawTextOnPath","(J[CIIJFFIJJ)V",
- (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
- {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V",
- (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
-
- {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
-
- {"freeTextLayoutCaches", "()V", (void*) SkCanvasGlue::freeTextLayoutCaches}
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include <android_runtime/AndroidRuntime.h>
-
-#define REG(env, name, array) \
- result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
- SK_ARRAY_COUNT(array)); \
- if (result < 0) return result
-
-int register_android_graphics_Canvas(JNIEnv* env) {
- int result;
-
- REG(env, "android/graphics/Canvas", gCanvasMethods);
-
- return result;
-}
-
-} // namespace android
-
-// GraphicsJNI helper for external clients.
-// We keep the implementation here to avoid exposing NativeCanvasWrapper
-// externally.
-SkCanvas* GraphicsJNI::getNativeCanvas(jlong nativeHandle) {
- return android::SkCanvasGlue::getNativeCanvas(nativeHandle);
-}
diff --git a/core/jni/android/graphics/Canvas.h b/core/jni/android/graphics/Canvas.h
new file mode 100644
index 0000000..710845d
--- /dev/null
+++ b/core/jni/android/graphics/Canvas.h
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_GRAPHICS_CANVAS_H
+#define ANDROID_GRAPHICS_CANVAS_H
+
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkMatrix.h"
+
+namespace android {
+
+// TODO: move this further up the stack so that all interaction with minikin
+// happens prior to calling into this interface
+class TypefaceImpl;
+
+class Canvas {
+public:
+ virtual ~Canvas() {};
+
+ static Canvas* create_canvas(SkBitmap* bitmap);
+ static Canvas* create_canvas(SkCanvas* skiaCanvas);
+
+ // TODO: enable HWUI to either create similar canvas wrapper or subclass
+ // directly from Canvas
+ //static Canvas* create_canvas(uirenderer::Renderer* renderer);
+
+ // TODO: this is a temporary affordance until all necessary logic can be
+ // moved within this interface! Further, the return value should
+ // NOT be unref'd and is valid until this canvas is destroyed or a
+ // new bitmap is set.
+ virtual SkCanvas* getSkCanvas() = 0;
+
+ virtual void setBitmap(SkBitmap* bitmap, bool copyState) = 0;
+
+ virtual bool isOpaque() = 0;
+ virtual int width() = 0;
+ virtual int height() = 0;
+
+// ----------------------------------------------------------------------------
+// Canvas state operations
+// ----------------------------------------------------------------------------
+ // Save (layer)
+ virtual int getSaveCount() const = 0;
+ virtual int save(SkCanvas::SaveFlags flags) = 0;
+ virtual void restore() = 0;
+ virtual void restoreToCount(int saveCount) = 0;
+
+ virtual int saveLayer(float left, float top, float right, float bottom,
+ const SkPaint* paint, SkCanvas::SaveFlags flags) = 0;
+ virtual int saveLayerAlpha(float left, float top, float right, float bottom,
+ int alpha, SkCanvas::SaveFlags flags) = 0;
+
+ // Matrix
+ virtual void getMatrix(SkMatrix* outMatrix) const = 0;
+ virtual void setMatrix(const SkMatrix& matrix) = 0;
+
+ virtual void concat(const SkMatrix& matrix) = 0;
+ virtual void rotate(float degrees) = 0;
+ virtual void scale(float sx, float sy) = 0;
+ virtual void skew(float sx, float sy) = 0;
+ virtual void translate(float dx, float dy) = 0;
+
+ // clip
+ virtual bool getClipBounds(SkRect* outRect) const = 0;
+ virtual bool quickRejectRect(float left, float top, float right, float bottom) const = 0;
+ virtual bool quickRejectPath(const SkPath& path) const = 0;
+
+ virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) = 0;
+ virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0;
+ virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
+
+ // filters
+ virtual void setDrawFilter(SkDrawFilter* drawFilter) = 0;
+
+// ----------------------------------------------------------------------------
+// Canvas draw operations
+// ----------------------------------------------------------------------------
+ virtual void drawColor(int color, SkXfermode::Mode mode) = 0;
+ virtual void drawPaint(const SkPaint& paint) = 0;
+
+ // Geometry
+ virtual void drawPoint(float x, float y, const SkPaint& paint) = 0;
+ virtual void drawPoints(const float* points, int count, const SkPaint& paint) = 0;
+ virtual void drawLine(float startX, float startY, float stopX, float stopY,
+ const SkPaint& paint) = 0;
+ virtual void drawLines(const float* points, int count, const SkPaint& paint) = 0;
+ virtual void drawRect(float left, float top, float right, float bottom,
+ const SkPaint& paint) = 0;
+ virtual void drawRoundRect(float left, float top, float right, float bottom,
+ float rx, float ry, const SkPaint& paint) = 0;
+ virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) = 0;
+ virtual void drawOval(float left, float top, float right, float bottom,
+ const SkPaint& paint) = 0;
+ virtual void drawArc(float left, float top, float right, float bottom,
+ float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) = 0;
+ virtual void drawPath(const SkPath& path, const SkPaint& paint) = 0;
+ virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
+ const float* verts, const float* tex, const int* colors,
+ const uint16_t* indices, int indexCount, const SkPaint& paint) = 0;
+
+ // Bitmap-based
+ virtual void drawBitmap(const SkBitmap& bitmap, float left, float top,
+ const SkPaint* paint) = 0;
+ virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
+ const SkPaint* paint) = 0;
+ virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
+ float srcRight, float srcBottom, float dstLeft, float dstTop,
+ float dstRight, float dstBottom, const SkPaint* paint) = 0;
+ virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
+ const float* vertices, const int* colors, const SkPaint* paint) = 0;
+
+ // Text
+ virtual void drawText(const char* text, int start, int count, int contextCount,
+ float x, float y, int bidiFlags, const SkPaint& paint,
+ TypefaceImpl* typeface) = 0;
+ virtual void drawPosText(const char* text, const float* positions, int count, int posCount,
+ const SkPaint& paint) = 0;
+ virtual void drawTextOnPath(const char* text, int count, const SkPath& path,
+ float hOffset, float vOffset, const SkPaint& paint) = 0;
+};
+
+}; // namespace android
+#endif // ANDROID_GRAPHICS_CANVAS_H
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 9177696..74be577 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -4,6 +4,7 @@
#include "JNIHelp.h"
#include "GraphicsJNI.h"
+#include "Canvas.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkMath.h"
@@ -364,7 +365,7 @@
SkASSERT(canvas);
SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
jlong canvasHandle = env->GetLongField(canvas, gCanvas_nativeInstanceID);
- SkCanvas* c = getNativeCanvas(canvasHandle);
+ SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
SkASSERT(c);
return c;
}
@@ -415,7 +416,7 @@
}
jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
- int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density)
+ int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets, int density)
{
SkASSERT(bitmap);
SkASSERT(bitmap->pixelRef());
@@ -429,17 +430,11 @@
jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
reinterpret_cast<jlong>(bitmap), buffer,
bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied,
- ninepatch, layoutbounds);
+ ninePatchChunk, ninePatchInsets);
hasException(env); // For the side effect of logging.
return obj;
}
-jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags,
- jbyteArray ninepatch, int density)
-{
- return createBitmap(env, bitmap, NULL, bitmapCreateFlags, ninepatch, NULL, density);
-}
-
void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap,
bool isPremultiplied)
{
@@ -720,7 +715,7 @@
gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "J");
- gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(J[BIIIZZ[B[I)V");
+ gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(J[BIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index a03391d..28a6edb 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -47,7 +47,6 @@
static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
- static SkCanvas* getNativeCanvas(jlong nativeHandle);
static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas);
static SkPaint* getNativePaint(JNIEnv*, jobject paint);
static android::TypefaceImpl* getNativeTypeface(JNIEnv*, jobject paint);
@@ -76,10 +75,12 @@
bitmap's SkAlphaType must already be in sync with bitmapCreateFlags.
*/
static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
- int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density = -1);
+ int bitmapCreateFlags, jbyteArray ninePatch, jobject ninePatchInsets, int density = -1);
static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags,
- jbyteArray ninepatch, int density = -1);
+ jbyteArray ninePatch, int density = -1) {
+ return createBitmap(env, bitmap, NULL, bitmapCreateFlags, ninePatch, NULL, density);
+ }
/** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
sync with isPremultiplied
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index ab5bdb0..e82e8a6 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -23,6 +23,7 @@
#include <Caches.h>
+#include "Canvas.h"
#include "SkCanvas.h"
#include "SkRegion.h"
#include "GraphicsJNI.h"
@@ -119,7 +120,7 @@
static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF,
jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
jint destDensity, jint srcDensity) {
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
+ SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
@@ -138,7 +139,7 @@
static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect,
jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
jint destDensity, jint srcDensity) {
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
+ SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp
index 5daa1ad..ea5193b 100644
--- a/core/jni/android/graphics/NinePatchPeeker.cpp
+++ b/core/jni/android/graphics/NinePatchPeeker.cpp
@@ -21,7 +21,7 @@
using namespace android;
bool NinePatchPeeker::peek(const char tag[], const void* data, size_t length) {
- if (strcmp("npTc", tag) == 0 && length >= sizeof(Res_png_9patch)) {
+ if (!strcmp("npTc", tag) && length >= sizeof(Res_png_9patch)) {
Res_png_9patch* patch = (Res_png_9patch*) data;
size_t patchSize = patch->serializedSize();
assert(length == patchSize);
@@ -30,12 +30,9 @@
memcpy(patchNew, patch, patchSize);
Res_png_9patch::deserialize(patchNew);
patchNew->fileToDevice();
- free(fPatch);
- fPatch = patchNew;
- fPatchSize = patchSize;
- //printf("9patch: (%d,%d)-(%d,%d)\n",
- // fPatch.sizeLeft, fPatch.sizeTop,
- // fPatch.sizeRight, fPatch.sizeBottom);
+ free(mPatch);
+ mPatch = patchNew;
+ mPatchSize = patchSize;
// now update our host to force index or 32bit config
// 'cause we don't want 565 predithered, since as a 9patch, we know
@@ -47,10 +44,15 @@
table.fPrefFor_8bpc_NoAlpha_src = SkBitmap::kARGB_8888_Config;
table.fPrefFor_8bpc_YesAlpha_src = SkBitmap::kARGB_8888_Config;
- fHost->setPrefConfigTable(table);
- } else if (strcmp("npLb", tag) == 0 && length == sizeof(int) * 4) {
- fLayoutBounds = new int[4];
- memcpy(fLayoutBounds, data, sizeof(int) * 4);
+ mHost->setPrefConfigTable(table);
+ } else if (!strcmp("npLb", tag) && length == sizeof(int32_t) * 4) {
+ mHasInsets = true;
+ memcpy(&mOpticalInsets, data, sizeof(int32_t) * 4);
+ } else if (!strcmp("npOl", tag) && length == 24) { // 4 int32_ts, 1 float, 1 int32_t sized bool
+ mHasInsets = true;
+ memcpy(&mOutlineInsets, data, sizeof(int32_t) * 4);
+ mOutlineRadius = ((const float*)data)[4];
+ mOutlineFilled = ((const int32_t*)data)[5] & 0x01;
}
return true; // keep on decoding
}
diff --git a/core/jni/android/graphics/NinePatchPeeker.h b/core/jni/android/graphics/NinePatchPeeker.h
index 2043862..8d3e6cf 100644
--- a/core/jni/android/graphics/NinePatchPeeker.h
+++ b/core/jni/android/graphics/NinePatchPeeker.h
@@ -23,26 +23,34 @@
using namespace android;
class NinePatchPeeker : public SkImageDecoder::Peeker {
- SkImageDecoder* fHost;
+private:
+ // the host lives longer than we do, so a raw ptr is safe
+ SkImageDecoder* mHost;
public:
- NinePatchPeeker(SkImageDecoder* host) {
- // the host lives longer than we do, so a raw ptr is safe
- fHost = host;
- fPatch = NULL;
- fPatchSize = 0;
- fLayoutBounds = NULL;
+ NinePatchPeeker(SkImageDecoder* host)
+ : mHost(host)
+ , mPatch(NULL)
+ , mPatchSize(0)
+ , mHasInsets(false)
+ , mOutlineRadius(0)
+ , mOutlineFilled(false) {
+ memset(mOpticalInsets, 0, 4 * sizeof(int32_t));
+ memset(mOutlineInsets, 0, 4 * sizeof(int32_t));
}
~NinePatchPeeker() {
- free(fPatch);
- delete fLayoutBounds;
+ free(mPatch);
}
- Res_png_9patch* fPatch;
- size_t fPatchSize;
- int *fLayoutBounds;
-
virtual bool peek(const char tag[], const void* data, size_t length);
+
+ Res_png_9patch* mPatch;
+ size_t mPatchSize;
+ bool mHasInsets;
+ int32_t mOpticalInsets[4];
+ int32_t mOutlineInsets[4];
+ float mOutlineRadius;
+ bool mOutlineFilled;
};
#endif // NinePatchPeeker_h
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index bc0c25f..d214575 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
+#include "Canvas.h"
#include "Picture.h"
-#include "SkCanvas.h"
#include "SkStream.h"
namespace android {
@@ -36,12 +36,13 @@
}
}
-SkCanvas* Picture::beginRecording(int width, int height) {
+Canvas* Picture::beginRecording(int width, int height) {
mPicture.reset(NULL);
mRecorder.reset(new SkPictureRecorder);
mWidth = width;
mHeight = height;
- return mRecorder->beginRecording(width, height, NULL, 0);
+ SkCanvas* canvas = mRecorder->beginRecording(width, height, NULL, 0);
+ return Canvas::create_canvas(canvas);
}
void Picture::endRecording() {
@@ -93,14 +94,14 @@
}
}
-void Picture::draw(SkCanvas* canvas) {
+void Picture::draw(Canvas* canvas) {
if (NULL != mRecorder.get()) {
this->endRecording();
SkASSERT(NULL != mPicture.get());
}
if (NULL != mPicture.get()) {
// TODO: remove this const_cast once pictures are immutable
- const_cast<SkPicture*>(mPicture.get())->draw(canvas);
+ const_cast<SkPicture*>(mPicture.get())->draw(canvas->getSkCanvas());
}
}
diff --git a/core/jni/android/graphics/Picture.h b/core/jni/android/graphics/Picture.h
index abb0403..a2e5d4a 100644
--- a/core/jni/android/graphics/Picture.h
+++ b/core/jni/android/graphics/Picture.h
@@ -22,14 +22,13 @@
#include "SkRefCnt.h"
#include "SkTemplates.h"
-class SkCanvas;
-class SkPicture;
-class SkPictureRecorder;
class SkStream;
class SkWStream;
namespace android {
+class Canvas;
+
// Skia's SkPicture class has been split into an SkPictureRecorder
// and an SkPicture. AndroidPicture recreates the functionality
// of the old SkPicture interface by flip-flopping between the two
@@ -38,7 +37,7 @@
public:
explicit Picture(const Picture* src = NULL);
- SkCanvas* beginRecording(int width, int height);
+ Canvas* beginRecording(int width, int height);
void endRecording();
@@ -50,7 +49,7 @@
void serialize(SkWStream* stream) const;
- void draw(SkCanvas* canvas);
+ void draw(Canvas* canvas);
private:
int mWidth;
diff --git a/core/jni/android/graphics/SkiaCanvas.cpp b/core/jni/android/graphics/SkiaCanvas.cpp
new file mode 100644
index 0000000..5e93313
--- /dev/null
+++ b/core/jni/android/graphics/SkiaCanvas.cpp
@@ -0,0 +1,773 @@
+/*
+ * 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.
+ */
+
+#include "jni.h"
+#include "Canvas.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "SkCanvas.h"
+#include "SkClipStack.h"
+#include "SkDevice.h"
+#include "SkDeque.h"
+#include "SkDrawFilter.h"
+#include "SkGraphics.h"
+#include "SkPorterDuff.h"
+#include "SkShader.h"
+#include "SkTArray.h"
+#include "SkTemplates.h"
+
+#include <minikin/Layout.h>
+#include "MinikinSkia.h"
+#include "MinikinUtils.h"
+
+#include "TypefaceImpl.h"
+
+#include "unicode/ubidi.h"
+#include "unicode/ushape.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+// Holds an SkCanvas reference plus additional native data.
+class SkiaCanvas : public Canvas {
+public:
+ SkiaCanvas(SkBitmap* bitmap);
+
+ SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {
+ SkASSERT(canvas);
+ }
+
+ virtual SkCanvas* getSkCanvas() {
+ return mCanvas.get();
+ }
+
+ virtual void setBitmap(SkBitmap* bitmap, bool copyState);
+
+ virtual bool isOpaque();
+ virtual int width();
+ virtual int height();
+
+ virtual int getSaveCount() const;
+ virtual int save(SkCanvas::SaveFlags flags);
+ virtual void restore();
+ virtual void restoreToCount(int saveCount);
+
+ virtual int saveLayer(float left, float top, float right, float bottom,
+ const SkPaint* paint, SkCanvas::SaveFlags flags);
+ virtual int saveLayerAlpha(float left, float top, float right, float bottom,
+ int alpha, SkCanvas::SaveFlags flags);
+
+ virtual void getMatrix(SkMatrix* outMatrix) const;
+ virtual void setMatrix(const SkMatrix& matrix);
+ virtual void concat(const SkMatrix& matrix);
+ virtual void rotate(float degrees);
+ virtual void scale(float sx, float sy);
+ virtual void skew(float sx, float sy);
+ virtual void translate(float dx, float dy);
+
+ virtual bool getClipBounds(SkRect* outRect) const;
+ virtual bool quickRejectRect(float left, float top, float right, float bottom) const;
+ virtual bool quickRejectPath(const SkPath& path) const;
+ virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
+ virtual bool clipPath(const SkPath* path, SkRegion::Op op);
+ virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
+
+ virtual void setDrawFilter(SkDrawFilter* drawFilter);
+
+ virtual void drawColor(int color, SkXfermode::Mode mode);
+ virtual void drawPaint(const SkPaint& paint);
+
+ virtual void drawPoint(float x, float y, const SkPaint& paint);
+ virtual void drawPoints(const float* points, int count, const SkPaint& paint);
+ virtual void drawLine(float startX, float startY, float stopX, float stopY,
+ const SkPaint& paint);
+ virtual void drawLines(const float* points, int count, const SkPaint& paint);
+ virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint);
+ virtual void drawRoundRect(float left, float top, float right, float bottom,
+ float rx, float ry, const SkPaint& paint);
+ virtual void drawCircle(float x, float y, float radius, const SkPaint& paint);
+ virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint);
+ virtual void drawArc(float left, float top, float right, float bottom,
+ float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint);
+ virtual void drawPath(const SkPath& path, const SkPaint& paint);
+ virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
+ const float* verts, const float* tex, const int* colors,
+ const uint16_t* indices, int indexCount, const SkPaint& paint);
+
+ virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint);
+ virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint);
+ virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
+ float srcRight, float srcBottom, float dstLeft, float dstTop,
+ float dstRight, float dstBottom, const SkPaint* paint);
+ virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
+ const float* vertices, const int* colors, const SkPaint* paint);
+
+ virtual void drawText(const char* text, int start, int count, int contextCount,
+ float x, float y, int bidiFlags, const SkPaint& paint, TypefaceImpl* typeface);
+ virtual void drawPosText(const char* text, const float* positions, int count, int posCount,
+ const SkPaint& paint);
+ virtual void drawTextOnPath(const char* text, int count, const SkPath& path,
+ float hOffset, float vOffset, const SkPaint& paint);
+
+private:
+ struct SaveRec {
+ int saveCount;
+ SkCanvas::SaveFlags saveFlags;
+ };
+
+ void recordPartialSave(SkCanvas::SaveFlags flags);
+ void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount);
+ void applyClips(const SkTArray<SkClipStack::Element>& clips);
+
+ void drawPoints(const float* points, int count, const SkPaint& paint,
+ SkCanvas::PointMode mode);
+ void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
+
+ SkAutoTUnref<SkCanvas> mCanvas;
+ SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
+};
+
+// Construct an SkCanvas from the bitmap.
+static SkCanvas* createCanvas(SkBitmap* bitmap) {
+ if (bitmap) {
+ return SkNEW_ARGS(SkCanvas, (*bitmap));
+ }
+
+ // Create an empty bitmap device to prevent callers from crashing
+ // if they attempt to draw into this canvas.
+ SkBitmap emptyBitmap;
+ return new SkCanvas(emptyBitmap);
+}
+
+Canvas* Canvas::create_canvas(SkBitmap* bitmap) {
+ return new SkiaCanvas(bitmap);
+}
+
+Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) {
+ return new SkiaCanvas(skiaCanvas);
+}
+
+SkiaCanvas::SkiaCanvas(SkBitmap* bitmap) {
+ mCanvas.reset(createCanvas(bitmap));
+}
+
+// ----------------------------------------------------------------------------
+// Canvas state operations: Replace Bitmap
+// ----------------------------------------------------------------------------
+
+class ClipCopier : public SkCanvas::ClipVisitor {
+public:
+ ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
+
+ virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
+ m_dstCanvas->clipRect(rect, op, antialias);
+ }
+ virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
+ m_dstCanvas->clipRRect(rrect, op, antialias);
+ }
+ virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
+ m_dstCanvas->clipPath(path, op, antialias);
+ }
+
+private:
+ SkCanvas* m_dstCanvas;
+};
+
+void SkiaCanvas::setBitmap(SkBitmap* bitmap, bool copyState) {
+ SkCanvas* newCanvas = createCanvas(bitmap);
+ SkASSERT(newCanvas);
+
+ if (copyState) {
+ // Copy the canvas matrix & clip state.
+ newCanvas->setMatrix(mCanvas->getTotalMatrix());
+ if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) {
+ ClipCopier copier(newCanvas);
+ mCanvas->replayClips(&copier);
+ }
+ }
+
+ // unrefs the existing canvas
+ mCanvas.reset(newCanvas);
+
+ // clean up the old save stack
+ mSaveStack.reset(NULL);
+}
+
+// ----------------------------------------------------------------------------
+// Canvas state operations
+// ----------------------------------------------------------------------------
+
+bool SkiaCanvas::isOpaque() {
+ return mCanvas->getDevice()->accessBitmap(false).isOpaque();
+}
+
+int SkiaCanvas::width() {
+ return mCanvas->getBaseLayerSize().width();
+}
+
+int SkiaCanvas::height() {
+ return mCanvas->getBaseLayerSize().height();
+}
+
+// ----------------------------------------------------------------------------
+// Canvas state operations: Save (layer)
+// ----------------------------------------------------------------------------
+
+int SkiaCanvas::getSaveCount() const {
+ return mCanvas->getSaveCount();
+}
+
+int SkiaCanvas::save(SkCanvas::SaveFlags flags) {
+ int count = mCanvas->save();
+ recordPartialSave(flags);
+ return count;
+}
+
+void SkiaCanvas::restore() {
+ const SaveRec* rec = (NULL == mSaveStack.get())
+ ? NULL
+ : static_cast<SaveRec*>(mSaveStack->back());
+ int currentSaveCount = mCanvas->getSaveCount() - 1;
+ SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount);
+
+ if (NULL == rec || rec->saveCount != currentSaveCount) {
+ // Fast path - no record for this frame.
+ mCanvas->restore();
+ return;
+ }
+
+ bool preserveMatrix = !(rec->saveFlags & SkCanvas::kMatrix_SaveFlag);
+ bool preserveClip = !(rec->saveFlags & SkCanvas::kClip_SaveFlag);
+
+ SkMatrix savedMatrix;
+ if (preserveMatrix) {
+ savedMatrix = mCanvas->getTotalMatrix();
+ }
+
+ SkTArray<SkClipStack::Element> savedClips;
+ if (preserveClip) {
+ saveClipsForFrame(savedClips, currentSaveCount);
+ }
+
+ mCanvas->restore();
+
+ if (preserveMatrix) {
+ mCanvas->setMatrix(savedMatrix);
+ }
+
+ if (preserveClip && !savedClips.empty()) {
+ applyClips(savedClips);
+ }
+
+ mSaveStack->pop_back();
+}
+
+void SkiaCanvas::restoreToCount(int restoreCount) {
+ while (mCanvas->getSaveCount() > restoreCount) {
+ this->restore();
+ }
+}
+
+int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
+ const SkPaint* paint, SkCanvas::SaveFlags flags) {
+ SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
+ int count = mCanvas->saveLayer(&bounds, paint, flags | SkCanvas::kMatrixClip_SaveFlag);
+ recordPartialSave(flags);
+ return count;
+}
+
+int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
+ int alpha, SkCanvas::SaveFlags flags) {
+ SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
+ int count = mCanvas->saveLayerAlpha(&bounds, alpha, flags | SkCanvas::kMatrixClip_SaveFlag);
+ recordPartialSave(flags);
+ return count;
+}
+
+// ----------------------------------------------------------------------------
+// functions to emulate legacy SaveFlags (i.e. independent matrix/clip flags)
+// ----------------------------------------------------------------------------
+
+void SkiaCanvas::recordPartialSave(SkCanvas::SaveFlags flags) {
+ // A partial save is a save operation which doesn't capture the full canvas state.
+ // (either kMatrix_SaveFlags or kClip_SaveFlag is missing).
+
+ // Mask-out non canvas state bits.
+ flags = static_cast<SkCanvas::SaveFlags>(flags & SkCanvas::kMatrixClip_SaveFlag);
+
+ if (SkCanvas::kMatrixClip_SaveFlag == flags) {
+ // not a partial save.
+ return;
+ }
+
+ if (NULL == mSaveStack.get()) {
+ mSaveStack.reset(SkNEW_ARGS(SkDeque, (sizeof(struct SaveRec), 8)));
+ }
+
+ SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
+ // Store the save counter in the SkClipStack domain.
+ // (0-based, equal to the number of save ops on the stack).
+ rec->saveCount = mCanvas->getSaveCount() - 1;
+ rec->saveFlags = flags;
+}
+
+void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount) {
+ SkClipStack::Iter clipIterator(*mCanvas->getClipStack(),
+ SkClipStack::Iter::kTop_IterStart);
+ while (const SkClipStack::Element* elem = clipIterator.next()) {
+ if (elem->getSaveCount() < frameSaveCount) {
+ // done with the current frame.
+ break;
+ }
+ SkASSERT(elem->getSaveCount() == frameSaveCount);
+ clips.push_back(*elem);
+ }
+}
+
+void SkiaCanvas::applyClips(const SkTArray<SkClipStack::Element>& clips) {
+ ClipCopier clipCopier(mCanvas);
+
+ // The clip stack stores clips in device space.
+ SkMatrix origMatrix = mCanvas->getTotalMatrix();
+ mCanvas->resetMatrix();
+
+ // We pushed the clips in reverse order.
+ for (int i = clips.count() - 1; i >= 0; --i) {
+ clips[i].replay(&clipCopier);
+ }
+
+ mCanvas->setMatrix(origMatrix);
+}
+
+// ----------------------------------------------------------------------------
+// Canvas state operations: Matrix
+// ----------------------------------------------------------------------------
+
+void SkiaCanvas::getMatrix(SkMatrix* outMatrix) const {
+ *outMatrix = mCanvas->getTotalMatrix();
+}
+
+void SkiaCanvas::setMatrix(const SkMatrix& matrix) {
+ mCanvas->setMatrix(matrix);
+}
+
+void SkiaCanvas::concat(const SkMatrix& matrix) {
+ mCanvas->concat(matrix);
+}
+
+void SkiaCanvas::rotate(float degrees) {
+ mCanvas->rotate(degrees);
+}
+
+void SkiaCanvas::scale(float sx, float sy) {
+ mCanvas->scale(sx, sy);
+}
+
+void SkiaCanvas::skew(float sx, float sy) {
+ mCanvas->skew(sx, sy);
+}
+
+void SkiaCanvas::translate(float dx, float dy) {
+ mCanvas->translate(dx, dy);
+}
+
+// ----------------------------------------------------------------------------
+// Canvas state operations: Clips
+// ----------------------------------------------------------------------------
+
+// This function is a mirror of SkCanvas::getClipBounds except that it does
+// not outset the edge of the clip to account for anti-aliasing. There is
+// a skia bug to investigate pushing this logic into back into skia.
+// (see https://code.google.com/p/skia/issues/detail?id=1303)
+bool SkiaCanvas::getClipBounds(SkRect* outRect) const {
+ SkIRect ibounds;
+ if (!mCanvas->getClipDeviceBounds(&ibounds)) {
+ return false;
+ }
+
+ SkMatrix inverse;
+ // if we can't invert the CTM, we can't return local clip bounds
+ if (!mCanvas->getTotalMatrix().invert(&inverse)) {
+ if (outRect) {
+ outRect->setEmpty();
+ }
+ return false;
+ }
+
+ if (NULL != outRect) {
+ SkRect r = SkRect::Make(ibounds);
+ inverse.mapRect(outRect, r);
+ }
+ return true;
+}
+
+bool SkiaCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
+ SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
+ return mCanvas->quickReject(bounds);
+}
+
+bool SkiaCanvas::quickRejectPath(const SkPath& path) const {
+ return mCanvas->quickReject(path);
+}
+
+bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+ SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+ mCanvas->clipRect(rect, op);
+ return mCanvas->isClipEmpty();
+}
+
+bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
+ mCanvas->clipPath(*path, op);
+ return mCanvas->isClipEmpty();
+}
+
+bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
+ SkPath rgnPath;
+ if (region->getBoundaryPath(&rgnPath)) {
+ // The region is specified in device space.
+ SkMatrix savedMatrix = mCanvas->getTotalMatrix();
+ mCanvas->resetMatrix();
+ mCanvas->clipPath(rgnPath, op);
+ mCanvas->setMatrix(savedMatrix);
+ } else {
+ mCanvas->clipRect(SkRect::MakeEmpty(), op);
+ }
+ return mCanvas->isClipEmpty();
+}
+
+// ----------------------------------------------------------------------------
+// Canvas state operations: Filters
+// ----------------------------------------------------------------------------
+
+void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) {
+ mCanvas->setDrawFilter(drawFilter);
+}
+
+// ----------------------------------------------------------------------------
+// Canvas draw operations
+// ----------------------------------------------------------------------------
+
+void SkiaCanvas::drawColor(int color, SkXfermode::Mode mode) {
+ mCanvas->drawColor(color, mode);
+}
+
+void SkiaCanvas::drawPaint(const SkPaint& paint) {
+ mCanvas->drawPaint(paint);
+}
+
+// ----------------------------------------------------------------------------
+// Canvas draw operations: Geometry
+// ----------------------------------------------------------------------------
+
+void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint,
+ SkCanvas::PointMode mode) {
+ // convert the floats into SkPoints
+ count >>= 1; // now it is the number of points
+ SkAutoSTMalloc<32, SkPoint> storage(count);
+ SkPoint* pts = storage.get();
+ for (int i = 0; i < count; i++) {
+ pts[i].set(points[0], points[1]);
+ points += 2;
+ }
+ mCanvas->drawPoints(mode, count, pts, paint);
+}
+
+
+void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
+ mCanvas->drawPoint(x, y, paint);
+}
+
+void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
+ this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode);
+}
+
+void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
+ const SkPaint& paint) {
+ mCanvas->drawLine(startX, startY, stopX, stopY, paint);
+}
+
+void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
+ this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
+}
+
+void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
+ const SkPaint& paint) {
+ mCanvas->drawRectCoords(left, top, right, bottom, paint);
+
+}
+
+void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
+ float rx, float ry, const SkPaint& paint) {
+ SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+ mCanvas->drawRoundRect(rect, rx, ry, paint);
+}
+
+void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
+ mCanvas->drawCircle(x, y, radius, paint);
+}
+
+void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
+ SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
+ mCanvas->drawOval(oval, paint);
+}
+
+void SkiaCanvas::drawArc(float left, float top, float right, float bottom,
+ float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
+ SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
+ mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
+}
+
+void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+ mCanvas->drawPath(path, paint);
+}
+
+void SkiaCanvas::drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
+ const float* verts, const float* texs, const int* colors,
+ const uint16_t* indices, int indexCount, const SkPaint& paint) {
+#ifndef SK_SCALAR_IS_FLOAT
+ SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
+#endif
+ const int ptCount = vertexCount >> 1;
+ mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs,
+ (SkColor*)colors, NULL, indices, indexCount, paint);
+}
+
+// ----------------------------------------------------------------------------
+// Canvas draw operations: Bitmaps
+// ----------------------------------------------------------------------------
+
+void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
+ mCanvas->drawBitmap(bitmap, left, top, paint);
+}
+
+void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
+ mCanvas->drawBitmapMatrix(bitmap, matrix, paint);
+}
+
+void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
+ float srcRight, float srcBottom, float dstLeft, float dstTop,
+ float dstRight, float dstBottom, const SkPaint* paint) {
+ SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
+ SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
+ mCanvas->drawBitmapRectToRect(bitmap, &srcRect, dstRect, paint);
+}
+
+void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
+ const float* vertices, const int* colors, const SkPaint* paint) {
+
+ const int ptCount = (meshWidth + 1) * (meshHeight + 1);
+ const int indexCount = meshWidth * meshHeight * 6;
+
+ /* Our temp storage holds 2 or 3 arrays.
+ texture points [ptCount * sizeof(SkPoint)]
+ optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
+ copy to convert from float to fixed
+ indices [ptCount * sizeof(uint16_t)]
+ */
+ ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
+ storageSize += indexCount * sizeof(uint16_t); // indices[]
+
+
+#ifndef SK_SCALAR_IS_FLOAT
+ SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
+#endif
+ SkAutoMalloc storage(storageSize);
+ SkPoint* texs = (SkPoint*)storage.get();
+ uint16_t* indices = (uint16_t*)(texs + ptCount);
+
+ // cons up texture coordinates and indices
+ {
+ const SkScalar w = SkIntToScalar(bitmap.width());
+ const SkScalar h = SkIntToScalar(bitmap.height());
+ const SkScalar dx = w / meshWidth;
+ const SkScalar dy = h / meshHeight;
+
+ SkPoint* texsPtr = texs;
+ SkScalar y = 0;
+ for (int i = 0; i <= meshHeight; i++) {
+ if (i == meshHeight) {
+ y = h; // to ensure numerically we hit h exactly
+ }
+ SkScalar x = 0;
+ for (int j = 0; j < meshWidth; j++) {
+ texsPtr->set(x, y);
+ texsPtr += 1;
+ x += dx;
+ }
+ texsPtr->set(w, y);
+ texsPtr += 1;
+ y += dy;
+ }
+ SkASSERT(texsPtr - texs == ptCount);
+ }
+
+ // cons up indices
+ {
+ uint16_t* indexPtr = indices;
+ int index = 0;
+ for (int i = 0; i < meshHeight; i++) {
+ for (int j = 0; j < meshWidth; j++) {
+ // lower-left triangle
+ *indexPtr++ = index;
+ *indexPtr++ = index + meshWidth + 1;
+ *indexPtr++ = index + meshWidth + 2;
+ // upper-right triangle
+ *indexPtr++ = index;
+ *indexPtr++ = index + meshWidth + 2;
+ *indexPtr++ = index + 1;
+ // bump to the next cell
+ index += 1;
+ }
+ // bump to the next row
+ index += 1;
+ }
+ SkASSERT(indexPtr - indices == indexCount);
+ SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
+ }
+
+ // double-check that we have legal indices
+#ifdef SK_DEBUG
+ {
+ for (int i = 0; i < indexCount; i++) {
+ SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
+ }
+ }
+#endif
+
+ // cons-up a shader for the bitmap
+ SkPaint tmpPaint;
+ if (paint) {
+ tmpPaint = *paint;
+ }
+ SkShader* shader = SkShader::CreateBitmapShader(bitmap,
+ SkShader::kClamp_TileMode,
+ SkShader::kClamp_TileMode);
+ SkSafeUnref(tmpPaint.setShader(shader));
+
+ mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices,
+ texs, (const SkColor*)colors, NULL, indices,
+ indexCount, tmpPaint);
+}
+
+// ----------------------------------------------------------------------------
+// Canvas draw operations: Text
+// ----------------------------------------------------------------------------
+
+class DrawTextFunctor {
+public:
+ DrawTextFunctor(const Layout& layout, SkCanvas* canvas, float x, float y, SkPaint* paint,
+ uint16_t* glyphs, SkPoint* pos)
+ : layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
+ pos(pos) { }
+
+ void operator()(size_t start, size_t end) {
+ for (size_t i = start; i < end; i++) {
+ glyphs[i] = layout.getGlyphId(i);
+ pos[i].fX = x + layout.getX(i);
+ pos[i].fY = y + layout.getY(i);
+ }
+ canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
+ }
+private:
+ const Layout& layout;
+ SkCanvas* canvas;
+ float x;
+ float y;
+ SkPaint* paint;
+ uint16_t* glyphs;
+ SkPoint* pos;
+};
+
+void SkiaCanvas::drawText(const char* text, int start, int count, int contextCount,
+ float x, float y, int bidiFlags, const SkPaint& paint, TypefaceImpl* typeface) {
+ Layout layout;
+ std::string css = MinikinUtils::setLayoutProperties(&layout, &paint, bidiFlags, typeface);
+ layout.doLayout((uint16_t*)text, start, count, contextCount, css);
+
+ size_t nGlyphs = layout.nGlyphs();
+ uint16_t* glyphs = new uint16_t[nGlyphs];
+ SkPoint* pos = new SkPoint[nGlyphs];
+
+ SkPaint paintCopy(paint);
+ x += MinikinUtils::xOffsetForTextAlign(&paintCopy, layout);
+ paintCopy.setTextAlign(SkPaint::kLeft_Align);
+ paintCopy.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+
+ DrawTextFunctor f(layout, mCanvas, x, y, &paintCopy, glyphs, pos);
+ MinikinUtils::forFontRun(layout, &paintCopy, f);
+ drawTextDecorations(x, y, layout.getAdvance(), paintCopy);
+
+ delete[] glyphs;
+ delete[] pos;
+}
+
+// Same values used by Skia
+#define kStdStrikeThru_Offset (-6.0f / 21.0f)
+#define kStdUnderline_Offset (1.0f / 9.0f)
+#define kStdUnderline_Thickness (1.0f / 18.0f)
+
+void SkiaCanvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
+ uint32_t flags;
+ SkDrawFilter* drawFilter = mCanvas->getDrawFilter();
+ if (drawFilter) {
+ SkPaint paintCopy(paint);
+ drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
+ flags = paintCopy.getFlags();
+ } else {
+ flags = paint.getFlags();
+ }
+ if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+ SkScalar left = x;
+ SkScalar right = x + length;
+ float textSize = paint.getTextSize();
+ float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
+ if (flags & SkPaint::kUnderlineText_Flag) {
+ SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
+ SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
+ mCanvas->drawRectCoords(left, top, right, bottom, paint);
+ }
+ if (flags & SkPaint::kStrikeThruText_Flag) {
+ SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
+ SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
+ mCanvas->drawRectCoords(left, top, right, bottom, paint);
+ }
+ }
+}
+
+void SkiaCanvas::drawPosText(const char* text, const float* positions, int count, int posCount,
+ const SkPaint& paint) {
+ SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
+ int indx;
+ for (indx = 0; indx < posCount; indx++) {
+ posPtr[indx].fX = positions[indx << 1];
+ posPtr[indx].fY = positions[(indx << 1) + 1];
+ }
+
+ SkPaint paintCopy(paint);
+ paintCopy.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ mCanvas->drawPosText(text, count, posPtr, paintCopy);
+
+ delete[] posPtr;
+}
+
+void SkiaCanvas::drawTextOnPath(const char* text, int count, const SkPath& path,
+ float hOffset, float vOffset, const SkPaint& paint) {
+ mCanvas->drawTextOnPathHV(text, count, path, hOffset, vOffset, paint);
+}
+
+} // namespace android
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index 3812c27..9436a47 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -19,9 +19,9 @@
#include <android_runtime/AndroidRuntime.h>
#include <vector>
+#include "Canvas.h"
#include "CreateJavaOutputStreamAdaptor.h"
-#include "SkCanvas.h"
#include "SkDocument.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
@@ -132,8 +132,9 @@
jint pageWidth, jint pageHeight,
jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
- return reinterpret_cast<jlong>(document->startPage(pageWidth, pageHeight,
- contentLeft, contentTop, contentRight, contentBottom));
+ SkCanvas* canvas = document->startPage(pageWidth, pageHeight,
+ contentLeft, contentTop, contentRight, contentBottom);
+ return reinterpret_cast<jlong>(Canvas::create_canvas(canvas));
}
static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
new file mode 100644
index 0000000..fd96a90
--- /dev/null
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -0,0 +1,653 @@
+/*
+ * 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.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "Canvas.h"
+#include "SkGraphics.h"
+#include "SkPorterDuff.h"
+#include "TypefaceImpl.h"
+
+#include <minikin/Layout.h>
+#include "MinikinSkia.h"
+#include "MinikinUtils.h"
+
+namespace android {
+
+namespace CanvasJNI {
+
+static Canvas* get_canvas(jlong canvasHandle) {
+ return reinterpret_cast<Canvas*>(canvasHandle);
+}
+
+static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
+ delete get_canvas(canvasHandle);
+}
+
+// Native wrapper constructor used by Canvas(Bitmap)
+static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
+}
+
+// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
+// optionally copying canvas matrix & clip state.
+static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
+ jboolean copyState) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ get_canvas(canvasHandle)->setBitmap(bitmap, copyState);
+}
+
+static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
+ return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
+}
+
+static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
+ return static_cast<jint>(get_canvas(canvasHandle)->width());
+}
+
+static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
+ return static_cast<jint>(get_canvas(canvasHandle)->height());
+}
+
+static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
+ return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
+}
+
+static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
+ return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
+}
+
+static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
+ jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
+ return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
+}
+
+static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
+ jfloat r, jfloat b, jint alpha, jint flagsHandle) {
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
+ return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
+}
+
+static void restore(JNIEnv* env, jobject, jlong canvasHandle) {
+ Canvas* canvas = get_canvas(canvasHandle);
+ if (canvas->getSaveCount() <= 1) { // cannot restore anymore
+ doThrowISE(env, "Underflow in restore");
+ return;
+ }
+ canvas->restore();
+}
+
+static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount) {
+ Canvas* canvas = get_canvas(canvasHandle);
+ if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
+ doThrowIAE(env, "Underflow in restoreToCount");
+ return;
+ }
+ canvas->restoreToCount(restoreCount);
+}
+
+static void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
+ SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ get_canvas(canvasHandle)->getMatrix(matrix);
+}
+
+static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
+ const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
+}
+
+static void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
+ const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ get_canvas(canvasHandle)->concat(*matrix);
+}
+
+static void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
+ get_canvas(canvasHandle)->rotate(degrees);
+}
+
+static void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
+ get_canvas(canvasHandle)->scale(sx, sy);
+}
+
+static void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
+ get_canvas(canvasHandle)->skew(sx, sy);
+}
+
+static void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
+ get_canvas(canvasHandle)->translate(dx, dy);
+}
+
+static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
+ SkRect r;
+ SkIRect ir;
+ bool result = get_canvas(canvasHandle)->getClipBounds(&r);
+
+ if (!result) {
+ r.setEmpty();
+ }
+ r.round(&ir);
+
+ (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
+ return result ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat left, jfloat top, jfloat right, jfloat bottom) {
+ bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
+ return result ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
+ SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
+ return result ? JNI_TRUE : JNI_FALSE;
+}
+
+static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
+ jfloat r, jfloat b, jint opHandle) {
+ SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
+ bool emptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
+ return emptyClip ? JNI_FALSE : JNI_TRUE;
+}
+
+static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
+ jint opHandle) {
+ SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
+ bool emptyClip = get_canvas(canvasHandle)->clipPath(path, op);
+ return emptyClip ? JNI_FALSE : JNI_TRUE;
+}
+
+static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
+ jint opHandle) {
+ SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
+ SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
+ bool emptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
+ return emptyClip ? JNI_FALSE : JNI_TRUE;
+}
+
+static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
+ SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
+ get_canvas(canvasHandle)->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
+}
+
+static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawPaint(*paint);
+}
+
+static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
+ jlong paintHandle) {
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawPoint(x, y, *paint);
+}
+
+static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
+ jint offset, jint count, jlong paintHandle) {
+ NPE_CHECK_RETURN_VOID(env, jptsArray);
+ AutoJavaFloatArray autoPts(env, jptsArray);
+ float* floats = autoPts.ptr();
+ const int length = autoPts.length();
+
+ if ((offset | count) < 0 || offset + count > length) {
+ doThrowAIOOBE(env);
+ return;
+ }
+
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
+}
+
+static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
+ jfloat stopX, jfloat stopY, jlong paintHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
+}
+
+static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
+ jint offset, jint count, jlong paintHandle) {
+ NPE_CHECK_RETURN_VOID(env, jptsArray);
+ AutoJavaFloatArray autoPts(env, jptsArray);
+ float* floats = autoPts.ptr();
+ const int length = autoPts.length();
+
+ if ((offset | count) < 0 || offset + count > length) {
+ doThrowAIOOBE(env);
+ return;
+ }
+
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
+}
+
+static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jlong paintHandle) {
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
+}
+
+static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
+}
+
+static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
+ jfloat radius, jlong paintHandle) {
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
+}
+
+static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jlong paintHandle) {
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
+}
+
+static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
+ jboolean useCenter, jlong paintHandle) {
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
+ useCenter, *paint);
+}
+
+static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
+ jlong paintHandle) {
+ const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawPath(*path, *paint);
+}
+
+static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
+ jint modeHandle, jint vertexCount,
+ jfloatArray jverts, jint vertIndex,
+ jfloatArray jtexs, jint texIndex,
+ jintArray jcolors, jint colorIndex,
+ jshortArray jindices, jint indexIndex,
+ jint indexCount, jlong paintHandle) {
+ AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
+ AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
+ AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
+ AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
+
+ const float* verts = vertA.ptr() + vertIndex;
+ const float* texs = texA.ptr() + vertIndex;
+ const int* colors = NULL;
+ const uint16_t* indices = NULL;
+
+ if (jcolors != NULL) {
+ colors = colorA.ptr() + colorIndex;
+ }
+ if (jindices != NULL) {
+ indices = (const uint16_t*)(indexA.ptr() + indexIndex);
+ }
+
+ SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
+ indices, indexCount, *paint);
+}
+
+static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jlong bitmapHandle,
+ jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
+ jint screenDensity, jint bitmapDensity) {
+ Canvas* canvas = get_canvas(canvasHandle);
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+
+ if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
+ if (screenDensity != 0 && screenDensity != bitmapDensity) {
+ SkPaint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+ canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
+ } else {
+ canvas->drawBitmap(*bitmap, left, top, paint);
+ }
+ } else {
+ canvas->save(SkCanvas::kMatrixClip_SaveFlag);
+ SkScalar scale = canvasDensity / (float)bitmapDensity;
+ canvas->translate(left, top);
+ canvas->scale(scale, scale);
+
+ SkPaint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+
+ canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
+ canvas->restore();
+ }
+}
+
+static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
+ jlong matrixHandle, jlong paintHandle) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawBitmap(*bitmap, *matrix, paint);
+}
+
+static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
+ float srcLeft, float srcTop, float srcRight, float srcBottom,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ jlong paintHandle, jint screenDensity, jint bitmapDensity) {
+ Canvas* canvas = get_canvas(canvasHandle);
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+
+ if (screenDensity != 0 && screenDensity != bitmapDensity) {
+ SkPaint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+ canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
+ dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
+ } else {
+ canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
+ dstLeft, dstTop, dstRight, dstBottom, paint);
+ }
+}
+
+static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
+ jintArray jcolors, jint offset, jint stride,
+ jfloat x, jfloat y, jint width, jint height,
+ jboolean hasAlpha, jlong paintHandle) {
+ // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
+ // correct the alphaType to kOpaque_SkAlphaType.
+ SkImageInfo info = SkImageInfo::Make(width, height,
+ hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
+ kPremul_SkAlphaType);
+ SkBitmap bitmap;
+ if (!bitmap.allocPixels(info)) {
+ return;
+ }
+
+ if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
+ return;
+ }
+
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
+}
+
+static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
+ jint meshWidth, jint meshHeight, jfloatArray jverts,
+ jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
+ const int ptCount = (meshWidth + 1) * (meshHeight + 1);
+ AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
+ AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
+
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ get_canvas(canvasHandle)->drawBitmapMesh(*bitmap, meshWidth, meshHeight,
+ vertA.ptr(), colorA.ptr(), paint);
+}
+
+static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
+ jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
+ jlong paintHandle, jlong typefaceHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ jchar* jchars = env->GetCharArrayElements(text, NULL);
+ const char* textArray = reinterpret_cast<const char*>(jchars) + index;
+ get_canvas(canvasHandle)->drawText(textArray, 0, count, count, x, y, bidiFlags, *paint, typeface);
+ env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
+}
+
+static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
+ jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
+ jlong paintHandle, jlong typefaceHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ const int count = end - start;
+ const jchar* jchars = env->GetStringChars(text, NULL);
+ const char* textArray = reinterpret_cast<const char*>(jchars) + start;
+ get_canvas(canvasHandle)->drawText(textArray, 0, count, count, x, y, bidiFlags, *paint, typeface);
+ env->ReleaseStringChars(text, jchars);
+}
+
+static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
+ jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
+ jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
+ const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
+ jchar* jchars = env->GetCharArrayElements(text, NULL);
+ const char* textArray = reinterpret_cast<const char*>(jchars) + contextIndex;
+ get_canvas(canvasHandle)->drawText(textArray, index - contextIndex, count, contextCount,
+ x, y, bidiFlags, *paint, typeface);
+ env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
+}
+
+static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
+ jint start, jint end, jint contextStart, jint contextEnd,
+ jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
+ jlong typefaceHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
+ int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
+ jint count = end - start;
+ jint contextCount = contextEnd - contextStart;
+ const jchar* jchars = env->GetStringChars(text, NULL);
+ const char* textArray = reinterpret_cast<const char*>(jchars) + contextStart;
+ get_canvas(canvasHandle)->drawText(textArray, start - contextStart, count, contextCount,
+ x, y, bidiFlags, *paint, typeface);
+ env->ReleaseStringChars(text, jchars);
+}
+
+static void drawPosTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
+ jint index, jint count, jfloatArray pos, jlong paintHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ jchar* jchars = text ? env->GetCharArrayElements(text, NULL) : NULL;
+ float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
+ int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
+
+ const char* textArray = reinterpret_cast<const char*>(jchars) + index;
+ get_canvas(canvasHandle)->drawPosText(textArray, posArray, count << 1, posCount, *paint);
+
+ if (text) {
+ env->ReleaseCharArrayElements(text, jchars, 0);
+ }
+ if (pos) {
+ env->ReleaseFloatArrayElements(pos, posArray, 0);
+ }
+}
+
+
+static void drawPosTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
+ jfloatArray pos, jlong paintHandle) {
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ const jchar* jchars = text ? env->GetStringChars(text, NULL) : NULL;
+ int byteLength = text ? env->GetStringLength(text) : 0;
+ float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
+ int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
+
+ const char* textArray = reinterpret_cast<const char*>(jchars);
+ get_canvas(canvasHandle)->drawPosText(textArray , posArray, byteLength << 1, posCount, *paint);
+
+ if (text) {
+ env->ReleaseStringChars(text, jchars);
+ }
+ if (pos) {
+ env->ReleaseFloatArrayElements(pos, posArray, 0);
+ }
+}
+
+class DrawTextOnPathFunctor {
+public:
+ DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
+ float vOffset, const SkPaint& paint, const SkPath& path)
+ : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
+ paint(paint), path(path) {
+ }
+ void operator()(size_t start, size_t end) {
+ uint16_t glyphs[1];
+ for (size_t i = start; i < end; i++) {
+ glyphs[0] = layout.getGlyphId(i);
+ float x = hOffset + layout.getX(i);
+ float y = vOffset + layout.getY(i);
+ canvas->drawTextOnPath((const char*) glyphs, 1, path, x, y, paint);
+ }
+ }
+private:
+ const Layout& layout;
+ Canvas* canvas;
+ float hOffset;
+ float vOffset;
+ const SkPaint& paint;
+ const SkPath& path;
+};
+
+static void drawTextOnPath(Canvas* canvas, const char* text, int count, int bidiFlags,
+ const SkPath& path, float hOffset, float vOffset,
+ const SkPaint& paint, TypefaceImpl* typeface) {
+ SkPaint paintCopy(paint);
+ Layout layout;
+ std::string css = MinikinUtils::setLayoutProperties(&layout, &paintCopy, bidiFlags, typeface);
+ layout.doLayout((uint16_t*)text, 0, count, count, css);
+ hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
+
+ // Set align to left for drawing, as we don't want individual
+ // glyphs centered or right-aligned; the offset above takes
+ // care of all alignment.
+ paintCopy.setTextAlign(SkPaint::kLeft_Align);
+
+ DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
+ MinikinUtils::forFontRun(layout, &paintCopy, f);
+}
+
+static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
+ jint index, jint count, jlong pathHandle, jfloat hOffset,
+ jfloat vOffset, jint bidiFlags, jlong paintHandle,
+ jlong typefaceHandle) {
+ SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
+ jchar* jchars = env->GetCharArrayElements(text, NULL);
+ const char* textArray = reinterpret_cast<const char*>(jchars);
+
+ drawTextOnPath(get_canvas(canvasHandle), textArray + index, count, bidiFlags, *path,
+ hOffset, vOffset, *paint, typeface);
+
+ env->ReleaseCharArrayElements(text, jchars, 0);
+}
+
+static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
+ jlong pathHandle, jfloat hOffset, jfloat vOffset,
+ jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
+ SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
+ const jchar* jchars = env->GetStringChars(text, NULL);
+ const char* textArray = reinterpret_cast<const char*>(jchars);
+ int count = env->GetStringLength(text);
+
+ drawTextOnPath(get_canvas(canvasHandle), textArray, count, bidiFlags, *path,
+ hOffset, vOffset, *paint, typeface);
+
+ env->ReleaseStringChars(text, jchars);
+}
+
+static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
+ get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
+}
+
+static void freeCaches(JNIEnv* env, jobject) {
+ SkGraphics::PurgeFontCache();
+}
+
+static void freeTextLayoutCaches(JNIEnv* env, jobject) {
+ Layout::purgeCaches();
+}
+
+}; // namespace CanvasJNI
+
+static JNINativeMethod gMethods[] = {
+ {"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
+ {"initRaster", "(J)J", (void*) CanvasJNI::initRaster},
+ {"native_setBitmap", "(JJZ)V", (void*) CanvasJNI::setBitmap},
+ {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
+ {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
+ {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
+ {"native_save","(JI)I", (void*) CanvasJNI::save},
+ {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
+ {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
+ {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
+ {"native_restore","(J)V", (void*) CanvasJNI::restore},
+ {"native_restoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
+ {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
+ {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
+ {"native_concat","(JJ)V", (void*) CanvasJNI::concat},
+ {"native_rotate","(JF)V", (void*) CanvasJNI::rotate},
+ {"native_scale","(JFF)V", (void*) CanvasJNI::scale},
+ {"native_skew","(JFF)V", (void*) CanvasJNI::skew},
+ {"native_translate","(JFF)V", (void*) CanvasJNI::translate},
+ {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
+ {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
+ {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
+ {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
+ {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
+ {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
+ {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor},
+ {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
+ {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
+ {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
+ {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
+ {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
+ {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
+ {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
+ {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
+ {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
+ {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
+ {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
+ {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
+ {"native_drawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap},
+ {"nativeDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
+ {"native_drawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
+ {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
+ {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
+ {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
+ {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
+ {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
+ {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
+ {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
+ {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
+ {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
+ {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
+ {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
+};
+
+int register_android_graphics_Canvas(JNIEnv* env) {
+ return AndroidRuntime::registerNativeMethods(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp
index f827907..eb8f6dd 100644
--- a/core/jni/android_graphics_Picture.cpp
+++ b/core/jni/android_graphics_Picture.cpp
@@ -51,7 +51,7 @@
static void android_graphics_Picture_draw(JNIEnv* env, jobject, jlong canvasHandle,
jlong pictureHandle) {
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
+ Canvas* canvas = reinterpret_cast<Canvas*>(canvasHandle);
Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
SkASSERT(canvas);
SkASSERT(picture);
@@ -84,12 +84,7 @@
static jlong android_graphics_Picture_beginRecording(JNIEnv* env, jobject, jlong pictHandle,
jint w, jint h) {
Picture* pict = reinterpret_cast<Picture*>(pictHandle);
- // beginRecording does not ref its return value, it just returns it.
- SkCanvas* canvas = pict->beginRecording(w, h);
- // the java side will wrap this guy in a Canvas.java, which will call
- // unref in its finalizer, so we have to ref it here, so that both that
- // Canvas.java and our picture can both be owners
- canvas->ref();
+ Canvas* canvas = pict->beginRecording(w, h);
return reinterpret_cast<jlong>(canvas);
}
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 9621bb2..d2f5b5d 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -19,17 +19,20 @@
#include <utils/Log.h>
#include <utils/Errors.h>
#include <utils/Trace.h>
+#include <camera/CameraUtils.h>
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/android_view_Surface.h"
+#include "android_runtime/android_graphics_SurfaceTexture.h"
#include <gui/Surface.h>
#include <gui/IGraphicBufferProducer.h>
#include <ui/GraphicBuffer.h>
#include <system/window.h>
#include <hardware/camera3.h>
+#include <system/camera_metadata.h>
#include <stdint.h>
#include <inttypes.h>
@@ -335,6 +338,25 @@
return anw;
}
+static sp<ANativeWindow> getNativeWindowFromTexture(JNIEnv* env, jobject surfaceTexture) {
+ sp<ANativeWindow> anw;
+ if (surfaceTexture) {
+ anw = android_SurfaceTexture_getNativeWindow(env, surfaceTexture);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+ } else {
+ jniThrowNullPointerException(env, "surfaceTexture");
+ return NULL;
+ }
+ if (anw == NULL) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "SurfaceTexture had no valid native window.");
+ return NULL;
+ }
+ return anw;
+}
+
static sp<Surface> getSurface(JNIEnv* env, jobject surface) {
sp<Surface> s;
if (surface) {
@@ -376,6 +398,17 @@
static jint LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
jobject surface, jintArray dimens) {
ALOGV("nativeGetSurfaceDimens");
+
+ if (dimens == NULL) {
+ ALOGE("%s: Null dimens argument passed to nativeDetectSurfaceDimens", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (env->GetArrayLength(dimens) < 2) {
+ ALOGE("%s: Invalid length of dimens argument in nativeDetectSurfaceDimens", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
sp<ANativeWindow> anw;
if ((anw = getNativeWindow(env, surface)) == NULL) {
ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
@@ -398,6 +431,37 @@
return NO_ERROR;
}
+static jint LegacyCameraDevice_nativeDetectTextureDimens(JNIEnv* env, jobject thiz,
+ jobject surfaceTexture, jintArray dimens) {
+ ALOGV("nativeDetectTextureDimens");
+ sp<ANativeWindow> anw;
+ if ((anw = getNativeWindowFromTexture(env, surfaceTexture)) == NULL) {
+ ALOGE("%s: Could not retrieve native window from SurfaceTexture.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ int32_t dimenBuf[2];
+ status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
+ if(err != NO_ERROR) {
+ ALOGE("%s: Error while querying SurfaceTexture width %s (%d)", __FUNCTION__,
+ strerror(-err), err);
+ return err;
+ }
+
+ err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
+ if(err != NO_ERROR) {
+ ALOGE("%s: Error while querying SurfaceTexture height %s (%d)", __FUNCTION__,
+ strerror(-err), err);
+ return err;
+ }
+
+ env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
+ if (env->ExceptionCheck()) {
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
static jint LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
jint width, jint height, jint pixelFormat) {
ALOGV("nativeConfigureSurface");
@@ -504,6 +568,42 @@
return reinterpret_cast<jlong>(b.get());
}
+static jint LegacyCameraDevice_nativeSetSurfaceOrientation(JNIEnv* env, jobject thiz,
+ jobject surface, jint facing, jint orientation) {
+ ALOGV("nativeSetSurfaceOrientation");
+ sp<ANativeWindow> anw;
+ if ((anw = getNativeWindow(env, surface)) == NULL) {
+ ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ status_t err = NO_ERROR;
+ CameraMetadata staticMetadata;
+
+ int32_t orientVal = static_cast<int32_t>(orientation);
+ uint8_t facingVal = static_cast<uint8_t>(facing);
+ staticMetadata.update(ANDROID_SENSOR_ORIENTATION, &orientVal, 1);
+ staticMetadata.update(ANDROID_LENS_FACING, &facingVal, 1);
+
+ int32_t transform = 0;
+
+ if ((err = CameraUtils::getRotationTransform(staticMetadata, /*out*/&transform)) != OK) {
+ ALOGE("%s: Invalid rotation transform %s (%d)", __FUNCTION__, strerror(-err),
+ err);
+ return err;
+ }
+
+ ALOGV("%s: Setting buffer sticky transform to %d", __FUNCTION__, transform);
+
+ if ((err = native_window_set_buffers_sticky_transform(anw.get(), transform)) != OK) {
+ ALOGE("%s: Unable to configure surface transform, error %s (%d)", __FUNCTION__,
+ strerror(-err), err);
+ return err;
+ }
+
+ return NO_ERROR;
+}
+
} // extern "C"
static JNINativeMethod gCameraDeviceMethods[] = {
@@ -528,6 +628,12 @@
{ "nativeGetSurfaceId",
"(Landroid/view/Surface;)J",
(void *)LegacyCameraDevice_nativeGetSurfaceId },
+ { "nativeDetectTextureDimens",
+ "(Landroid/graphics/SurfaceTexture;[I)I",
+ (void *)LegacyCameraDevice_nativeDetectTextureDimens },
+ { "nativeSetSurfaceOrientation",
+ "(Landroid/view/Surface;II)I",
+ (void *)LegacyCameraDevice_nativeSetSurfaceOrientation },
};
// Get all the required offsets in java class and register native functions
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index c352398..8641e73 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -100,6 +100,12 @@
renderer->setViewport(width, height);
}
+static void android_view_GLES20Canvas_setHighContrastText(JNIEnv* env, jobject clazz,
+ jlong rendererPtr, jboolean highContrastText) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+ renderer->setHighContrastText(highContrastText);
+}
+
static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
jlong rendererPtr, jboolean opaque) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
@@ -842,6 +848,7 @@
{ "nDestroyRenderer", "(J)V", (void*) android_view_GLES20Canvas_destroyRenderer },
{ "nSetViewport", "(JII)V", (void*) android_view_GLES20Canvas_setViewport },
+ { "nSetHighContrastText","(JZ)V", (void*) android_view_GLES20Canvas_setHighContrastText },
{ "nPrepare", "(JZ)I", (void*) android_view_GLES20Canvas_prepare },
{ "nPrepareDirty", "(JIIIIZ)I", (void*) android_view_GLES20Canvas_prepareDirty },
{ "nFinish", "(J)V", (void*) android_view_GLES20Canvas_finish },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index aab48b3..988d461 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -138,13 +138,6 @@
}
}
-protected:
- virtual void damageSelf(TreeInfo& info) {
- // Intentionally a no-op. As RootRenderNode gets a new DisplayListData
- // every frame this would result in every draw push being a full inval,
- // which is wrong. Only RootRenderNode has this issue.
- }
-
private:
sp<Looper> mLooper;
std::vector<OnFinishedEvent> mOnFinishedEvents;
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 989b60ee..1f7acec 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -39,6 +39,7 @@
#include <cutils/fs.h>
#include <cutils/multiuser.h>
#include <cutils/sched_policy.h>
+#include <private/android_filesystem_config.h>
#include <utils/String8.h>
#include <selinux/android.h>
#include <processgroup/processgroup.h>
@@ -439,8 +440,11 @@
if (!is_system_server) {
int rc = createProcessGroup(uid, getpid());
if (rc != 0) {
- ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
- RuntimeAbort(env);
+ if (rc == -EROFS) {
+ ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
+ } else {
+ ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
+ }
}
}
@@ -533,8 +537,15 @@
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
jintArray fdsToClose) {
+ // Grant CAP_WAKE_ALARM to the Bluetooth process.
+ jlong capabilities = 0;
+ if (uid == AID_BLUETOOTH) {
+ capabilities |= (1LL << CAP_WAKE_ALARM);
+ }
+
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
- rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose);
+ rlimits, capabilities, capabilities, mount_external, se_info,
+ se_name, false, fdsToClose);
}
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4725cfb..658ef96 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -235,6 +235,7 @@
<protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
<protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
<protected-broadcast android:name="android.net.wifi.WIFI_SCAN_AVAILABLE" />
<protected-broadcast android:name="android.net.wifi.SCAN_RESULTS" />
<protected-broadcast android:name="android.net.wifi.RSSI_CHANGED" />
@@ -805,6 +806,19 @@
android:description="@string/permdesc_changeWifiState"
android:label="@string/permlab_changeWifiState" />
+ <!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.READ_WIFI_CREDENTIAL"
+ android:permissionGroup="android.permission-group.NETWORK"
+ android:protectionLevel="signature|system" />
+
+ <!-- @SystemApi @hide Allow system apps to receive broadcast
+ when a wifi network credential is changed.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE"
+ android:permissionGroup="android.permission-group.NETWORK"
+ android:protectionLevel="signature|system" />
+
<!-- @hide -->
<permission android:name="android.permission.ACCESS_WIMAX_STATE"
android:permissionGroup="android.permission-group.NETWORK"
@@ -819,7 +833,7 @@
android:description="@string/permdesc_changeWimaxState"
android:label="@string/permlab_changeWimaxState" />
- <!-- Allows applications to act as network scorers. @hide -->
+ <!-- Allows applications to act as network scorers. @hide @SystemApi-->
<permission android:name="android.permission.SCORE_NETWORKS"
android:permissionGroup="android.permission-group.NETWORK"
android:protectionLevel="normal"
@@ -2149,7 +2163,7 @@
android:description="@string/permdesc_bindTvInput"
android:protectionLevel="signature|system" />
- <!-- Must be required by a {@link android.media.routeprovider.RouteProviderService}
+ <!-- Must be required by a {@link android.media.routing.MediaRouteService}
to ensure that only the system can interact with it.
@hide -->
<permission android:name="android.permission.BIND_ROUTE_PROVIDER"
@@ -2720,6 +2734,13 @@
android:description="@string/permdesc_bindConditionProviderService"
android:protectionLevel="signature" />
+ <!-- Must be required by a {@link android.media.routing.MediaRouteService},
+ to ensure that only the system can bind to it. -->
+ <permission android:name="android.permission.BIND_MEDIA_ROUTE_SERVICE"
+ android:label="@string/permlab_bindMediaRouteService"
+ android:description="@string/permdesc_bindMediaRouteService"
+ android:protectionLevel="signature" />
+
<!-- Must be required by an {@link android.service.dreams.DreamService},
to ensure that only the system can bind to it. -->
<permission android:name="android.permission.BIND_DREAM_SERVICE"
diff --git a/core/res/res/anim/launch_task_behind_background.xml b/core/res/res/anim/launch_task_behind_background.xml
new file mode 100644
index 0000000..358511f
--- /dev/null
+++ b/core/res/res/anim/launch_task_behind_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="top">
+
+ <translate android:fromYDelta="110%" android:toYDelta="66%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_quint"
+ android:startOffset="50"
+ android:duration="300" />
+
+ <translate android:fromYDelta="0%" android:toYDelta="167%"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@interpolator/accelerate_quint"
+ android:startOffset="433"
+ android:duration="300" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/launch_task_behind_source.xml b/core/res/res/anim/launch_task_behind_source.xml
new file mode 100644
index 0000000..426ee5d
--- /dev/null
+++ b/core/res/res/anim/launch_task_behind_source.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/accelerate_cubic"
+ android:duration="133"/>
+
+ <translate android:fromYDelta="0" android:toYDelta="10%"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@interpolator/accelerate_cubic"
+ android:duration="350"/>
+
+ <scale android:fromXScale="1.0" android:toXScale="0.9"
+ android:fromYScale="1.0" android:toYScale="0.9"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="350" />
+
+ <alpha android:fromAlpha="1.0" android:toAlpha="1.6"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:startOffset="433"
+ android:duration="133"/>
+
+ <translate android:fromYDelta="0%" android:toYDelta="-10%"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:startOffset="433"
+ android:duration="350"/>
+
+ <scale android:fromXScale="1.0" android:toXScale="1.1"
+ android:fromYScale="1.0" android:toYScale="1.1"
+ android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
+ android:pivotX="50%p" android:pivotY="50%p"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:startOffset="433"
+ android:duration="350" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_calendar_holo_dark.xml b/core/res/res/color/date_picker_calendar_holo_dark.xml
new file mode 100644
index 0000000..d29486f
--- /dev/null
+++ b/core/res/res/color/date_picker_calendar_holo_dark.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_enabled="true" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_holo_dark"/>
+ <item android:state_enabled="true" android:state_selected="true"
+ android:color="@color/holo_blue_light"/>
+ <item android:state_enabled="false"
+ android:color="@color/datepicker_default_disabled_text_color_holo_dark"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_calendar_holo_light.xml b/core/res/res/color/date_picker_calendar_holo_light.xml
new file mode 100644
index 0000000..776f39b
--- /dev/null
+++ b/core/res/res/color/date_picker_calendar_holo_light.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_enabled="true" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_holo_light"/>
+ <item android:state_enabled="true" android:state_selected="true"
+ android:color="@color/holo_blue_light"/>
+ <item android:state_enabled="false"
+ android:color="@color/datepicker_default_disabled_text_color_holo_light"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_calendar_material_dark.xml b/core/res/res/color/date_picker_calendar_material_dark.xml
new file mode 100644
index 0000000..86a0673
--- /dev/null
+++ b/core/res/res/color/date_picker_calendar_material_dark.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_enabled="true" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_material_dark"/>
+ <item android:state_enabled="true" android:state_selected="true"
+ android:color="@color/holo_blue_light"/>
+ <item android:state_enabled="false"
+ android:color="@color/datepicker_default_disabled_text_color_material_dark"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_calendar_material_light.xml b/core/res/res/color/date_picker_calendar_material_light.xml
new file mode 100644
index 0000000..015eed7
--- /dev/null
+++ b/core/res/res/color/date_picker_calendar_material_light.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_enabled="true" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_material_light"/>
+ <item android:state_enabled="true" android:state_selected="true"
+ android:color="@color/holo_blue_light"/>
+ <item android:state_enabled="false"
+ android:color="@color/datepicker_default_disabled_text_color_material_light"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_selector_holo_dark.xml b/core/res/res/color/date_picker_selector_holo_dark.xml
new file mode 100644
index 0000000..9e5a5bd
--- /dev/null
+++ b/core/res/res/color/date_picker_selector_holo_dark.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_pressed="true"
+ android:color="@color/datepicker_default_pressed_text_color_holo_dark"/>
+ <item android:state_pressed="false" android:state_selected="true"
+ android:color="@color/datepicker_default_selected_text_color_holo_dark"/>
+ <item android:state_pressed="false" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_holo_dark"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_selector_holo_light.xml b/core/res/res/color/date_picker_selector_holo_light.xml
new file mode 100644
index 0000000..bf8667c
--- /dev/null
+++ b/core/res/res/color/date_picker_selector_holo_light.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_pressed="true"
+ android:color="@color/datepicker_default_pressed_text_color_holo_light"/>
+ <item android:state_pressed="false" android:state_selected="true"
+ android:color="@color/datepicker_default_selected_text_color_holo_light"/>
+ <item android:state_pressed="false" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_holo_light"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_selector_material_dark.xml b/core/res/res/color/date_picker_selector_material_dark.xml
new file mode 100644
index 0000000..e407387
--- /dev/null
+++ b/core/res/res/color/date_picker_selector_material_dark.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_pressed="true"
+ android:color="@color/datepicker_default_pressed_text_color_material_dark"/>
+ <item android:state_pressed="false" android:state_selected="true"
+ android:color="@color/datepicker_default_selected_text_color_material_dark"/>
+ <item android:state_pressed="false" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_material_dark"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/color/date_picker_selector_material_light.xml b/core/res/res/color/date_picker_selector_material_light.xml
new file mode 100644
index 0000000..b4c6a47
--- /dev/null
+++ b/core/res/res/color/date_picker_selector_material_light.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_pressed="true"
+ android:color="@color/datepicker_default_pressed_text_color_material_light"/>
+ <item android:state_pressed="false" android:state_selected="true"
+ android:color="@color/datepicker_default_selected_text_color_material_light"/>
+ <item android:state_pressed="false" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_material_light"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/lock_task_notify_bg.xml b/core/res/res/color/date_picker_year_selector_holo_dark.xml
similarity index 64%
copy from core/res/res/drawable/lock_task_notify_bg.xml
copy to core/res/res/color/date_picker_year_selector_holo_dark.xml
index 3a8fab5..ce519b2 100644
--- a/core/res/res/drawable/lock_task_notify_bg.xml
+++ b/core/res/res/color/date_picker_year_selector_holo_dark.xml
@@ -13,10 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@android:color/black" />
- <corners
- android:radius="8dip" />
-</shape>
+ <item android:state_pressed="true"
+ android:color="@color/datepicker_default_pressed_text_color_holo_dark"/>
+ <item android:state_pressed="false" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_holo_dark"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/lock_task_notify_bg.xml b/core/res/res/color/date_picker_year_selector_holo_light.xml
similarity index 64%
copy from core/res/res/drawable/lock_task_notify_bg.xml
copy to core/res/res/color/date_picker_year_selector_holo_light.xml
index 3a8fab5..c228711 100644
--- a/core/res/res/drawable/lock_task_notify_bg.xml
+++ b/core/res/res/color/date_picker_year_selector_holo_light.xml
@@ -13,10 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@android:color/black" />
- <corners
- android:radius="8dip" />
-</shape>
+ <item android:state_pressed="true"
+ android:color="@color/datepicker_default_pressed_text_color_holo_light"/>
+ <item android:state_pressed="false" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_holo_light"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/lock_task_notify_bg.xml b/core/res/res/color/date_picker_year_selector_material_dark.xml
similarity index 64%
copy from core/res/res/drawable/lock_task_notify_bg.xml
copy to core/res/res/color/date_picker_year_selector_material_dark.xml
index 3a8fab5..b5ff09a 100644
--- a/core/res/res/drawable/lock_task_notify_bg.xml
+++ b/core/res/res/color/date_picker_year_selector_material_dark.xml
@@ -13,10 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@android:color/black" />
- <corners
- android:radius="8dip" />
-</shape>
+ <item android:state_pressed="true"
+ android:color="@color/datepicker_default_pressed_text_color_material_dark"/>
+ <item android:state_pressed="false" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_material_dark"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/lock_task_notify_bg.xml b/core/res/res/color/date_picker_year_selector_material_light.xml
similarity index 64%
copy from core/res/res/drawable/lock_task_notify_bg.xml
copy to core/res/res/color/date_picker_year_selector_material_light.xml
index 3a8fab5..5e329b3 100644
--- a/core/res/res/drawable/lock_task_notify_bg.xml
+++ b/core/res/res/color/date_picker_year_selector_material_light.xml
@@ -13,10 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="@android:color/black" />
- <corners
- android:radius="8dip" />
-</shape>
+ <item android:state_pressed="true"
+ android:color="@color/datepicker_default_pressed_text_color_material_light"/>
+ <item android:state_pressed="false" android:state_selected="false"
+ android:color="@color/datepicker_default_normal_text_color_material_light"/>
+
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable-hdpi/ic_recent.png b/core/res/res/drawable-hdpi/ic_recent.png
deleted file mode 100644
index 8866539..0000000
--- a/core/res/res/drawable-hdpi/ic_recent.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_disabled.png b/core/res/res/drawable-hdpi/stat_notify_disabled.png
deleted file mode 100644
index c5e5917..0000000
--- a/core/res/res/drawable-hdpi/stat_notify_disabled.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_recent.png b/core/res/res/drawable-mdpi/ic_recent.png
deleted file mode 100644
index 2b607df..0000000
--- a/core/res/res/drawable-mdpi/ic_recent.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_disabled.png b/core/res/res/drawable-mdpi/stat_notify_disabled.png
deleted file mode 100644
index c03277c..0000000
--- a/core/res/res/drawable-mdpi/stat_notify_disabled.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_recent.png b/core/res/res/drawable-xhdpi/ic_recent.png
deleted file mode 100644
index 86316db..0000000
--- a/core/res/res/drawable-xhdpi/ic_recent.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_disabled.png b/core/res/res/drawable-xhdpi/stat_notify_disabled.png
deleted file mode 100644
index a99f1f4..0000000
--- a/core/res/res/drawable-xhdpi/stat_notify_disabled.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_recent.png b/core/res/res/drawable-xxhdpi/ic_recent.png
deleted file mode 100644
index e6bd125..0000000
--- a/core/res/res/drawable-xxhdpi/ic_recent.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_disabled.png b/core/res/res/drawable-xxhdpi/stat_notify_disabled.png
deleted file mode 100644
index 06d7677b..0000000
--- a/core/res/res/drawable-xxhdpi/stat_notify_disabled.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/lock_task_notify_bg.xml b/core/res/res/drawable/background_leanback_setup.xml
similarity index 76%
rename from core/res/res/drawable/lock_task_notify_bg.xml
rename to core/res/res/drawable/background_leanback_setup.xml
index 3a8fab5..ca3392c 100644
--- a/core/res/res/drawable/lock_task_notify_bg.xml
+++ b/core/res/res/drawable/background_leanback_setup.xml
@@ -13,10 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
- <solid android:color="@android:color/black" />
- <corners
- android:radius="8dip" />
-</shape>
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
+ <item android:drawable="@color/black"/>
+</layer-list>
diff --git a/core/res/res/drawable/btn_check_material_anim.xml b/core/res/res/drawable/btn_check_material_anim.xml
index 73b8a3e..1e05e84 100644
--- a/core/res/res/drawable/btn_check_material_anim.xml
+++ b/core/res/res/drawable/btn_check_material_anim.xml
@@ -30,28 +30,28 @@
<transition android:fromId="@+id/off" android:toId="@+id/on">
<animation-list>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_on_mtrl_000" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_mtrl_000" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_on_mtrl_001" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_mtrl_001" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_on_mtrl_002" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_mtrl_002" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_on_mtrl_003" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_mtrl_003" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_on_mtrl_004" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_mtrl_004" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_on_mtrl_005" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_mtrl_005" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_on_mtrl_006" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_mtrl_006" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_on_mtrl_007" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_mtrl_007" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
<bitmap android:src="@drawable/btn_check_to_on_mtrl_008" android:tint="?attr/colorControlActivated" />
@@ -106,28 +106,28 @@
<bitmap android:src="@drawable/btn_check_to_off_mtrl_007" android:tint="?attr/colorControlActivated" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_off_mtrl_008" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_off_mtrl_008" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_off_mtrl_009" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_off_mtrl_009" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_off_mtrl_010" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_off_mtrl_010" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_off_mtrl_011" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_off_mtrl_011" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_off_mtrl_012" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_off_mtrl_012" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_off_mtrl_013" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_off_mtrl_013" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_off_mtrl_014" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_off_mtrl_014" android:tint="?attr/colorControlNormal" />
</item>
<item android:duration="15">
- <bitmap android:src="@drawable/btn_check_to_off_mtrl_015" android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_off_mtrl_015" android:tint="?attr/colorControlNormal" />
</item>
</animation-list>
</transition>
diff --git a/core/res/res/drawable/stat_notify_disabled_data.xml b/core/res/res/drawable/stat_notify_disabled_data.xml
new file mode 100644
index 0000000..d287a75
--- /dev/null
+++ b/core/res/res/drawable/stat_notify_disabled_data.xml
@@ -0,0 +1,37 @@
+<!--
+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" >
+ <size
+ android:width="24dp"
+ android:height="24dp"/>
+
+ <viewport
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0"/>
+
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M40.709,4.5l-6.604,7.337 0.0,16.601 6.604,6.604z"/>
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M32.305,13.838l-6.0629997,6.7370005 6.0629997,6.0629997z"/>
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M15.498,40.5l0.0,-7.9869995 -7.205,7.9869995z"/>
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M10.265,9.72l-2.5460005,2.545 9.971001,9.971 3.7139988,3.7140007 -4.105999,4.5619984 0.0,9.988001 6.6019993,0.0 0.0,-12.054001 1.8029995,1.8030014 0.0,10.250999 6.602001,0.0 0.0,-3.6479988 1.7999992,1.7999992 1.8479996,1.8479996 4.670002,4.669998 2.5459976,-2.5459976z"/>
+</vector>
diff --git a/core/res/res/layout-land/date_picker_holo.xml b/core/res/res/layout-land/date_picker_holo.xml
new file mode 100644
index 0000000..98e26ca
--- /dev/null
+++ b/core/res/res/layout-land/date_picker_holo.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/datepicker_view_animator_height"
+ android:gravity="center"
+ android:orientation="horizontal" >
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:background="?android:attr/datePickerHeaderSelectorBackgroundColor"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:orientation="vertical" >
+
+ <include layout="@layout/date_picker_header_view" />
+
+ <include layout="@layout/date_picker_selected_date" />
+ </LinearLayout>
+
+ <include layout="@layout/date_picker_done_button" />
+ </LinearLayout>
+
+ <include layout="@layout/date_picker_view_animator" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout-land/time_picker_holo.xml b/core/res/res/layout-land/time_picker_holo.xml
index f5ce1ec..1725ddc 100644
--- a/core/res/res/layout-land/time_picker_holo.xml
+++ b/core/res/res/layout-land/time_picker_holo.xml
@@ -33,8 +33,7 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dip"
- android:layout_weight="1"
- android:background="?android:attr/timePickerHeaderBackgroundColor">
+ android:layout_weight="1">
<include
layout="@layout/time_header_label"
android:layout_width="match_parent"
@@ -47,7 +46,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:background="?android:attr/timePickerHeaderBackgroundColor"
android:divider="?android:attr/dividerHorizontal"
android:showDividers="beginning">
<Button
diff --git a/core/res/res/layout-sw600dp/date_picker_holo.xml b/core/res/res/layout-sw600dp/date_picker_holo.xml
new file mode 100644
index 0000000..847aa32
--- /dev/null
+++ b/core/res/res/layout-sw600dp/date_picker_holo.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2011 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="match_parent"
+ android:background="@color/datepicker_default_view_animator_color_holo_light"
+ android:gravity="center"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/datepicker_selected_calendar_layout_height"
+ android:orientation="vertical" >
+
+ <include layout="@layout/date_picker_header_view" />
+
+ <include layout="@layout/date_picker_selected_date" />
+ </LinearLayout>
+
+ <include layout="@layout/date_picker_view_animator" />
+
+ <include layout="@layout/date_picker_done_button" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index 93acc3f..6a435b2 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -20,13 +20,7 @@
android:id="@+id/parentPanel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:background="@drawable/dialog_background_material"
- android:translationZ="@dimen/floating_window_z"
- android:layout_marginLeft="@dimen/floating_window_margin_left"
- android:layout_marginTop="@dimen/floating_window_margin_top"
- android:layout_marginRight="@dimen/floating_window_margin_right"
- android:layout_marginBottom="@dimen/floating_window_margin_bottom">
+ android:orientation="vertical">
<LinearLayout android:id="@+id/topPanel"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/date_picker_done_button.xml b/core/res/res/layout/date_picker_done_button.xml
new file mode 100644
index 0000000..b8e8c03
--- /dev/null
+++ b/core/res/res/layout/date_picker_done_button.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/layout_buttons"
+ style="?android:attr/buttonBarStyle"
+ android:layout_width="@dimen/datepicker_component_width"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:divider="?android:attr/dividerHorizontal"
+ android:showDividers="beginning" >
+
+ <Button
+ android:id="@+id/done"
+ style="?android:attr/buttonBarButtonStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="48dp"
+ android:text="@string/done_label"
+ android:textSize="@dimen/datepicker_done_label_size" />
+</LinearLayout>
diff --git a/core/res/res/layout/date_picker_header_view.xml b/core/res/res/layout/date_picker_header_view.xml
new file mode 100644
index 0000000..eccdd3e
--- /dev/null
+++ b/core/res/res/layout/date_picker_header_view.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 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.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/date_picker_header"
+ android:layout_width="@dimen/datepicker_component_width"
+ android:layout_height="@dimen/datepicker_header_height"
+ android:background="?android:attr/datePickerHeaderDayOfWeekLabelBackgroundColor"
+ android:gravity="center"
+ android:textAppearance="?android:attr/datePickerHeaderDayOfWeekLabelTextAppearance"
+ android:importantForAccessibility="no"
+ android:textAllCaps="true"
+ />
diff --git a/core/res/res/layout/date_picker_holo.xml b/core/res/res/layout/date_picker_holo.xml
index b465d97..389c2b5 100644
--- a/core/res/res/layout/date_picker_holo.xml
+++ b/core/res/res/layout/date_picker_holo.xml
@@ -1,92 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-**
-** Copyright 2011, 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.
-*/
--->
+ Copyright (C) 2011 The Android Open Source Project
-<!-- Layout of date picker-->
+ 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
-<!-- Warning: everything within the "pickers" layout is removed and re-ordered
- depending on the date format selected by the user.
+ 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:layout_gravity="center_horizontal"
- android:orientation="horizontal"
- android:gravity="center">
+ android:layout_width="@dimen/datepicker_component_width"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="vertical" >
- <LinearLayout android:id="@+id/pickers"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:gravity="center">
-
- <!-- Month -->
- <NumberPicker
- android:id="@+id/month"
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="16dip"
- android:layout_marginBottom="16dip"
- android:layout_marginStart="8dip"
- android:layout_marginEnd="8dip"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
+ android:orientation="vertical" >
- <!-- Day -->
- <NumberPicker
- android:id="@+id/day"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dip"
- android:layout_marginBottom="16dip"
- android:layout_marginStart="8dip"
- android:layout_marginEnd="8dip"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
+ <include layout="@layout/date_picker_header_view" />
- <!-- Year -->
- <NumberPicker
- android:id="@+id/year"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dip"
- android:layout_marginBottom="16dip"
- android:layout_marginStart="8dip"
- android:layout_marginEnd="16dip"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
-
+ <include layout="@layout/date_picker_selected_date" />
</LinearLayout>
- <!-- calendar view -->
- <CalendarView
- android:id="@+id/calendar_view"
- android:layout_width="245dip"
- android:layout_height="280dip"
- android:layout_marginStart="16dip"
- android:layout_marginEnd="16dip"
- android:layout_weight="1"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
+ <include layout="@layout/date_picker_view_animator" />
-</LinearLayout>
+ <include layout="@layout/date_picker_done_button" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker_legacy.xml
similarity index 100%
rename from core/res/res/layout/date_picker.xml
rename to core/res/res/layout/date_picker_legacy.xml
diff --git a/core/res/res/layout/date_picker_legacy_holo.xml b/core/res/res/layout/date_picker_legacy_holo.xml
new file mode 100644
index 0000000..b465d97
--- /dev/null
+++ b/core/res/res/layout/date_picker_legacy_holo.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2011, 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.
+*/
+-->
+
+<!-- Layout of date picker-->
+
+<!-- Warning: everything within the "pickers" layout is removed and re-ordered
+ depending on the date format selected by the user.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:orientation="horizontal"
+ android:gravity="center">
+
+ <LinearLayout android:id="@+id/pickers"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="center">
+
+ <!-- Month -->
+ <NumberPicker
+ android:id="@+id/month"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dip"
+ android:layout_marginBottom="16dip"
+ android:layout_marginStart="8dip"
+ android:layout_marginEnd="8dip"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ />
+
+ <!-- Day -->
+ <NumberPicker
+ android:id="@+id/day"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dip"
+ android:layout_marginBottom="16dip"
+ android:layout_marginStart="8dip"
+ android:layout_marginEnd="8dip"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ />
+
+ <!-- Year -->
+ <NumberPicker
+ android:id="@+id/year"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dip"
+ android:layout_marginBottom="16dip"
+ android:layout_marginStart="8dip"
+ android:layout_marginEnd="16dip"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ />
+
+ </LinearLayout>
+
+ <!-- calendar view -->
+ <CalendarView
+ android:id="@+id/calendar_view"
+ android:layout_width="245dip"
+ android:layout_height="280dip"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:layout_weight="1"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ />
+
+</LinearLayout>
diff --git a/core/res/res/layout/date_picker_selected_date.xml b/core/res/res/layout/date_picker_selected_date.xml
new file mode 100644
index 0000000..426deed
--- /dev/null
+++ b/core/res/res/layout/date_picker_selected_date.xml
@@ -0,0 +1,65 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/day_picker_selector_layout"
+ android:layout_width="@dimen/datepicker_component_width"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:paddingTop="8dip"
+ android:paddingBottom="8dip"
+ android:background="?android:attr/datePickerHeaderSelectorBackgroundColor"
+ android:gravity="center"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:id="@+id/date_picker_month_and_day_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:clickable="true"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/date_picker_month"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:duplicateParentState="true"
+ android:gravity="center_horizontal|bottom"
+ android:textAppearance="?android:attr/datePickerHeaderSelectorMonthLabelTextAppearance" />
+
+ <TextView
+ android:id="@+id/date_picker_day"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginBottom="-10dip"
+ android:layout_marginTop="-10dip"
+ android:duplicateParentState="true"
+ android:gravity="center"
+ android:textAppearance="?android:attr/datePickerHeaderSelectorDayOfMonthLabelTextAppearance" />
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/date_picker_year"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center_horizontal|top"
+ android:textAppearance="?android:attr/datePickerHeaderSelectorYearLabelTextAppearance" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/drawable/lock_task_notify_bg.xml b/core/res/res/layout/date_picker_view_animator.xml
similarity index 66%
copy from core/res/res/drawable/lock_task_notify_bg.xml
copy to core/res/res/layout/date_picker_view_animator.xml
index 3a8fab5..9085ed5 100644
--- a/core/res/res/drawable/lock_task_notify_bg.xml
+++ b/core/res/res/layout/date_picker_view_animator.xml
@@ -13,10 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
-
- <solid android:color="@android:color/black" />
- <corners
- android:radius="8dip" />
-</shape>
+<com.android.internal.widget.AccessibleDateAnimator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/animator"
+ android:layout_width="@dimen/datepicker_component_width"
+ android:layout_height="@dimen/datepicker_view_animator_height"
+ android:gravity="center" />
\ No newline at end of file
diff --git a/core/res/res/layout/lock_to_app_checkbox.xml b/core/res/res/layout/lock_to_app_checkbox.xml
new file mode 100644
index 0000000..890507b
--- /dev/null
+++ b/core/res/res/layout/lock_to_app_checkbox.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/layout/alert_dialog.xml
+**
+** Copyright 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.
+*/
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="15dip"
+ android:paddingBottom="0dip"
+ android:paddingStart="12dip"
+ android:paddingEnd="25dip"
+ >
+
+ <CheckBox
+ android:id="@+id/lock_to_app_checkbox"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+</FrameLayout>
diff --git a/core/res/res/layout/lock_to_app_enter.xml b/core/res/res/layout/lock_to_app_enter.xml
deleted file mode 100644
index c034536..0000000
--- a/core/res/res/layout/lock_to_app_enter.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="20dp"
- android:paddingRight="20dp"
- android:paddingBottom="12dp"
- android:alpha=".8"
- android:background="@drawable/lock_task_notify_bg" >
-
- <ImageView
- android:id="@+id/lock_icon"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="20dp"
- android:alpha=".8"
- android:src="@drawable/ic_lock_outline_wht_24dp" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/lock_icon"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="2dp"
- android:textColor="@android:color/white"
- android:alpha=".8"
- android:text="@string/lock_to_app_start" />
-</RelativeLayout>
diff --git a/core/res/res/layout/lock_to_app_exit.xml b/core/res/res/layout/lock_to_app_exit.xml
deleted file mode 100644
index 4a60c80..0000000
--- a/core/res/res/layout/lock_to_app_exit.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="20dp"
- android:paddingRight="20dp"
- android:paddingBottom="12dp"
- android:alpha=".8"
- android:background="@drawable/lock_task_notify_bg" >
-
- <ImageView
- android:id="@+id/lock_icon"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="20dp"
- android:alpha=".8"
- android:src="@drawable/ic_lock_open_wht_24dp" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/lock_icon"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="2dp"
- android:textColor="@android:color/white"
- android:alpha=".8"
- android:text="@string/lock_to_app_exit" />
-</RelativeLayout>
diff --git a/core/res/res/layout/preference_child_material.xml b/core/res/res/layout/preference_child_material.xml
index 690d64a..e5a8819 100644
--- a/core/res/res/layout/preference_child_material.xml
+++ b/core/res/res/layout/preference_child_material.xml
@@ -29,7 +29,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="58dip"
- android:gravity="left|center_vertical"
+ android:gravity="start|center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+android:id/icon"
@@ -67,7 +67,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="58dip"
- android:gravity="right|center_vertical"
+ android:gravity="end|center_vertical"
android:orientation="vertical" />
</LinearLayout>
diff --git a/core/res/res/layout/preference_information_material.xml b/core/res/res/layout/preference_information_material.xml
index f21640fc..d283f62 100644
--- a/core/res/res/layout/preference_information_material.xml
+++ b/core/res/res/layout/preference_information_material.xml
@@ -30,7 +30,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="58dip"
- android:gravity="left|center_vertical"
+ android:gravity="start|center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+android:id/icon"
@@ -68,7 +68,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="58dip"
- android:gravity="right|center_vertical"
+ android:gravity="end|center_vertical"
android:orientation="vertical" />
</LinearLayout>
diff --git a/core/res/res/layout/preference_material.xml b/core/res/res/layout/preference_material.xml
index a9599139..3919f5f 100644
--- a/core/res/res/layout/preference_material.xml
+++ b/core/res/res/layout/preference_material.xml
@@ -71,7 +71,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="58dip"
- android:gravity="right|center_vertical"
+ android:gravity="end|center_vertical"
android:orientation="vertical" />
</LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index b3a3478..5acb588 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -35,7 +35,6 @@
android:layout_alignParentTop="true"
style="?attr/actionBarStyle"
android:transitionName="android:action_bar"
- android:touchscreenBlocksFocus="true"
android:gravity="top">
<com.android.internal.widget.ActionBarView
android:id="@+id/action_bar"
@@ -54,6 +53,5 @@
android:layout_height="wrap_content"
style="?attr/actionBarSplitStyle"
android:visibility="gone"
- android:touchscreenBlocksFocus="true"
android:gravity="center"/>
</com.android.internal.widget.ActionBarOverlayLayout>
diff --git a/core/res/res/layout/screen_toolbar.xml b/core/res/res/layout/screen_toolbar.xml
index 039e89f..56815f8 100644
--- a/core/res/res/layout/screen_toolbar.xml
+++ b/core/res/res/layout/screen_toolbar.xml
@@ -35,7 +35,6 @@
android:layout_alignParentTop="true"
style="?attr/actionBarStyle"
android:transitionName="android:action_bar"
- android:touchscreenBlocksFocus="true"
android:gravity="top">
<Toolbar
android:id="@+id/action_bar"
diff --git a/core/res/res/layout/time_header_label.xml b/core/res/res/layout/time_header_label.xml
index f5f4a04..45c6241 100644
--- a/core/res/res/layout/time_header_label.xml
+++ b/core/res/res/layout/time_header_label.xml
@@ -25,8 +25,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/separator"
- android:layout_alignBaseline="@+id/separator"
- android:textAppearance="?android:attr/timePickerHeaderTimeLabelTextAppearance"/>
+ android:layout_alignBaseline="@+id/separator"/>
<TextView
android:id="@+id/separator"
@@ -35,7 +34,6 @@
android:paddingLeft="@dimen/timepicker_separator_padding"
android:paddingRight="@dimen/timepicker_separator_padding"
android:layout_centerInParent="true"
- android:textAppearance="?android:attr/timePickerHeaderTimeLabelTextAppearance"
android:importantForAccessibility="no" />
<TextView
@@ -43,8 +41,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/separator"
- android:layout_alignBaseline="@+id/separator"
- android:textAppearance="?android:attr/timePickerHeaderTimeLabelTextAppearance" />
+ android:layout_alignBaseline="@+id/separator" />
<TextView
android:id="@+id/ampm_label"
@@ -53,7 +50,6 @@
android:paddingLeft="@dimen/timepicker_ampm_left_padding"
android:paddingRight="@dimen/timepicker_ampm_left_padding"
android:layout_toRightOf="@+id/separator"
- android:layout_alignBaseline="@+id/separator"
- android:textAppearance="?android:attr/timePickerHeaderAmPmLabelTextAppearance" />
+ android:layout_alignBaseline="@+id/separator" />
</RelativeLayout>
diff --git a/core/res/res/layout/year_label_text_view.xml b/core/res/res/layout/year_label_text_view.xml
new file mode 100644
index 0000000..4e39831
--- /dev/null
+++ b/core/res/res/layout/year_label_text_view.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<android.widget.TextViewWithCircularIndicator
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/month_text_view"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/datepicker_year_label_height"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:textAppearance="?android:attr/datePickerHeaderListYearLabelTextAppearance" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 285001b..9d169b1 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Laat die program toe om SMS-boodskappe te skryf wat op jou foon of SIM-kaart gestoor is. Kwaadwillige programme kan dalk jou boodskappe uitvee."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"ontvang teksboodskappe (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Laat die program toe om WAP-boodskappe te ontvang en te verwerk. Hierdie toestemming sluit ook in dat boodskappe wat na jou toestel gestuur is, gemonitor of uitgevee kan word, sonder dat jy dit gesien het."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"ontvang Bluetooth-boodskappe (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Laat die program toe om Bluetooth-MAP-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur word, kan monitor of uitvee sonder dat jy dit gesien het."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"haal lopende programme op"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Laat die program toe om inligting oor die huidig- en onlangslopende take op te haal. Dit kan moontlik die program toelaat om inligting oor watter programme op die toestel gebruik word, te ontdek."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interaksie tussen gebruikers"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"kamma liggingbronne vir toetsing"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Skep skynliggingsbronne vir toetsing of installeer \'n nuwe liggingsverskaffer. Die program kan dan die ligging en/of status wat deurgegee is deur ander liggingsbronne, soos GPS of liggingsverskaffers, oorheers."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"Kry toegang tot ekstra liggingverskaffer-bevele"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Laat die program toe om ekstra liggingverskaffer-bevele te gebruik. Die programme kan dit moontlik gebruik om met die werking van die GPS of ander liggingsbronne in te meng."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Gee die program toegang tot ekstra liggingverskaffer-bevele. Dit kan die program dalk toelaat om in te meng met die werking van die GPS of ander liggingbronne."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"toestemming om \'n liggingverskaffer te installeer"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Skep skynliggingsbronne vir toetsing of installeer \'n nuwe liggingsverskaffer. Die program kan dan die ligging en/of status wat deurgegee is deur ander liggingsbronne, soos GPS of liggingsverskaffers, oorheers."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"presiese ligging (GPS en netwerkgebaseer)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Laat die program toe om netwerkbeleide te bestuur en program-spesifieke reëls te definieer."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"verander verrekening van netwerkgebruik"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Laat die program toe om te verander hoe netwerkgebruik teenoor programme gemeet word. Nie vir gebruik deur normale programme nie."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"wysig sokmerke"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Laat die program toe om sokmerke vir roetering te wysig"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"kry toegang tot kennisgewings"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Laat die program toe om kennisgewings op te haal, te bestudeer en te verwyder, insluitende die kennisgewings wat deur ander programme geplaas is."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind aan \'n kennisgewingluisteraardiens"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Laat die houer toe om aan die top-koppelvlak van \'n kennisgewingluisteraardiens te bind. Behoort nooit vir gewone programme nodig te wees nie."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"verbind met \'n toestandverskafferdiens"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Laat die houer toe om met die topvlak-koppelvlak van \'n toestandverskafferdiens te verbind. Behoort nooit vir normale programme nodig te wees nie."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"bind aan \'n droomdiens"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Laat die houer toe om aan die topvlak-koppelvlak van \'n droomdiens te bind. Behoort nooit vir normale programme nodig te wees nie."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"roep die opstellingprogram op wat deur die diensverskaffer voorsien is"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Laat die program toe om die kalibrasieparameters van die raakskerm te wysig. Dit behoort nooit vir normale programme nodig te wees nie."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"gaan in by DRM-sertifikate"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Laat \'n program toe om DRM-sertifikate op te stel en te gebruik. Behoort nooit vir normale programme nodig te wees nie."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Ontvang oordraguitsendings."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Laat toe dat oordragstatusinligting ontvang word."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Ontvang Android Straal-oordragstatus"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Laat hierdie program toe om inligting oor huidige Android Straal-oordragte te ontvang."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Beheer lengte en watter karakters wat in die skermontsluit-wagwoorde gebruik word."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Laat die program toe om die blaaier se geskiedenis of boekmerke wat op jou foon gestoor is, te verander. Dit kan moontlik die program toelaat om blaaierdata uit te vee of te verander. Let wel: hierdie toestemming mag dalk nie deur derdeparty-blaaiers of ander programme met webblaaivermoëns afgedwing word nie."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"stel \'n wekker"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Laat die program toe om \'n alarm in \'n geïnstalleerde wekkerprogram te stel. Sommige wekkerprogramme werk dalk nie met hierdie funksie nie."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"verwyder stemposse"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Laat die program toe om boodskappe uit jou stemposinkassie te verwyder."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"bestuur stemboodskapdiens"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Laat die program toe om boodskappe uit jou stemposinkassie te wysig en te verwyder."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"voeg stemboodskap by"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Laat die program toe om boodskappe by te voeg by jou stempos-inkassie."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"lees alle stempos"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"AAN"</string>
<string name="capital_off" msgid="6815870386972805832">"AF"</string>
<string name="whichApplication" msgid="4533185947064773386">"Voltooi handeling met"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Kies \'n tuisprogram"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Gebruik hierdie aksie by verstek."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Vee die verstek instelling uit in Stelselinstellings > Programme > Afgelaai."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Laat altyd toe"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Moet nooit toelaat nie"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-kaart verwyder"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Die mobielnetwerk sal nie beskikbaar wees nie totdat jy weer begin met \'n geldige SIM-kaart."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Klaar"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-kaart bygevoeg"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Herbegin jou toestel om toegang tot die mobiele netwerk te kry."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Herbegin"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Stel tyd"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Stel datum"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> gekies"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> uitgevee"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Jy is in Sluit-na-program-modus."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Gebruik Sluit-na-program?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Sluit-na-program sluit die skerm in \'n enkele program.\n\nOm uit te gaan, druk en hou die knoppie vir onlangse programme $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NEE"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"BEGIN"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Begin Sluit-na-program"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Gaan uit Sluit-na-program"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 54979cb..5859045 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"በስልክዎ ወይም ሲም ካርድዎ ላይ ኤስ ኤም ኤስ መልዕክቶችን ለመፃፍ ለመተግበሪያው ይፈቅዳሉ። መልዕክቶችዎን ተንኮል አዘል መተግበሪያዎች ሊሰርዙ ይችላሉ።"</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"የፅሁፍ መልዕክቶችን ተቀበል (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"መተግበሪያው የWAP መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ፈቃድ የተላኩልዎን መልዕክቶች ለእርስዎ ሳያሳይዎ የመቆጣጠር ወይም የመሰረዝ ብቃትን ያጠቃልላል።"</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"የብሉቱዝ መልእክቶችን ተቀበል (ኤምኤፒ)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"መተግበሪያው የብሉቱዝ ኤምኤፒ መልእክቶችን እንዲቀበልና እንዲያካሂድ ይፈቅድለታል። ይህ ማለት መተግበሪያው ወደመሳሪያዎ የተላኩ መልእክቶችን ለእርስዎ ሳያሳይ ሊከታተል ወይም ሊሰረዝ ይችላል ማለት ነው።"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"አሂድ መተግበሪያዎችን ሰርስረው ያውጡ"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"መተግበሪያው በአሁኑ ጊዜና በቅርቡ እየተካሄዱ ስላሉ ተግባሮችን መረጃ ሰርስሮ እንዲያወጣ ይፈቅድለታል። ይህ መተግበሪያው በመሳሪያው ላይ የትኛዎቹ መተግበሪያዎች ጥቅም ላይ ስለመዋላቸው መረጃ እንዲያገኝ ሊፈቅድለት ይችላል።"</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"በተለያዩ ተጠቃሚዎች መካከል መስተጋብር መፍጠር"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"ለሙከራ ጊዜያዊ ሥፍራ ፍጠር።"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"ለሙከራ የጊዜያዊ የመነሻ ምንጮችን ይፍጠሩ ወይም አዲስ የአካባቢ አቅራቢ ይጫኑ። ይህ መተግበሪያው አካባቢውን እና/ወይም እንደ GPS ወይም የአካባቢ አቅራቢዎች ባሉ ሌላ የመነሻ ምንጮች የተመለሱ ሁኔታዎችን ችላ እንዲል ይፈቅድለታል።"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ተጨማሪ ሥፍራ አቅራቢ ትዕዛዞችን ድረስ።"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"መተግበሪያው ተጨማሪ የአካባቢ አቅራቢ ትእዛዞችን እንዲደርስ ይፈቅድለታል። ይህ መተግበሪያው በGPS ወይም ሌላ የመነሻ ምንጮች ክወና ላይ ጣልቃ እንዲገባ ሊፈቅድለት ይችላል።"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"መተግበሪያው ተጨማሪ የአካባቢ አቅራቢ ትእዛዞችን እንዲደርስ ይፈቅድለታል። ይሄ መተግበሪያው በጂፒኤስ ወይም ሌላ የአካባቢ ምንጮች ስራ ላይ ጣልቃ እንዲገባ ሊፈቅድለት ይችላል።"</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"የሥፍራ አቅራቢ ለመጫን ፍቀድ"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"ለሙከራ የጊዜያዊ የመነሻ ምንጮችን ይፍጠሩ ወይም አዲስ የአካባቢ አቅራቢ ይጫኑ። ይህ መተግበሪያው አካባቢውን እና/ወይም እንደ ጂፒኤስ ወይም የአካባቢ አቅራቢዎች ባሉ ሌላ የመነሻ ምንጮች የተመለሱ ሁኔታዎችን ችላ እንዲል ይፈቅድለታል።"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ትክክለኛ አካባቢ (በጂ ፒ ኤስ እና አውታረ መረብ ላይ የተመሠረተ)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"የአውታረመረብ ቋሚ መመሪያዎችን እና ትግበራ ተኮር ደንቦችን ለማደራጀት ለመተግበሪያው ይፈቅዳሉ፡፡"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"የአውታረ መረብ አጠቃቀም"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ከመተግበሪያዎች በተለየ መልኩ እንዴት የአውታረ መረብ አጠቃቀም እንደተመዘገበ ለመቀየር ለመተግበሪያው ይፈቅዳሉ።ለመደበኛ መተግበሪያዎች አገልግሎት አይውልም።"</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"የሶኬት ምልክቶችን መቀየር"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"መተግበሪያው መንገድ እንዲፈልግ የሶኬት ምልክቶቹን እንዲቀይር ያስችለዋል"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"ማሳወቂያዎችን ይድረሱ"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"መተግበሪያው ማሳወቂያዎችን እንዲያስመጣ፣ እንዲመረምር እና እንዲያጸዳ ያስችለዋል፣ በሌሎች መተግበሪያዎች የተለጠፉትንም ጨምሮ።"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ከአንድ የማሳወቂያ አዳማጭ አገልግሎት ጋር ይሰሩ"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ያዢው የማሳወቂያ አዳማጭ አገልግሎቱን ከከፍተኛ-ደረጃ በይነገጹ ጋር እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ከአንድ የሁኔታ አቅራቢ አገልግሎት ጋር ይሰሩ"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"ያዢው የአንድ የሁኔታ አቅራቢ አገልግሎት የከፍተኛ ደረጃ በይነገጽ እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"ከህልም አገልግሎት ጋር ጠርዝ"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"ያዢው የህልም አገልግሎቱን ከከፍተኛ-ደረጃ በይነገጽ ጋር እንዲጠርዝ ይፈቅዳል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"በድምጸ-ተያያዥ ሞደም የቀረበው የውቅር መተግበሪያውን መጥራት"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"መተግበሪያው የማያ ንካ የማስተካከያ ልኬቶቹን እንዲቀይር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"የDRM የምስክር ወረቀቶች ላይ ይድረሱ"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"አንድ መተግበሪያ የDRM የምስክር ወረቀቶችን እንዲሰጥና እንዲጠቀም ያስችላል። ለመደበኛ መተግበሪያዎች በፍጹም አስፈላጊ አይሆንም።"</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"የርክክብ ትልልፍ ስርጭቶችን ተቀበል።"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"የርክክብ ትልልፍ ሁኔታ መረጃ እንዲቀበል ያስችላል።"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"የAndroid Beam ሽግግር ሁኔታን ይቀበሉ"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"ይም መተግበሪያ ስለአሁን የAndroid Beam ሽግግሮች መረጃ እንዲቀበል ይፈቅዳል"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"በማያ-መክፈት የተፈቀዱ የይለፍ ቃል ርዝመት እና ቁምፊዎች ተቆጣጠር።"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"መተግበሪያው ስልክህ ላይ የተከማቹ የአሳሹን ታሪክ ወይም ዕልባቶችን እንዲቀይር ይፈቅድለታል። ይህ መተግበሪያው የአሳሽ ውሂብ እንዲያጠፋ ወይም እንዲያስተካክል ሊፈቅድለት ይችላል። ማስታወሻ፦ ይህ ፈቃድ በሶስተኛ ወገን አሳሾች ወይም በሌላ የድር አሳሽነት አቅም ባላቸው መተግበሪያዎች ላይፈጸም ይችላል።"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"ማንቂያ አስቀምጥ"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"በተጫነው የማንቂያ ሰዓት መተግበሪያ ውስጥ ማንቅያን ለማደራጀት ለመተግበሪያው ይፈቅዳሉ፡፡አንዳንድ የማንቂያ ሰዓት መተግበሪያዎች ይሄንን ባህሪ ላይፈፅሙ ይችላሉ፡፡"</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"የድምጽ መልዕክቶችን ያስወግዳል"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"መተግበሪያው መልዕክቶችን ከገቢ የድምጽ መልዕክት ሳጥዎ እንዲያስወግድ ያስችለዋል።"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"የድምጽ መልእክቶችን ያስተዳድሩ"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"መተግበሪያው ከድምጽ መልእክት የገቢ መልእክት ሳጥንዎ ውስጥ መልእክቶችን እንዲያስተካክልና እንዲያስወግድ ይፈቅዳል"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"የድምፅ መልዕክት አክል"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"ወደ ድምፅ መልዕክት የገቢ መልዕክትህ መልዕክቶች ለማከል ለመተግበሪያው ይፈቅዳሉ።"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ሁሉንም የድምጽ መልዕክት ያነብባል"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"በ"</string>
<string name="capital_off" msgid="6815870386972805832">"ውጪ"</string>
<string name="whichApplication" msgid="4533185947064773386">"... በመጠቀም ድርጊቱን አጠናቅ"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"የመነሻ መተግበሪያ ይምረጡ"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ለዕርምጃ ነባሪ ተጠቀም።"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"ነባሪ አጽዳ በስርዓት ቅንብሮች ውስጥ > Apps &gt፤ወርዷል፡፡"</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"ሁልጊዜ ፍቀድ"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"በጭራሽ አትፍቀድ"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM ካርድ ተወግዷል"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"በትክክል የገባ SIM ካርድ ድጋሚ እስኪያስጀምሩ የተንቀሳቃሽ ስልክ አውታረመረብ አይገኝም።"</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"ተከናውኗል"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM ካርድ አክል"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"የተንቀሳቃሽ አውታረ መረብን ለመድረስ መሣሪያህን ድጋሚ አስነሳ።"</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"ዳግም ጀምር"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"ጊዜ አዘጋጅ"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ተመርጧል"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ተሰርዟል"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"መተግበሪያ-ላይ-ቆልፍን ይጠቀሙ?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"መተግበሪያ-ላይ-ቆልፍ ማሳያውን በአንዲት መተግበሪያ ውስጥ ይቆልፋል።\n\nለመውጣት የቅርብ ጊዜ መተግበሪያዎች አዝራር $ን ተጭነው ይያዙት"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"አይ"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"ከመተግበሪያ-እዚህ-ቆልፍ ሁነታ ላይ ነው ያሉት።"</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"መተግበሪያ-እዚህ-ቆልፍን ይጠቀም?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ጀምር"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"መተግበሪያ-ላይ-ቆልፍን ጀምር"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"ከመተግበሪያ-ላይ-ቆልፍ ውጣ"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 664490c..6164506 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"للسماح للتطبيق بالكتابة إلى الرسائل القصيرة SMS المخزّنة على الهاتف أو بطاقة SIM. قد تحذف التطبيقات الضارة رسائلك."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"تلقي رسائل نصية (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"للسماح للتطبيق بتلقي رسائل WAP ومعالجتها. ويتضمن هذا الإذن إمكانية مراقبة الرسائل التي يتم إرسالها إليك أو حذفها بدون عرضها لك."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"تلقي رسائل بلوتوث (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"يسمح للتطبيق بتلقي رسائل بلوتوث MAP ومعالجتها. وهذا يعني أنه سيكون بإمكان التطبيق الإشراف على أو حذف الرسائل المرسلة إليك بدون عرضها لك."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"استرداد التطبيقات التي قيد التشغيل"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"للسماح للتطبيق باسترداد معلومات حول المهام التي يجري تشغيلها حاليًا والتي تم تشغيلها مؤخرًا. وقد يسمح هذا للتطبيق باكتشاف معلومات حول التطبيقات المستخدمة على الجهاز."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"التعامل بين المستخدمين"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"مصادر مواقع وهمية للاختبار"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"لإنشاء مصادر مواقع زائفة للاختبار أو تثبيت موفر مواقع جديد. يتيح هذا للتطبيق إلغاء الموقع و/أو الحالة التي تعرضها مصادر المواقع الأخرى مثل GPS أو موفري المواقع."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"الدخول إلى المزيد من أوامر موفر الموقع"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"للسماح للتطبيق بالدخول إلى المزيد من أوامر موفر خدمة الموقع. وقد يتيح هذا للتطبيق التدخل في عمل GPS أو مصادر المواقع الأخرى."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"للسماح للتطبيق بالدخول إلى أوامر إضافية لموفر الموقع. قد يتيح هذا للتطبيق التداخل مع تشغيل تقنية نظام تحديد المواقع العالمي (GPS) أو مصادر الموقع الأخرى."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"إذن لتثبيت موفر خدمة موقع"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"لإنشاء مصادر مواقع زائفة للاختبار أو تثبيت موفر مواقع جديد. يتيح هذا للتطبيق إلغاء الموقع و/أو الحالة التي تعرضها مصادر المواقع الأخرى مثل GPS أو موفري المواقع."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"الموقع الدقيق (مستند إلى نظام تحديد المواقع العالمي والشبكة)"</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"للسماح لتطبيق بإدارة سياسات الشبكة وتحديد قواعد متعلقة بالتطبيق."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"تعديل حساب استخدام الشبكة"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"للسماح للتطبيق بتعديل كيفية حساب استخدام الشبكة في التطبيقات. ليس للاستخدام بواسطة التطبيقات العادية."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"تعديل علامات المقابس"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"للسماح للتطبيق بتعديل علامات المقابس لإعادة التوجيه."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"إشعارات الدخول"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"يتيح للتطبيق استرجاع الإشعارات وفحصها ومسحها، بما في ذلك تلك التي نشرتها تطبيقات أخرى."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"الربط بخدمة تلقّي الإشعارات الصوتية"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"يتيح للمالك الربط بواجهة المستوى العلوي لخدمة تلقّي الإشعارات الصوتية. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"الربط بخدمة موفر الحالة"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"للسماح للمالك بالربط بواجهة المستوى العلوي لخدمة موفر الحالة. لن تكون هناك حاجة إلى هذا الإعداد مطلقًا مع التطبيقات العادية."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"الربط بخدمة توجيه الوسائط"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"للسماح للمالك بالربط بواجهة المستوى العلوي لخدمة توجيه الوسائط. لن تكون هناك حاجة إلى هذا الإعداد مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"الالتزام بخدمة dream"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة dream. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"استدعاء تطبيق التهيئة الذي يوفره مشغل شبكة الجوال"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"يتيح للتطبيق إمكانية تعديل معلمات المعايرة في شاشة اللمس. يجب عدم اللجوء إليه مع التطبيقات العادية."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"الدخول إلى شهادات DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"للسماح لأحد التطبيقات بتقديم شهادات DRM واستخدامها. لا يجب أن يكون ذلك لازمًا مطلقًا مع التطبيقات العادية."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"استلام عمليات البث المتعلقة بنقل إمكانية التحكم."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"للسماح باستلام معلومات حالة نقل إمكانية التحكم."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"تلقي حالة نقل شعاع Android"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"السماح لهذا التطبيق بتلقي معلومات حول عمليات نقل شعاع Android الحالية"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"يمكنك التحكم في الطول والأحرف المسموح بها في كلمات مرور إلغاء تأمين الشاشة."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء قفل الشاشة"</string>
@@ -1008,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"للسماح للتطبيق بتعديل سجل المتصفح أو الإشارات المرجعية المخزنة على هاتفك. وقد يتيح هذا للتطبيق محو بيانات المتصفح أو تعديلها. ملاحظة: لا يجوز فرض هذا الإذن من قِبل متصفحات جهات خارجية أو تطبيقات أخرى بها إمكانيات تصفح الويب."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"تعيين منبه"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"للسماح للتطبيق بضبط المنبه في تطبيق المنبه المثبّت. ربما لا تنفذ بعض تطبيقات المنبه هذه الميزة."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"إزالة رسائل البريد الصوتي"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"للسماح للتطبيق بإزالة الرسائل من صندوق البريد الصوتي."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"إدارة رسائل البريد الصوتي"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"للسماح للتطبيق بتعديل الرسائل وإزالتها من صندوق البريد الصوتي."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"إضافة بريد صوتي"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"للسماح للتطبيق بإضافة رسائل إلى صندوق البريد الصوتي."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"قراءة جميع رسائل البريد الصوتي"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"تشغيل"</string>
<string name="capital_off" msgid="6815870386972805832">"إيقاف"</string>
<string name="whichApplication" msgid="4533185947064773386">"إكمال الإجراء باستخدام"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"إكمال الإجراء باستخدام %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"فتح باستخدام"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"فتح باستخدام %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"تعديل باستخدام"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"تعديل باستخدام %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"مشاركة مع"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"مشاركة مع %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"تحديد تطبيق الشاشة الرئيسية"</string>
<string name="alwaysUse" msgid="4583018368000610438">"الاستخدام بشكل افتراضي لهذا الإجراء."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"يمكنك محو الإعدادات الافتراضية في إعدادات النظام > التطبيقات > ما تم تنزيله."</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"السماح دومًا"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"عدم السماح مطلقًا"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"تمت إزالة بطاقة SIM"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"لن تكون شبكة الجوال متاحة حتى تتم إعادة التشغيل وإدخال بطاقة SIM صالحة."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"لن تكون شبكة الجوّال متوفرة إلى أن تعيد تشغيل الهاتف مع إدخال بطاقة SIM صالحة."</string>
<string name="sim_done_button" msgid="827949989369963775">"تم"</string>
<string name="sim_added_title" msgid="3719670512889674693">"تمت إضافة بطاقة SIM"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"أعد تشغيل جهازك للدخول إلى شبكة الجوال."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"أعد تشغيل جهازك للدخول إلى شبكة الجوّال."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"إعادة التشغيل"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"تعيين الوقت"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"تعيين التاريخ"</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"تم تحديد <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"تم حذف <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> المخصص للعمل"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"هل تريد استخدام قفل تشغيل الجهاز على تطبيق؟"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"تتيح ميزة \"قفل تشغيل الجهاز على تطبيق\" تأمين الشاشة وقصر استخدامها على تطبيق واحد.\n\nللخروج اضغط مع الاستمرار على زر التطبيقات الحديثة $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"لا"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"أنت في وضع \"التقييد بتطبيق\"."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"هل تريد استخدام ميزة التقييد بتطبيق؟"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"بدء"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"بدء قفل تشغيل الجهاز على تطبيق"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"خروج من قفل تشغيل الجهاز على تطبيق"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index a97b639..a3ce885 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Разрешава на приложението да записва в SMS съобщенията, съхранени в телефона или в SIM картата ви. Злонамерените приложения могат да изтрият съобщенията ви."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"получаване на текстови съобщения (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Разрешава на приложението да получава и обработва WAP съобщения. Това разрешение включва възможността да наблюдава или изтрива изпратените до вас, без да ви ги покаже."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"получаване на съобщения чрез Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Разрешава на приложението да получава и обработва съобщения чрез Bluetooth MAP. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"извличане на изпълняваните приложения"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Разрешава на приложението да извлича информация за задачите, изпълнявани понастоящем и неотдавна. Това може да му позволи да открива данни за това, кои приложения се използват на устройството."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"взаимодействие с потребителите"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"имитиране на източници на местоположение за тестване"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Създаване на мними източници на местоположение за тестване или инсталиране на нов доставчик на местоположение. Това разрешава на приложението да заменя местоположението и/или състоянието, връщано от други източници, като GPS или доставчиците."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"достъп до допълнителни команди на доставчика на местоположение"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Разрешава на приложението достъп до допълнителни команди на доставчика на местоположение. Това може да му позволи да смущава работата на GPS или на другите източници на местоположение."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Разрешава на приложението достъп до допълнителни команди на доставчика на местоположение. Това може да позволи на приложението да смущава работата на GPS или на другите източници на местоположение."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"разрешение за инсталиране на доставчик на местоположение"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Създаване на мними източници на местоположение за тестване или инсталиране на нов доставчик на местоположение. Това разрешава на приложението да заменя местоположението и/или състоянието, връщано от други източници, като GPS или доставчиците."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"точно местоположение (основано на GPS и мрежата)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Разрешава на приложението да управлява правилата на мрежата и да определя такива за конкретно приложение."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"промяна на отчетността на употребата на мрежа"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Разрешава на приложението да променя това как употребата на мрежа се отчита спрямо приложенията. Не е предназначено за нормални приложения."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"промяна на означенията на сокетите"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Разрешава на приложението да променя означенията на сокетите за маршрутизиране."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"достъп до известията"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Разрешава на приложението да извлича, преглежда и изчиства известия, включително публикуваните от други приложения."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"обвързване с услуга за слушател на известия"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Разрешава на притежателя да се обвърже с интерфейса от първо ниво на услуга за слушател на известия. Нормалните приложения не би трябвало никога да се нуждаят от това."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"свързване с услуга за предоставяне на условия"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Разрешава на притежателя да се свърже с интерфейса от най-високото ниво на услуга за предоставяне на условия. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"свързване с услуга за „мечти“"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Разрешава на притежателя да се свърже с интерфейса от най-високото ниво на услуга за „мечти“. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"извикване на предоставеното от оператора приложение за конфигуриране"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Разрешава на приложението да променя параметрите на калибриране на сензорния екран. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"достъп до сертификатите за управление на цифровите права (DRM)"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Разрешава на приложението да обезпечава и използва сертификатите за управление на цифровите права (DRM). Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Получаване на излъчвания с данни за прехвърлянията."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Разрешава получаването на информация за състоянието на прехвърлянията."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Получаване на състоянието на прехвърлянията чрез Android Лъч"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Разрешава на това приложение да получава информация относно текущите прехвърляния чрез Android Лъч"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролирайте дължината и разрешените знаци за паролите за отключване на екрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Разрешава на приложението да променя историята или отметките на браузъра, съхранени на телефона ви. Това може да му позволи да изтрива или променя данните на браузъра. Забележка: Възможно е браузъри на трети страни или други приложения с възможности за сърфиране в мрежата да не могат да наложат ограниченията на разрешението."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"навиване на будилника"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Разрешава на приложението да навие инсталирано приложение будилник. Някои будилници може да не изпълнят тази функция."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"премахване на гласови съобщения"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Разрешава на приложението да премахва съобщения от входящата ви гласова поща."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"управление на гласовите съобщения"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Разрешава на приложението да променя и премахва съобщения от входящата ви гласова поща."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"добавяне на гласова поща"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Разрешава на приложението да добавя съобщения към входящата ви гласова поща."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"четене на цялата гласова поща"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"ВКЛ"</string>
<string name="capital_off" msgid="6815870386972805832">"ИЗКЛ"</string>
<string name="whichApplication" msgid="4533185947064773386">"Изпълняване на действието чрез"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Избиране на приложение за начало"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Използване по подразбиране за това действие."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Изчистване на стандартната настройка в „Системни настройки“ > „Приложения“ > „Изтеглени“."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Винаги да се разрешава"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Никога да не се разрешава"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM картата е премахната"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Няма да имате достъп до мобилната мрежа, докато не рестартирате с поставена валидна SIM карта."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM картата е добавена"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Рестартирайте устройството си, за да осъществите достъп до мобилната мрежа."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Рестартиране"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Задаване на часа"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Задаване на дата"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Избрахте <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Изтрихте <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> за работа"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Режимът на заключване в приложението е включен."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Да се използва ли „Заключване в приложението“?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Със „Заключване в приложението“ екранът се заключва в едно приложение.\n\nЗа изход натиснете и задръжте бутона за скорошни приложения $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"НЕ"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"СТАРТИРАНЕ"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Стартиране на „Заключване в приложението“"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Изход от „Заключване в приложението“"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 515773d..da68afe 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Permet que l\'aplicació llegeixi missatges SMS emmagatzemats al telèfon o a la targeta SIM. Les aplicacions malicioses poden llegir els teus missatges confidencials."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"recepció de missatges de text (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permet que l\'aplicació rebi i processi missatges WAP. Aquest permís inclou la capacitat de controlar o de suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"rebre missatges de Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Permet que l\'aplicació rebi i processi missatges de Bluetooth MAP. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'hagin enviat al teu dispositiu sense mostrar-te\'ls."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"recupera les aplicacions en execució"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Permet que l\'aplicació recuperi informació sobre les tasques que s\'executen actualment i les que s\'han executat recentment. Aquesta acció pot permetre que l\'aplicació descobreixi informació sobre les aplicacions que s\'utilitzen al dispositiu."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interacciona entre usuaris"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"crear orígens d\'ubicacions fictícies per fer proves"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Crea fonts d\'ubicació fictícies per provar o per instal·lar un proveïdor d\'ubicació nou. Aquesta acció permet que l\'aplicació substitueixi la ubicació o l\'estat que retornen altres fonts d\'ubicació, com ara el GPS o altres proveïdors d\'ubicació."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accedir a ordres del proveïdor d\'ubicació addicionals"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permet que l\'aplicació accedeixi a ordres del proveïdor d\'ubicació addicionals. Aquesta acció pot permetre que l\'aplicació interfereixi amb el funcionament del GPS o d\'altres fonts d\'ubicació."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permet que l\'aplicació accedeixi a ordres addicionals del proveïdor d\'ubicacions; per tant, és possible que l\'aplicació pugui interferir en el funcionament del GPS o d\'altres fonts d\'ubicacions."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"permís per instal·lar un proveïdor d\'ubicacions"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Crea fonts d\'ubicació fictícies per provar o per instal·lar un proveïdor d\'ubicació nou. Aquesta acció permet que l\'aplicació substitueixi la ubicació o l\'estat que retornen altres fonts d\'ubicació, com ara el GPS o altres proveïdors d\'ubicació."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ubicació precisa (basada en GPS i xarxa)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permet que l\'aplicació gestioni les polítiques de la xarxa i que defineixi les regles específiques d\'aplicació."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificació del càlcul d\'ús de la xarxa"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permet que l\'aplicació modifiqui la manera com es calcula l\'ús de la xarxa per part de les aplicacions. No indicat per a les aplicacions normals."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modifica les marques dels sòcols"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permet que l\'aplicació modifiqui les marques de sòcols per a l\'encaminament"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"accedeix a les notificacions"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet que l\'aplicació recuperi, examini i esborri les notificacions, incloses les que han publicat altres aplicacions."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincula a un servei oient de notificacions"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei oient de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"enllaçar amb el servei de proveïdor de condicions"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet enllaçar amb la interfície de nivell superior d\'un servei de proveïdor de condicions. No ha de ser mai necessari per a aplicacions normals."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"enllaçar amb un servei en repòs"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Permet enllaçar amb la interfície de nivell superior d\'un servei en repòs. No hauria de ser mai necessari per a aplicacions normals."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoca l\'aplicació de configuració proporcionada per l\'operador"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permet que l\'aplicació modifiqui els paràmetres de calibratge de la pantalla tàctil. No ha de ser mai necessari per a aplicacions normals."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accedir als certificats de DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permet que una aplicació proporcioni i utilitzi certificats de gestió de drets digitals (DRM, Digital Rights Management). No ha de ser mai necessari per a aplicacions normals."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"rebre difusions de transferència d\'entrega"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Permet rebre informació sobre l\'estat de la transferència d\'entrega."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Rep l\'estat de la transferència d\'Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Permet que aquesta aplicació rebi informació sobre les transferències d\'Android Beam actuals."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Controlar els intents de desbloqueig de pantalla"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permet que l\'aplicació modifiqui l\'historial del navegador o els marcadors del telèfon. Això pot permetre que l\'aplicació esborri o modifiqui les dades del navegador. Nota: És possible que aquest permís no s\'apliqui a navegadors de tercers o a altres aplicacions amb capacitats de navegació web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"configuració d\'una alarma"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Permet que l\'aplicació defineixi una alarma en una aplicació de despertador instal·lada. És possible que algunes aplicacions de despertador no incorporin aquesta funció."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"suprimir correus de veu"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Permet que l\'aplicació suprimeixi missatges de la safata d\'entrada de la bústia de veu."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"gestionar els correus de veu"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Permet que aquesta aplicació modifiqui i suprimeixi missatges de la safata d\'entrada de la bústia de veu."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"afegeix bústia de veu"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permet que l\'aplicació afegeixi missatges a la safata d\'entrada de la bústia de veu."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"accedir a tots els correus de veu"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"SÍ"</string>
<string name="capital_off" msgid="6815870386972805832">"NO"</string>
<string name="whichApplication" msgid="4533185947064773386">"Completa l\'acció mitjançant"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Selecciona una aplicació d\'inici"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utilitza-ho de manera predeterminada per a aquesta acció."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Esborra els paràmetres predeterminats a Configuració del sistema > Aplicacions > Baixades."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permet sempre"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"No permetis mai"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Extracció de la targeta SIM"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"La xarxa de telefonia mòbil no estarà disponible fins que no reiniciïs amb una targeta SIM vàlida inserida."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Fet"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Addició de la targeta SIM"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Reinicia el dispositiu per accedir a la xarxa de telefonia mòbil."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Reinicia"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Defineix l\'hora"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Establiment de data"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionat"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> suprimit"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Estàs en el mode de bloqueig d\'aplicació."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Vols fer servir la funció Bloqueig d\'aplicació?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"La funció Bloqueig d\'aplicació bloqueja la pantalla d\'una sola aplicació.\n\nPer sortir-ne, mantén premut el botó d\'aplicacions recents $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"INICI"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Inicia Bloqueig d\'aplicació"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Surt de Bloqueig d\'aplicació"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7cbb911..7721a08 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -130,7 +130,7 @@
<string name="httpErrorLookup" msgid="4711687456111963163">"Adresu URL nelze najít."</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"Schéma ověření webu není podporováno."</string>
<string name="httpErrorAuth" msgid="1435065629438044534">"Nelze provést ověření."</string>
- <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Ověření pomocí serveru proxy bylo neúspěšné."</string>
+ <string name="httpErrorProxyAuth" msgid="1788207010559081331">"Ověření pomocí proxy serveru bylo neúspěšné."</string>
<string name="httpErrorConnect" msgid="8714273236364640549">"K serveru se nelze připojit."</string>
<string name="httpErrorIO" msgid="2340558197489302188">"Se serverem nelze komunikovat. Zkuste to později."</string>
<string name="httpErrorTimeout" msgid="4743403703762883954">"Spojení se serverem vypršelo."</string>
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Umožňuje aplikaci zapisování do zpráv SMS uložených v telefonu nebo na SIM kartě. Škodlivé aplikace mohou vaše zprávy smazat."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"příjem textových zpráv (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Umožňuje aplikaci přijmout a zpracovat zprávy WAP. Toto oprávnění umožňuje sledovat přijaté zprávy nebo je smazat, aniž by se vám zobrazily."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"příjem zpráv Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Umožňuje aplikaci přijímat a zpracovat zprávy Bluetooth MAP. To znamená, že aplikace může sledovat a mazat zprávy odeslané do zařízení, aniž by vám je zobrazila."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"načtení spuštěných aplikací"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Umožňuje aplikaci získat informace o aktuálně a naposledy spuštěných úlohách. Aplikace s tímto oprávněním může odhalit informace o aplikacích, které se v zařízení používají."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakce napříč uživateli"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"simulace zdrojů polohy pro účely testování"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Vytváření simulace zdrojů polohy pro účely testování nebo instalace nového poskytovatele polohy. Toto oprávnění umožňuje aplikaci přepsat polohu nebo stav, který vracejí jiné zdroje polohy, například systém GPS nebo poskytovatelé polohy."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"přístup k dalším příkazům poskytovatele polohy"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Umožňuje aplikaci získat přístup k dalším příkazům poskytovatele polohy. Aplikace s tímto oprávněním může narušit funkci GPS či jiných zdrojů polohy."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Umožňuje aplikaci přístup k dalším příkazům poskytovatele polohy. To aplikaci umožní zasahovat do fungování systému GPS a dalších zdrojů polohy."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"oprávnění k instalaci poskytovatele polohy"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Vytváření simulace zdrojů polohy pro účely testování nebo instalace nového poskytovatele polohy. Toto oprávnění umožňuje aplikaci přepsat polohu nebo stav, který vracejí jiné zdroje polohy, například systém GPS nebo poskytovatelé polohy."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"přesná poloha (pomocí GPS a sítě)"</string>
@@ -640,7 +638,7 @@
<string name="permlab_createNetworkSockets" msgid="8018758136404323658">"úplný přístup k síti"</string>
<string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Umožňuje aplikaci vytvářet síťové sokety a používat vlastní síťové protokoly. K odesílání údajů na internet toto oprávnění není nutné, protože údaje lze na internet odesílat prostřednictvím prohlížečů a dalších aplikací."</string>
<string name="permlab_writeApnSettings" msgid="505660159675751896">"měnit/zachytávat nastavení sítě a síťové přenosy"</string>
- <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Umožňuje aplikaci změnit nastavení sítě a zachytit a prozkoumat síťové přenosy, například za účelem změny serveru proxy a portu jakéhokoli názvu přístupového bodu. Škodlivé aplikace mohou bez vašeho vědomí sledovat, přesměrovat nebo upravit síťové pakety."</string>
+ <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Umožňuje aplikaci změnit nastavení sítě a zachytit a prozkoumat síťové přenosy, například za účelem změny proxy serveru a portu jakéhokoli názvu přístupového bodu. Škodlivé aplikace mohou bez vašeho vědomí sledovat, přesměrovat nebo upravit síťové pakety."</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"změna připojení k síti"</string>
<string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Umožňuje aplikaci změnit stav připojení k síti."</string>
<string name="permlab_changeTetherState" msgid="5952584964373017960">"změnit sdílené datové připojení"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Umožňuje aplikaci spravovat zásady sítě a definovat pravidla pro konkrétní aplikace."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"upravit kontrolu používání sítě"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Umožňuje aplikaci upravit způsob výpočtu využití sítě aplikacemi. Toto oprávnění není určeno pro běžné aplikace."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"upravit značky soketů"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Umožňuje aplikaci upravit značky soketů pro směrování"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"přístup k oznámením"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikacím načítat, zobrazovat a mazat oznámení včetně těch přidaných jinými aplikacemi."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"navázání na službu pro poslouchání oznámení"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteli navázat se na nejvyšší úroveň služby pro poslouchání oznámení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"navázání na službu poskytovatele podmínky"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní služby poskytovatele podmínky. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"navázat se na službu spořiče"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Umožňuje navázání na nejvyšší úroveň služby spořiče. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolat konfigurační aplikaci poskytnutou operátorem"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Umožňuje aplikaci měnit parametry kalibrace dotykové obrazovky. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"přístup k certifikátům DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Umožňuje aplikaci vydávat a používat certifikáty DRM. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Příjem vysílání pro předání spojení"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Povoluje příjem informací o stavu předání spojení."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Příjem stavu přenosů Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Umožňuje této aplikaci přijímat informace o aktuálních přenosech pomocí technologie Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Řídit délku hesel pro odemčení obrazovky a povolené znaky."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Umožňuje aplikaci upravit historii prohlížeče nebo záložky uložené v telefonu. Aplikace s tímto oprávněním může vymazat či pozměnit data prohlížeče. Poznámka: Pro prohlížeče třetí strany a jiné aplikace umožňující procházení webu toto oprávnění platit nemusí."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"nastavení budíku"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Umožňuje aplikaci nastavit budík v nainstalované aplikaci budík. Některé aplikace budík tuto funkci nemusí obsahovat."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"odstraňování hlasových zpráv"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Povoluje aplikaci odstraňovat zprávy z hlasové schránky."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"správa hlasových zpráv"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Povoluje aplikaci upravit a odebrat zprávy z hlasové schránky."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"přidat hlasovou zprávu"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Umožňuje aplikaci přidávat zprávy do hlasové schránky."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"číst všechny hlasové zprávy"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"I"</string>
<string name="capital_off" msgid="6815870386972805832">"O"</string>
<string name="whichApplication" msgid="4533185947064773386">"Dokončit akci pomocí aplikace"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Vyberte domovskou aplikaci"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Použít jako výchozí nastavení pro tuto činnost."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Výchozí nastavení vymažete v sekci Nastavení systému > Aplikace > Stažené."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Povolit vždy"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nepovolit nikdy"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM karta odebrána"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mobilní síť bude dostupná až poté, co vložíte platnou SIM kartu a restartujete zařízení."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Hotovo"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM karta přidána."</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Mobilní síť bude přístupná po restartu zařízení."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Restartovat"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastavení času"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavení data"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Vybrána položka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Číslice <xliff:g id="KEY">%1$s</xliff:g> byla smazána"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Pracovní <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Nacházíte se v režimu Uzamčení v aplikaci."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Použít Uzamčení v aplikaci?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Funkce Uzamčení v aplikaci uzamkne obrazovku na jedinou aplikaci.\n\nChcete-li tento režim opustit, stiskněte a podržte tlačítko posledních aplikací $."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NE"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"SPUSTIT"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Spustit Uzamčení v aplikaci"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Opustit Uzamčení v aplikaci"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 30e6dec..9de76a6 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Tillader, at appen kan skrive til sms-beskeder, der er gemt på din telefon eller dit SIM-kort. Ondsindede apps kan slette dine beskeder."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"modtage tekstbeskeder (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Tillader, at appen kan modtage og behandle WAP-beskeder. Denne tilladelse omfatter muligheden for at overvåge eller slette de beskeder, der sendes til dig, uden at vise dem til dig."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"modtage Bluetooth-beskeder (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Tillader, at appen kan modtage og behandle Bluetooth MAP-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"hente kørende apps"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Tillader, at appen kan hente oplysninger om nuværende og seneste opgaver. Med denne tilladelse kan appen finde oplysninger om, hvilke applikationer der bruges på enheden."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"kommunikere på tværs af brugere"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"imiterede placeringskilder til test"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Opret imiterede placeringskilder til test, eller installer en ny placeringsudbyder. Med denne tilladelse kan appen tilsidesætte den placering og/eller status, der returneres af andre placeringskilder, f.eks. GPS eller placeringsudbydere."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"få adgang til yderligere kommandoer for placeringsudbyder"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Tillader, at appen kan få adgang til yderligere kommandoer for placeringsudbydere. Dette bevirker muligvis, at appen kan forstyrre GPS-funktionen eller andre placeringskilder."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Tillader, at appen kan få adgang til yderligere kommandoer for placeringsudbydere. Dette kan gøre det muligt for appen at forstyrre GPS-funktionen eller andre placeringskilder."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"tilladelse til at installere en placeringsudbyder"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Opret imiterede placeringskilder til test, eller installer en ny placeringsudbyder. Herved kan appen tilsidesætte den placering og/eller status, der returneres af andre placeringskilder, som f.eks. GPS eller placeringsudbydere."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"præcis placering (GPS- og netværksbaseret)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Tillader, at appen kan administrere netværkspolitikker og definere appspecifikke regler."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"skift afregning af netværksbrug"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Tillader, at appen kan ændre den måde, som netværksforbrug udregnes på i forhold til apps. Anvendes ikke af normale apps."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"ændre socketmærker"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Tillader, at appen ændrer socketmærker ved omdirigering"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"adgang til underretninger"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillader, at appen kan hente, undersøge og rydde underretninger, f.eks. dem, der er sendt af andre apps."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"forpligte sig til en underretningslyttertjeneste"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Tillader brugeren at forpligte sig til en underretningslyttertjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"oprette binding til en tjeneste til formidling af betingelser"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Tillader, at brugeren opretter en binding til det øverste niveau af grænsefladen i en tjeneste til formidling af betingelser. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"fastlås til en drømmetjeneste"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Tillader, at indehaveren fastlåser det øverste niveau af brugergrænsefladen for en drømmetjeneste. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"aktivere konfigurationsappen, der leveres af mobilselskabet"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Tillader, at appen ændrer kalibreringsparametrene for berøringsskærmen. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"få adgang til DRM-certifikater"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Tillader, at en applikation leverer og anvender DRM-certfikater. Dette bør aldrig være nødvendigt for almindelige apps."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Modtag overdragelse af udsendelser."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Tillader modtagelse af statusoplysninger om overdragelse."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Modtag staus for Android Beam-overførsler"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Tillader, at applikationen modtager oplysninger om aktuelle Android Beam-overførsler"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærmen."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Tillader, at appen kan ændre browserens historik eller de bogmærker, der er gemt på din telefon. Dette kan give appen tilladelse til at slette eller ændre browserdata. Bemærk! Denne tilladelse håndhæves muligvis ikke af tredjepartsbrowsere eller andre applikationer med websøgningsfunktioner."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"indstille en alarm"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Tillader, at appen kan indstille en alarm i en installeret alarmapp. Nogle alarmapps har muligvis ikke denne funktion."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"fjern talebeskeder"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Tillader, at appen fjerner beskeder fra indbakken for din telefonsvarer."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"administrer beskeder i telefonsvareren"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Tillader, at appen ændrer og fjerner beskeder fra indbakken for din telefonsvarer."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"tilføje telefonsvarer"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Tillader, at appen kan tilføje beskeder på din telefonsvarer."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"læs alle talebeskeder"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"TIL"</string>
<string name="capital_off" msgid="6815870386972805832">"FRA"</string>
<string name="whichApplication" msgid="4533185947064773386">"Brug"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Vælg en startapp"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Brug som standard til denne handling."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Ryd standard i Systemindstillinger > Apps > Downloadet."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Tillad altid"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Tillad aldrig"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort blev fjernet"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile netværk er utilgængeligt, indtil du genstarter med et gyldigt SIM-kort."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Afslut"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-kort blev tilføjet"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Genstart din enhed for at få adgang til mobilnetværket."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Genstart"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Angiv tidspunkt"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Angiv dato"</string>
@@ -1376,7 +1392,7 @@
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Angiv en tillidsagent."</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Tillader, at en applikation angiver en tillidsagent."</string>
<string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Åbn indstillingsmenuen for trust agent."</string>
- <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"Tillader, at en app starter en aktivitet, der ændrer adfærden for en betroet agent."</string>
+ <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"Tillader, at en app starter en aktivitet, der ændrer adfærden for trust agent."</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Knytte sig til en trust agent-tjeneste"</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Tillader, at en applikation knytter sig til en trust agent-tjeneste."</string>
<string name="permlab_recovery" msgid="3157024487744125846">"Interager med opdaterings- og gendannelsessystemet"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> er valgt"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> – arbejde"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Vil du bruge Lås-til-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Med Lås-til-app låses skærmen, så den kun viser én app.\n\nHvis du vil afslutte denne tilstand, skal du trykke på knappen for seneste apps og holde fingeren nede $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NEJ"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Du bruger tilstanden Lås-til-app."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Vil du bruge Bliv i app?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Start Lås-til-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Afslut Lås-til-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index c09a80e..285fd78 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Ermöglicht der App, auf Ihrem Telefon oder Ihrer SIM-Karte gespeicherte SMS zu bearbeiten. Schädliche Apps können so Ihre Nachrichten löschen."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"Textnachrichten (WAP) empfangen"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Ermöglicht der App, WAP-Nachrichten zu empfangen und zu verarbeiten. Mit der Berechtigung können Nachrichten, die an Sie gesendet wurden, überwacht und gelöscht werden, bevor sie Ihnen angezeigt werden."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth-Nachrichten (MAP) empfangen"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Ermöglicht der App, Bluetooth MAP-Mitteilungen zu empfangen und zu verarbeiten. Das bedeutet, dass die App an Ihr Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie Ihnen anzuzeigen."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"Aktive Apps abrufen"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Ermöglicht der App, Informationen zu aktuellen und kürzlich ausgeführten Aufgaben abzurufen. Damit kann die App möglicherweise ermitteln, welche Apps auf Ihrem Gerät zum Einsatz kommen."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Nutzerübergreifend interagieren"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"Simulierte Standortquellen für Testzwecke"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Erstellen von simulierten Standortquellen für Testzwecke oder Installation eines neuen Standortanbieters. Damit kann die App den von anderen Standortquellen wie GPS oder Standortanbietern zurückgegebenen Standort und/oder Status überschreiben."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"Auf zusätzliche Dienstanbieterbefehle für Standort zugreifen"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Ermöglicht der App, auf zusätzliche Standortanbieterbefehle zuzugreifen. Damit könnte die App die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ermöglicht der App, auf zusätzliche Standortanbieterbefehle zuzugreifen. Damit könnte die App die Funktionsweise von GPS oder anderen Standortquellen beeinträchtigen."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"Berechtigung zur Installation eines Standortanbieters"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Erstellen von simulierten Standortquellen für Testzwecke oder Installation eines neuen Standortanbieters. Damit kann die App den von anderen Standortquellen wie GPS oder Standortanbietern zurückgegebenen Standort und/oder Status überschreiben."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"Genauer Standort (GPS- und netzwerkbasiert)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Ermöglicht der App, Netzwerkrichtlinien zu verwalten und anwendungsspezifische Regeln festzulegen"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Zuordnung für Netzwerknutzung ändern"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ermöglicht der App, die Art und Weise zu ändern, wie der Netzwerkverbrauch im Hinblick auf Apps berechnet wird. Nicht für normale Apps vorgesehen."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"Socket-Markierungen ändern"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Ermöglicht der App das Ändern von Socket-Markierungen für das Routing"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"Auf Benachrichtigungen zugreifen"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Ermöglicht der App das Abrufen, Überprüfen und Löschen von Benachrichtigungen, einschließlich Benachrichtigungen, die von anderen Apps gepostet wurden"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"An Benachrichtigungs-Listener-Dienst binden"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ermöglicht dem Inhaber, sich an die Oberfläche der obersten Ebene eines Benachrichtigungs-Listener-Dienstes zu binden. Sollte nie für normale Apps benötigt werden."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"An einen Bedingungsproviderdienst binden"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Bedingungsproviderdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"An Dream-Dienst binden"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Ermöglicht der App, sich an die Oberfläche eines Dream-Dienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufrufen"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Ermöglicht der App, die Kalibrierungsparameter des Touchscreens zu ändern. Für normale Apps sollte dies nie erforderlich sein."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Auf DRM-Zertifikate zugreifen"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Ermöglicht einer App die Bereitstellung und Nutzung von DRM-Zertifikaten. Sollte für normale Apps nie benötigt werden."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Handover-Übertragungen empfangen"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Ermöglicht das Empfangen von Informationen zum Handover-Übertragungsstatus"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Status von Android Beam-Übertragungen erhalten"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Ermöglicht dieser App, Informationen zu aktuellen Android Beam-Übertragungen zu erhalten"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Bildschirms festlegen"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Ermöglicht der App, den Browserverlauf und die Lesezeichen auf Ihrem Telefon zu ändern. Damit kann die App Browserdaten löschen und ändern. Hinweis: Diese Berechtigung kann nicht von Browsern von Drittanbietern oder anderen Apps mit Internetfunktionen erzwungen werden."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"Wecker stellen"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Ermöglicht der App, einen Alarm in einer installierten Wecker-App einzurichten. Einige Wecker-Apps implementieren diese Funktion möglicherweise nicht."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"Mailboxnachrichten entfernen"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Ermöglicht der App das Entfernen von Nachrichten aus Ihrer Mailbox"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"Mailbox-Nachrichten verwalten"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Ermöglicht dieser App, Nachrichten im Posteingang Ihrer Mailbox zu ändern und zu entfernen"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"Mailbox-Nachrichten hinzufügen"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ermöglicht der App, Nachrichten zu Ihrem Mailbox-Posteingang hinzuzufügen"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"Alle Mailboxnachrichten abrufen"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"AN"</string>
<string name="capital_off" msgid="6815870386972805832">"AUS"</string>
<string name="whichApplication" msgid="4533185947064773386">"Aktion durchführen mit"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Start-App auswählen"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Immer für diese Aktion verwenden"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Das Löschen der Standardeinstellungen ist in den Systemeinstellungen unter \"Apps > Heruntergeladen\" möglich."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Immer zulassen"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nie zulassen"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-Karte entfernt"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Das Mobilfunknetz ist erst wieder verfügbar, wenn Sie einen Neustart mit einer gültigen SIM-Karte durchführen."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Fertig"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-Karte hinzugefügt"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Starten Sie zur Nutzung des Mobilfunknetzes Ihr Gerät neu."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Neu starten"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Uhrzeit festlegen"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum festlegen"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ausgewählt"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> gelöscht"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Sie befinden sich im App-Verriegelungsmodus."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"App-Verriegelung verwenden?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Durch die App-Verriegelung bleibt das Display auf eine App fixiert.\n\nZum Beenden halten Sie die Schaltfläche \"Kürzlich geöffnete Apps\" $ gedrückt."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"Nein"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"Starten"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"App-Verriegelung anwenden"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"App-Verriegelung beenden"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 64cb918..112fdd7 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Επιτρέπει στην εφαρμογή την εγγραφή σε μηνύματα SMS που είναι αποθηκευμένα στο τηλέφωνό σας ή στην κάρτα SIM. Τυχόν κακόβουλες εφαρμογές ενδέχεται να διαγράψουν τα μηνύματά σας."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"λήψη μηνυμάτων κειμένου (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων WAP. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Λήψη μηνυμάτων Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων MAP Bluetooth. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"ανάκτηση εκτελούμενων εφαρμογών"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Επιτρέπει στην εφαρμογή την ανάκτηση πληροφοριών σχετικά με τρέχουσες και πρόσφατα εκτελούμενες εργασίες. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να ανακαλύπτει πληροφορίες σχετικά με το ποιες εφαρμογές χρησιμοποιούνται στη συσκευή."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"αλληλεπίδραση στους χρήστες"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"δημιουργία ψευδών πηγών τοποθεσίας για δοκιμή"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Δημιουργεί ψευδείς πηγές τοποθεσίας για τη δοκιμή ή την εγκατάσταση νέου παρόχου τοποθεσίας. Αυτό δίνει τη δυνατότητα στην εφαρμογή να παρακάμψει την τοποθεσία και/ή την κατάσταση που επιστρέφεται από άλλες πηγές τοποθεσίας, όπως το GPS ή οι πάροχοι τοποθεσίας."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Επιτρέπει στην εφαρμογή την πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας. Αυτό μπορεί να δώσει τη δυνατότητα στην εφαρμογή να παρέμβει στη λειτουργία του GPS ή άλλων πηγών τοποθεσίας."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Επιτρέπει στην εφαρμογή την πρόσβαση σε επιπλέον εντολές παρόχου τοποθεσίας. Αυτό μπορεί να δώσει τη δυνατότητα στην εφαρμογή να παρέμβει στη λειτουργία του GPS ή άλλων πηγών τοποθεσίας."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"άδεια για εγκατάσταση ενός παρόχου τοποθεσίας"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Δημιουργεί ψευδείς πηγές τοποθεσίας για τη δοκιμή ή την εγκατάσταση νέου παρόχου τοποθεσίας. Αυτό δίνει τη δυνατότητα στην εφαρμογή να παρακάμπτει την τοποθεσία και/ή την κατάσταση που επιστρέφεται από άλλες πηγές τοποθεσίας, όπως το GPS ή οι πάροχοι τοποθεσίας."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ακριβής θέση (GPS και βάσει δικτύου)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Επιτρέπει στην εφαρμογή τη διαχείριση των πολιτικών δικτύου και τον ορισμό κανόνων για ορισμένες εφαρμογές."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"τροποποίηση υπολογισμού χρήσης δικτύου"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Επιτρέπει στην εφαρμογή την τροποποίηση του τρόπου υπολογισμού της χρήσης δικτύου έναντι των εφαρμογών. Δεν προορίζεται για χρήση από συνήθεις εφαρμογές."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"τροποποίηση σημείων υποδοχής"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Επιτρέπει στην εφαρμογή την τροποποίηση σημείων υποδοχής για δρομολόγηση"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"πρόσβαση στις ειδοποιήσεις"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Επιτρέπει στην εφαρμογή να ανακτά, να εξετάζει και να απαλείφει ειδοποιήσεις, συμπεριλαμβανομένων εκείνων που δημοσιεύονται από άλλες εφαρμογές."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"δέσμευση σε υπηρεσία ακρόασης ειδοποίησης"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας ακρόασης ειδοποιήσεων. Δεν απαιτείται σε κανονικές εφαρμογές."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"σύνδεση σε μια υπηρεσία παρόχου συνθηκών"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανωτάτου επιπέδου ενός παρόχου συνθηκών. Δεν απαιτείται για κανονικές εφαρμογές."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"δέσμευση σε υπηρεσία dream"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας dream. Δεν απαιτείται σε κανονικές εφαρμογές."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"κλήση της εφαρμογής διαμόρφωσης που παρέχεται από την εταιρεία κινητής τηλεφωνίας"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Επιτρέπει στην εφαρμογή να τροποποιεί τις παραμέτρους βαθμονόμησης της οθόνης αφής. Δεν απαιτείται για τις κανονικές εφαρμογές."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"πρόσβαση σε πιστοποιητικά DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Επιτρέπει σε μια εφαρμογή να παρέχει και να χρησιμοποιεί πιστοποιητικά DRM. Δεν θα χρειαστεί ποτέ για κανονικές εφαρμογές."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Λήψη εκπομπών μεταφοράς παράδοσης."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Επιτρέπει τη λήψη πληροφοριών κατάστασης μεταφοράς παράδοσης."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Λήψη κατάστασης μεταφοράς Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Επιτρέπει σε αυτήν την εφαρμογή να λαμβάνει πληροφορίες σχετικά με τις τρέχουσες μεταφορές Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Επιτρέπει στην εφαρμογή την τροποποίηση του ιστορικού του προγράμματος περιήγησης ή των σελιδοδεικτών που έχουν αποθηκευτεί στο τηλέφωνό σας. Αυτό μπορεί να δίνει τη δυνατότητα στην εφαρμογή να διαγράφει ή να τροποποιεί δεδομένα του προγράμματος περιήγησης. Σημείωση: αυτή η άδεια ίσως να μην μπορεί να εφαρμοστεί από τρίτα προγράμματα περιήγησης ή άλλες εφαρμογές με δυνατότητες περιήγησης ιστού."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"ρύθμιση ξυπνητηριού"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Επιτρέπει στην εφαρμογή τη ρύθμιση μιας ειδοποίησης σε μια εγκατεστημένη εφαρμογή ξυπνητηριού. Ορισμένες εφαρμογές ξυπνητηριού ενδέχεται να μην μπορούν να ενσωματώσουν αυτήν τη λειτουργία."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"κατάργηση μηνυμάτων αυτόματου τηλεφωνητή"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Επιτρέπει στην εφαρμογή να καταργεί μηνύματα από τα εισερχόμενα του αυτόματου τηλεφωνητή σας."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"διαχείριση φωνητικών μηνυμάτων"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Επιτρέπει στην εφαρμογή να τροποποιεί και να καταργεί τα μηνύματα από τα Εισερχόμενα του τηλεφωνητή σας."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"προσθήκη τηλεφωνητή"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Επιτρέπει στην εφαρμογή να προσθέτει μηνύματα στα εισερχόμενα του αυτόματου τηλεφωνητή σας."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ανάγνωση όλων των μηνυμάτων του αυτόματου τηλεφωνητή"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"Ενεργό"</string>
<string name="capital_off" msgid="6815870386972805832">"Ανενεργό"</string>
<string name="whichApplication" msgid="4533185947064773386">"Ολοκλήρωση ενέργειας με τη χρήση"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Επιλέξτε μια εφαρμογή από την αρχική οθόνη"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Χρήση από προεπιλογή για αυτήν την ενέργεια."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Εκκθάριση προεπιλογής στις Ρυθμίσεις συστήματος > Εφαρμογές > Ληφθείσες."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Να επιτρέπεται πάντα"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Να μην επιτρέπεται ποτέ"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Η κάρτα SIM αφαιρέθηκε"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Το δίκτυο κινητής τηλεφωνίας δεν θα είναι διαθέσιμο μέχρι να κάνετε επανεκκίνηση αφού τοποθετήσετε μια έγκυρη κάρτα SIM."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Τέλος"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Προστέθηκε κάρτα SIM"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Επανεκκινήστε τη συσκευή σας για να αποκτήσετε πρόσβαση στο δίκτυο κινητής τηλεφωνίας."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Επανεκκίνηση"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Ρύθμιση ώρας"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Ορισμός ημερομηνίας"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Επιλέχτηκε το στοιχείο <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> διαγράφηκε"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Βρίσκεστε στη λειτουργία Lock-to-App."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Χρήση λειτουργίας lock-to-app;"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Η λειτουργία Lock-to-app κλειδώνει την οθόνη σε μία μόνο εφαρμογή.\n\nΓια έξοδο πατήστε παρατεταμένα το κουμπί των πρόσφατων εφαρμογών $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"ΟΧΙ"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ΕΝΑΡΞΗ"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Έναρξη Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Έξοδος από Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index d2dd109..5c89860 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"mock location sources for testing"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Create mock location sources for testing or install a new location provider. This allows the app to override the location and/or status returned by other location sources such as GPS or location providers."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"access extra location provider commands"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"permission to install a location provider"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Create mock location sources for testing or install a new location provider. This allows the app to override the location and/or status returned by other location sources such as GPS or location providers."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"precise location (GPS and network-based)"</string>
@@ -713,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Allows the app to manage network policies and define app-specific rules."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modify network usage accounting"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Allows the app to modify how network usage is accounted against apps. Not for use by normal apps."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modify socket marks"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Allows the app to modify socket marks for routing"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"access notifications"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Allows the app to retrieve, examine, and clear notifications, including those posted by other apps."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind to a notification listener service"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind to a condition provider service"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"bind to a media route service"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Allows the holder to bind to the top-level interface of a media route service. Should never be needed for normal apps."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"bind to a dream service"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoke the carrier-provided configuration app"</string>
@@ -731,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"access DRM certificates"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Allows an application to provision and use DRM certficates. Should never be needed for normal apps."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Receive handover transfer broadcasts."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Allows receiving handover transfer status information."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Receive Android Beam transfer status"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Allows this application to receive information about current Android Beam transfers"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -1006,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Allows the app to modify the Browser\'s history or bookmarks stored on your phone. This may allow the app to delete or modify Browser data. Note: this permission may not be enforced by third-party browsers or other applications with web browsing capabilities."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"set an alarm"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Allows the app to set an alarm in an installed alarm clock app. Some alarm clock apps may not implement this feature."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"remove voicemails"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Allows the app to remove messages from your voicemail inbox."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"manage voicemails"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Allows the app to modify and remove messages from your voicemail inbox."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"add voicemail"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Allows the app to add messages to your voicemail inbox."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"read all voicemail"</string>
@@ -1179,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"ON"</string>
<string name="capital_off" msgid="6815870386972805832">"OFF"</string>
<string name="whichApplication" msgid="4533185947064773386">"Complete action using"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"Complete action using %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Open with"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Open with %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Edit with"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit with %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Share with"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Share with %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Select a home app"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Use by default for this action."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Clear default in System settings > Apps > Downloaded."</string>
@@ -1281,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Always Allow*"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Never Allow"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM card removed"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"The mobile network will be unavailable until you restart with a valid SIM card inserted."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"The mobile network will be unavailable until you restart with a valid SIM card inserted."</string>
<string name="sim_done_button" msgid="827949989369963775">"Done"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM card added"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Restart your device to access the mobile network."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Restart your device to access the mobile network."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Restart"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
@@ -1735,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Use lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app locks the display in a single app.\n\nTo exit press and hold the recent apps button $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"You are in Lock-to-App mode."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Use Lock-to-app?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Start Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Exit Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index d2dd109..5c89860 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"mock location sources for testing"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Create mock location sources for testing or install a new location provider. This allows the app to override the location and/or status returned by other location sources such as GPS or location providers."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"access extra location provider commands"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Allows the app to access extra location provider commands. This may allow the app to interfere with the operation of the GPS or other location sources."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"permission to install a location provider"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Create mock location sources for testing or install a new location provider. This allows the app to override the location and/or status returned by other location sources such as GPS or location providers."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"precise location (GPS and network-based)"</string>
@@ -713,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Allows the app to manage network policies and define app-specific rules."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modify network usage accounting"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Allows the app to modify how network usage is accounted against apps. Not for use by normal apps."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modify socket marks"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Allows the app to modify socket marks for routing"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"access notifications"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Allows the app to retrieve, examine, and clear notifications, including those posted by other apps."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind to a notification listener service"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind to a condition provider service"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"bind to a media route service"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Allows the holder to bind to the top-level interface of a media route service. Should never be needed for normal apps."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"bind to a dream service"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoke the carrier-provided configuration app"</string>
@@ -731,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Allows the app to modify the calibration parameters of the touch screen. Should never be needed for normal apps."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"access DRM certificates"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Allows an application to provision and use DRM certficates. Should never be needed for normal apps."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Receive handover transfer broadcasts."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Allows receiving handover transfer status information."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Receive Android Beam transfer status"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Allows this application to receive information about current Android Beam transfers"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
@@ -1006,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Allows the app to modify the Browser\'s history or bookmarks stored on your phone. This may allow the app to delete or modify Browser data. Note: this permission may not be enforced by third-party browsers or other applications with web browsing capabilities."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"set an alarm"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Allows the app to set an alarm in an installed alarm clock app. Some alarm clock apps may not implement this feature."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"remove voicemails"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Allows the app to remove messages from your voicemail inbox."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"manage voicemails"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Allows the app to modify and remove messages from your voicemail inbox."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"add voicemail"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Allows the app to add messages to your voicemail inbox."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"read all voicemail"</string>
@@ -1179,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"ON"</string>
<string name="capital_off" msgid="6815870386972805832">"OFF"</string>
<string name="whichApplication" msgid="4533185947064773386">"Complete action using"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"Complete action using %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Open with"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Open with %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Edit with"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit with %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Share with"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Share with %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Select a home app"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Use by default for this action."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Clear default in System settings > Apps > Downloaded."</string>
@@ -1281,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Always Allow*"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Never Allow"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM card removed"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"The mobile network will be unavailable until you restart with a valid SIM card inserted."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"The mobile network will be unavailable until you restart with a valid SIM card inserted."</string>
<string name="sim_done_button" msgid="827949989369963775">"Done"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM card added"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Restart your device to access the mobile network."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Restart your device to access the mobile network."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Restart"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
@@ -1735,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Use lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app locks the display in a single app.\n\nTo exit press and hold the recent apps button $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"You are in Lock-to-App mode."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Use Lock-to-app?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Start Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Exit Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index dbc57f46e..60978d1 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Permite que la aplicación escriba en mensajes SMS almacenados en tu dispositivo o tarjeta SIM. Las aplicaciones maliciosas pueden eliminar tus mensajes."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"recibir mensajes de texto (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite que la aplicación reciba y procese mensajes WAP, lo que significa que podría controlar o eliminar mensajes enviados al usuario sin mostrártelos."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Recibir mensajes por Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Permite que la aplicación reciba y procese mensajes por Bluetooth (MAP), lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"recuperar aplicaciones en ejecución"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que la aplicación recupere información sobre las tareas que se estén ejecutando en ese momento o que se hayan ejecutado recientemente. La aplicación puede utilizar este permiso para descubrir cuáles son las aplicaciones que se utilizan en el dispositivo."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Interactuar con los usuarios"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"crear fuentes de ubicación de prueba"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Permite crear fuentes de ubicación simuladas para hacer pruebas o instalar un nuevo proveedor de ubicación. Esto autoriza a la aplicación a sobrescribir la ubicación o el estado proporcionados por otras fuentes de ubicación, como los proveedores de ubicación o GPS."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"acceder a comandos adicionales del proveedor del lugar"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite que la aplicación acceda a comandos adicionales del proveedor de ubicación. Esto puede permitirle a la aplicación interferir con el funcionamiento del GPS o de otras fuentes de ubicación."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que la aplicación acceda a comandos adicionales del proveedor de ubicación. Esto puede permitirle a la aplicación interferir con el funcionamiento del GPS o de otras fuentes de ubicación."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorización para instalar un proveedor de ubicación"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Permite crear fuentes de ubicación simuladas para hacer pruebas o instalar un nuevo proveedor de ubicación. Este permiso autoriza a la aplicación a sobrescribir la ubicación o el estado proporcionados por otras fuentes de ubicación, como los proveedores de ubicación o GPS."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ubicación precisa (según el GPS y la red)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite que la aplicación administre las políticas de red y defina reglas específicas de la aplicación."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Modificar la administración del uso de redes"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que la aplicación modifique cómo se registra el uso de red en relación con las aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modificar marcas de socket"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permite que la aplicación modifique marcas de socket para enrutamiento."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"acceder a las notificaciones"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y elimine notificaciones, incluidas aquellas publicadas por otras aplicaciones."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"Vincular a un servicio de agente de escucha de notificaciones"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite al propietario vincularse a la interfaz de nivel superior de un servicio de agente de escucha de notificaciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vincular con un servicio de proveedor de condiciones"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite vincular con la interfaz de nivel superior de un servicio de proveedor de condiciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"vincularse a un servicio de protector de pantalla interactivo"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Permite al propietario vincularse a la interfaz de nivel superior de un servicio de protector de pantalla interactivo. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ejecutar la aplicación de configuración proporcionada por el proveedor"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite que la aplicación modifique los parámetros de calibración de la pantalla táctil. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Acceder a certificados DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite que una aplicación proporcione y utilice certificados DRM. Las aplicaciones normales no deberían necesitar este permiso."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Recibir emisiones de transferencia de la conexión"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Permite recibir información sobre el estado de transferencia de la conexión."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Recibir estado de transferencias de Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Permite que esta aplicación reciba información sobre las transferencias actuales de Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que la aplicación modifique el historial o los marcadores del navegador almacenados en el dispositivo. La aplicación puede utilizar este permiso para borrar o modificar los datos del navegador. Nota: Este permiso no puede ser utilizado por navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"programar una alarma"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de alarma instalada. Es posible que algunas aplicaciones de alarma no incluyan esta función."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"eliminar mensajes del buzón de voz"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Permite que la aplicación elimine mensajes de la bandeja de entrada del buzón de voz."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"administrar mensajes del buzón de voz"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Permite que la aplicación modifique y elimine mensajes de la bandeja de entrada del buzón de voz."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"agregar correo de voz"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que la aplicación agregue mensajes a la bandeja de entrada de tu buzón de voz."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"Consultar todos los mensajes del buzón de voz"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"Sí"</string>
<string name="capital_off" msgid="6815870386972805832">"No"</string>
<string name="whichApplication" msgid="4533185947064773386">"Completar la acción mediante"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Seleccionar una aplicación de la pantalla principal"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utilizar de manera predeterminada en esta acción."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Eliminar valores predeterminados en Configuración del sistema > Aplicaciones > Descargas."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permitir siempre"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"No permitir nunca"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Tarjeta SIM eliminada"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"La red para celulares no estará disponible hasta que reinicies, luego de insertar una tarjeta SIM válida."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Finalizar"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Tarjeta SIM agregada"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Reinicia el dispositivo para acceder a la red móvil."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Configurar hora"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Configurar fecha"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> borrado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Estás en el modo de bloqueo de aplicación."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"¿Usar bloqueo de aplicación?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"El bloqueo de aplicación bloquea la pantalla en una sola aplicación.\n\nPara salir, mantén presionado el botón de aplicaciones recientes $."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"INICIAR"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Iniciar bloqueo de aplicación"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Salir de bloqueo de aplicación"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 551e83f..b5c2c1f 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Permite que la aplicación escriba en mensajes SMS almacenados en el teléfono o en la tarjeta SIM. Las aplicaciones malintencionadas pueden borrar los mensajes."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"recibir mensajes de texto (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite que la aplicación reciba y procese mensajes WAP, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al usuario sin mostrárselos."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"recibir mensajes por Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Permite que la aplicación reciba y procese mensajes por Bluetooth (MAP), lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"recuperar aplicaciones en ejecución"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que aplicación recupere información sobre tareas que se están ejecutando en ese momento o que se han ejecutado recientemente. La aplicación puede utilizar este permiso para descubrir cuáles son las aplicaciones que se utilizan en el dispositivo."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interactuar con los usuarios"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"simular fuentes de ubicación para prueba"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Permite crear fuentes de ubicación simuladas para hacer pruebas o instalar un nuevo proveedor de ubicación. Este permiso autoriza a la aplicación a sobrescribir la ubicación o el estado proporcionados por otras fuentes de ubicación, como los proveedores de ubicación o GPS."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"acceder a comandos de proveedor de ubicación adicional"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Este permiso autoriza a la aplicación a acceder a comandos adicionales del proveedor de ubicación y puede permitirle interferir en el funcionamiento del GPS o de otras fuentes de ubicación."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que la aplicación acceda a otros comandos del proveedor de ubicación. De esta forma, la aplicación podrá interferir en el funcionamiento del GPS o de otras fuentes de ubicación."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"permiso para instalar un proveedor de ubicación"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Permite crear fuentes de ubicación simuladas para hacer pruebas o instalar un nuevo proveedor de ubicación. Este permiso autoriza a la aplicación a sobrescribir la ubicación o el estado proporcionados por otras fuentes de ubicación, como los proveedores de ubicación o GPS."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ubicación precisa (basada en red y GPS)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite que la aplicación administre políticas de red y defina reglas específicas de la aplicación."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar cálculo de uso de red"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que la aplicación modifique cómo se registra el uso de red en relación con las aplicaciones. Las aplicaciones normales no deben usar este permiso."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modificar marcas de socket"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permite que la aplicación modifique marcas de socket para enrutamiento"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"acceder a las notificaciones"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y borre notificaciones, incluidas las que han publicado otras aplicaciones."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"enlazar con un servicio de detector de notificaciones"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite enlazar con la interfaz de nivel superior de un servicio de detector de notificaciones. No debe ser necesario para las aplicaciones normales."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"enlazar con un servicio de proveedor de condiciones"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite enlazar con la interfaz de nivel superior de un servicio de proveedor de condiciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"enlazar con un servicio de salvapantallas"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Permite enlazar con la interfaz de nivel superior de un servicio de salvapantallas. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ejecutar la aplicación de configuración proporcionada por el operador"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite que la aplicación modifique los parámetros de calibración de la pantalla táctil. No debe ser necesario para las aplicaciones normales."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"acceder a certificados DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite que una aplicación proporcione y utilice certificados DRM. Las aplicaciones normales no deberían necesitar este permiso."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Recibe emisiones de la transferencia de la conexión."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Permite recibir información sobre el estado de la transferencia de la conexión."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Recibir estado de transferencias de Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Permite que esta aplicación reciba información sobre las transferencias actuales de Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que la aplicación modifique el historial o los marcadores del navegador almacenados en el teléfono. La aplicación puede utilizar este permiso para borrar o modificar datos del navegador. Nota: este permiso no pueden utilizarlo navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"establecer una alarma"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de reloj instalada. Es posible que algunas aplicaciones de reloj no incluyan esta función."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"eliminar mensajes de voz"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Permite que la aplicación elimine mensajes de la bandeja de entrada del buzón de voz."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"administrar mensajes de voz"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Permite que la aplicación modifique y elimine mensajes de la bandeja de entrada del buzón de voz."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"añadir buzón de voz"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que la aplicación añada mensajes a la bandeja de entrada del buzón de voz."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"consultar todos los mensajes de voz"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"SÍ"</string>
<string name="capital_off" msgid="6815870386972805832">"NO"</string>
<string name="whichApplication" msgid="4533185947064773386">"Completar acción utilizando"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Seleccionar una aplicación en la pantalla de inicio"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Usar siempre para esta acción"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Para borrar los valores predeterminados, accede a Ajustes del sistema > Aplicaciones > Descargadas."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permitir siempre"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"No permitir nunca"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Tarjeta SIM eliminada"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"La red móvil no estará disponible hasta que reinicies el dispositivo con una tarjeta SIM válida."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Listo"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Tarjeta SIM añadida"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Reinicia el dispositivo para acceder a la red móvil."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Establecer hora"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Establecer fecha"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"¿Usar bloqueo de aplicación?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"El bloqueo de aplicación bloquea la pantalla en una sola aplicación.\n\nPara salir, mantén pulsado el botón de aplicaciones recientes $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Estás en el modo Bloqueo de aplicación."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"¿Usar Bloqueo de aplicación?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"INICIAR"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Iniciar bloqueo de aplicación"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Salir del bloqueo de aplicación"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 429f921..26e163a 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Võimaldab rakendusel kirjutada teie telefoni või SIM-kaardile salvestatud SMS-sõnumitesse. Pahatahtlikud rakendused võivad teie sõnumid kustutada."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"võtke vastu tekstisõnumeid (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Võimaldab rakendusel vastu võtta ja töödelda WAP-sõnumeid. See luba hõlmab võimet jälgida või kustutada teile saadetud sõnumeid neid teile näitamata."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetoothi sõnumite vastuvõtmine (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Võimaldab rakendusel vastu võtta ja töödelda Bluetoothi MAP-sõnumeid. See tähendab, et rakendus saab teie seadmesse saadetud sõnumeid jälgida või kustutada ilma neid teile näitamata."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"Käitatud rakenduste toomine"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Võimaldab rakendusel tuua teavet praegu ja hiljuti käitatud ülesannete kohta. See võib lubada rakendusel avastada teavet selle kohta, milliseid rakendusi seadmes kasutatakse."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"toimingud erinevatel kasutajakontodel"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"võltsasukohad testimiseks"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Looge võltsasukoha allikaid, et katsetada või installida uut asukohapakkujat. See lubab rakendusel tühistada teiste asukohaallikate, näiteks GPS-i või asukohapakkujate tagastatud asukoha ja/või oleku."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"juurdepääs asukohapakkuja lisakäskudele"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Võimaldab rakendusel pääseda juurde asukohapakkuja erikäskudele. See võib lubada rakendusel segada GPS-i või muude asukohaallikate tööd."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Võimaldab rakendusel juurde pääseda asukohapakkuja erikäskudele. See võib lubada rakendusel mõjutada GPS-i või muude asukohaallikate tööd."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"luba asukohapakkuja installimiseks"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Looge võltsasukoha allikaid, et katsetada või installida uut asukohapakkujat. See lubab rakendusel tühistada teiste asukohaallikate, näiteks GPS-i või asukohapakkujate tagastatud asukoha ja/või oleku."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"täpne asukoht (GPS- ja võrgupõhine)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Võimaldab rakendusel hallata võrgueeskirju ja määratleda rakendusespetsiifilisi reegleid."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"võrgukasutuse arvestamise muutmine"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Võimaldab rakendusel muuta võrgukasutuse loendamist rakenduste suhtes. Mitte kasutada tavarakenduste puhul."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"sokli märkide muutmine"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Lubab rakendusel muuta marsruutimiseks sokli märke"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"juurdepääsu märguanded"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Võimaldab rakendusel tuua, kontrollida ja kustutada märguandeid, sh neid, mille on postitanud teised rakendused."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"seo märguannete kuulamisteenusega"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Võimaldab omanikul siduda märguannete kuulamisteenuse ülemise taseme kasutajaliidese. Seda ei tohiks tavarakenduste puhul kunagi vaja olla."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"seo tingimuse pakkuja teenusega"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Lubab omanikul siduda tingimuse pakkuja teenuse ülataseme liidesega. Pole kunagi vajalik tavaliste rakenduste puhul."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"sidumine uneteenusega"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Lubab omanikul siduda uneteenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"operaatoripoolse konfiguratsioonirakenduse aktiveerimine"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lubab rakendusel muuta puuteekraani kalibreerimisparameetreid. Ei tohiks kunagi olla vajalik tavaliste rakenduste puhul."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"juurdepääs DRM-i sertifikaatidele"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Lubab rakendusel ette valmistada ja kasutada DRM-i sertifikaate. Tavarakenduste puhul ei tohiks see vajalik olla."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Üleandmise edastuste vastuvõtmine"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Võimaldab vastu võtta üleandmise olekuteavet."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Android Beami ülekande oleku vastuvõtmine"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Lubab rakendusel saada teavet praeguste Android Beami ülekannete kohta"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrollige ekraaniluku avamise paroolide pikkust ja tähemärke."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekraani avamiskatsed"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Võimaldab rakendusel muuta telefoni salvestatud brauseri ajalugu või järjehoidjaid. See võimaldab rakendusel kustutada või muuta brauseri andmeid. Märkus: see luba ei pruugi jõustuda kolmanda osapoole brauserites või teistes veebisirvimisvõimega rakendustes."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"määrake äratus"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Võimaldab rakendusel seada installitud äratuskellarakenduses äratuse. Mõned äratuskellarakendused ei pruugi seda funktsiooni juurutada."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"kõnepostisõnumite eemaldamine"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Võimaldab rakendusel teie kõneposti postkastist sõnumeid eemaldada."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"kõneposti haldamine"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Lubab rakendusel muuta ja kustutada kõneposti postkasti sõnumeid."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"lisa kõneposti"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Võimaldab rakendusel lisada sõnumeid teie kõneposti postkasti."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"kogu kõneposti lugemine"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"SEES"</string>
<string name="capital_off" msgid="6815870386972805832">"VÄLJAS"</string>
<string name="whichApplication" msgid="4533185947064773386">"Lõpetage toiming rakendusega"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Avalehe rakenduse valimine"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Kasuta vaikimisi selleks toiminguks."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Tühjendage vaikeandmed valikutes Süsteemiseaded > Rakendused > Allalaaditud."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Luba alati"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ära luba"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-kaart eemaldatud"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mobiilsidevõrk ei ole saadaval, kuni sisestate kehtiva SIM-kaardi ja taaskäivitate seadme."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Valmis"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-kaart lisatud"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Mobiilsidevõrku pääsemiseks taaskäivitage seade."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Taaskäivita"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Kellaaja määramine"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Kuupäeva määramine"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> on valitud"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> on kustutatud"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Töö <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Kas soovite kasutada rakendusele lukustamist?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Rakendusele lukustamise funktsioon lukustab kuva ühele rakendusele.\n\nVäljumiseks hoidke hiljutiste rakenduste nuppu $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"EI"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Seade on režiimis Rakendusele lukustamine."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Kas soovite kasutada Rakendusele lukustamist?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"KÄIVITA"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Käivita rakendusele lukustamine"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Välju rakendusele lukustamisest"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 10cd1fb..3760e33 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -257,7 +257,7 @@
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"بازیابی محتوای پنجره"</string>
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"محتوای پنجرهای را که در حال تعامل با آن هستید بررسی کنید."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"فعالسازی کاوش لمسی"</string>
- <string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"موارد لمس شده با صدای بلند خوانده میشوند و با استفاده از حرکات لمسی میتوانید صفحه را کاوش کنید."</string>
+ <string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"موارد لمس شده با صدای بلند خوانده میشوند و با استفاده از حرکات میتوانید صفحه را کاوش کنید."</string>
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"فعالسازی دسترسپذیری پیشرفته برای وب"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"ممکن است جهت افزایش دسترسپذیری به محتوای برنامه، اسکریپتهایی نصب شود."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"نوشتاری را که تایپ میکنید مشاهده نمایید"</string>
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"به برنامه اجازه میدهد تا در پیامهای کوتاه ذخیره شده در تلفن یا سیم کارت بنویسد. برنامههای مخرب میتوانند پیامهای شما را حذف کنند."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"دریافت پیامهای نوشتاری (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"به برنامه اجازه میدهد پیامهای WAP را دریافت و پردازش کند. این مجوز میتواند پیامهای ارسالی به شما را بدون نمایش آنها به شما حذف یا کنترل کند."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"دریافت پیامهای بلوتوث (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"به برنامه اجازه میدهد پیامهای بلوتوث MAP را دریافت و پردازش کند. این یعنی برنامه میتواند پیامهای ارسالی به دستگاه شما را بدون نمایش آنها به شما حذف یا کنترل کند."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"بازیابی برنامههای در حال اجرا"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"به برنامه امکان میدهد اطلاعات مربوط به کارهای در حال اجرای اخیر و کنونی را بازیابی کند. این ممکن است به برنامه امکان دهد به اطلاعات مربوط به برنامههایی که در دستگاه استفاده میشوند دست یابد."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"ارتباط بین کاربران"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"منابع مکان کاذب برای تست"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائهدهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان میدهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائهدهندگان موقعیت مکانی را نادیده بگیرد."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"دسترسی به فرمانهای بیشتر ارائه دهنده مکان"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"به برنامه اجازه میدهد تا به فرمانهای ارائهدهنده موقعیت مکانی دیگری دسترسی داشته باشد. این ویژگی ممکن است باعث مختل شدن عملکرد GPS یا دیگر منابع موقعیت مکانی توسط این برنامه شود."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"به برنامه اجازه میدهد به دستورات ارائهدهنده مکان تکمیلی دسترسی داشته باشد. این کار ممکن است به برنامه امکان دهد با کارکرد GPS یا منابع دیگر مکان تداخل داشته باشد."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"مجوز برای نصب یک ارائه دهنده مکان"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"منابع موقعیت مکانی کاذب را برای تست کردن یا نصب یک ارائهدهنده موقعیت مکانی جدید ایجاد نمایید. این کار به برنامه امکان میدهد موقعیت مکانی و/یا وضعیت گزارش داده شده توسط سایر منابع موقعیت مکانی مانند GPS یا ارائهدهندگان موقعیت مکانی را نادیده بگیرد."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"موقعیت مکانی دقیق (مبتنی بر GPS و شبکه)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"به برنامه اجازه میدهد تا خط مشیهای شبکه را مدیریت کند و قوانین خاص برنامه را تعیین کند."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"اصلاح محاسبه استفاده از شبکه"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"به برنامه اجازه میدهد تا نحوه محاسبه کاربرد شبکه در برنامه را تغییر دهد. برای استفاده برنامههای عادی نیست."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"تغییر علائم سوکت"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"به برنامه اجازه میدهد برای مسیریابی علائم سوکت را تغییر دهد."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"اعلانهای دسترسی"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"به برنامه اجازه میدهد به بازیابی، بررسی و پاک کردن اعلانها از جمله موارد پست شده توسط سایر برنامهها بپردازد."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"اتصال به یک سرویس شنونده اعلان"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"به دارنده اجازه میدهد به یک رابط سطح بالای سرویس شنونده اعلان متصل شود. هرگز نباید برای برنامههای عادی لازم شود."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"مقید بودن به سرویس ارائهدهنده وضعیت"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"به دارنده امکان میدهد تا به واسط سطح بالای سرویس ارائهدهنده وضعیت مقید باشد. برای برنامههای عادی هرگز نباید لازم باشد."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"اتصال به سرویس مورد نظر"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"به برنامه اجازه میدهد که به رابط سطح بالای سرویس مورد نظر متصل شود. هرگز نباید برای برنامههای معمولی مورد نیاز باشد."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"لغو برنامه پیکربندی ارائه شده توسط شرکت مخابراتی"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"به برنامه امکان میدهد پارامترهای کالیبراسیون صفحه لمسی را تغییر دهد. هرگز نباید برای برنامههای عادی مورد نیاز باشد."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"دسترسی به گواهیهای DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"به یک برنامه کاربردی اجازه ارائه مجوز و استفاده از گواهیهای DRM را میدهد. هرگز برای برنامههای عادی مورد نیاز نیست."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"دریافت پخشهای انتقال تحویلی."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"دریافت اطلاعات وضعیت انتقالی را ممکن میسازد."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"دریافت وضعیت انتقال پرتوی Android"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"به برنامه امکان میدهد تا اطلاعاتی درباره انتقالهای کنونی پرتوی Android به دست آورد"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"طول و نویسههای مجاز در گذرواژههای بازکردن قفل صفحه را کنترل کنید."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاشهای قفل گشایی صفحه"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"به برنامه اجازه میدهد سابقه مرورگر یا نشانکهای ذخیره شده در تلفن شما را اصلاح کند. این ویژگی ممکن است به برنامه اجازه دهد دادههای مرورگر را حذف یا اصلاح کند. توجه: این مجوز ممکن است توسط مرورگرهای شخص ثالث یا سایر برنامههای دارای قابلیت مرور وب قابل اجرا نباشد."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"تنظیم یک هشدار"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"به برنامه اجازه میدهد تا هشداری را در برنامه ساعت زنگدار نصب شده تنظیم کند. برخی از برنامههای ساعت زنگدار نمیتوانند این ویژگی را اعمال کنند."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"حذف پستهای صوتی"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"به برنامه امکان میدهد پیامها را از صندوق ورودی پست صوتی شما حذف کند."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"مدیریت پستهای صوتی"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"به برنامه امکان میدهد پیامها را از صندوق ورودی پست صوتی شما تغییر داده و حذف کند."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"افزودن پست صوتی"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"به برنامه اجازه میدهد تا پیامها را به صندوق دریافت پست صوتی شما اضافه کند."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"خواندن کل پست صوتی"</string>
@@ -1044,8 +1044,8 @@
<string name="searchview_description_submit" msgid="2688450133297983542">"ارسال عبارت جستجو"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"جستجوی صوتی"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"فعال کردن «کاوش با لمس»؟"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> میخواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، میتوانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از رایانهٔ لوحی از حرکات اشاره استفاده کنید."</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> میخواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، میتوانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از تلفن خود از حرکات اشاره استفاده کنید."</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> میخواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، میتوانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از رایانهٔ لوحی از حرکات استفاده کنید."</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> میخواهد «کاوش با لمس» را فعال کند. وقتی «کاوش با لمس» فعال است، میتوانید توضیحاتی را برای آنچه که زیر انگشت شما است مشاهده کرده یا بشنوید یا برای استفاده از تلفن خود از حرکات استفاده کنید."</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"۱ ماه قبل"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"قبل از ۱ ماه گذشته"</string>
<plurals name="num_seconds_ago">
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"روشن"</string>
<string name="capital_off" msgid="6815870386972805832">"خاموش"</string>
<string name="whichApplication" msgid="4533185947064773386">"تکمیل عملکرد با استفاده از"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"انتخاب یک برنامه صفحه اصلی"</string>
<string name="alwaysUse" msgid="4583018368000610438">"استفاده به صورت پیشفرض برای این عملکرد."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"پیشفرض را در تنظیمات سیستم> برنامهها> مورد دانلود شده پاک کنید."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"همیشه مجاز"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"همیشه غیرمجاز"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"سیم کارت برداشته شد"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"تا وقتی که با یک سیمکارت معتبر راهاندازی مجدد نکنید شبکهٔ تلفن همراه غیر قابل دسترس خواهد بود."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"انجام شد"</string>
<string name="sim_added_title" msgid="3719670512889674693">"سیم کارت اضافه شد"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"برای دسترسی به شبکهٔ تلفن همراه، دستگاه خود را مجدداً راهاندازی کنید."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"راهاندازی مجدد"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"تنظیم زمان"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ تنظیم"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> انتخاب شد"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> حذف شد"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> محل کار"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"از «قفل برنامه» استفاده شود؟"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"«قفل برنامه» نمایشگر را در یک برنامه قفل میکند.\n\nبرای خروج، دکمه برنامههای جدید $ را فشار داده و نگهدارید"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"خیر"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"در حالت «قفل به برنامه» هستید."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"از «قفل به برنامه» استفاده شود؟"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"شروع"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"راهاندازی «قفل برنامه»"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"خروج از «قفل برنامه»"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 11b35d6..0892093 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"imitoi sijaintilähteitä testaustarkoituksissa"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Luo imitoituja sijaintilähteitä testaustarkoituksessa tai asenna uusi sijaintipalvelu. Sovellus voi ohittaa muiden sijaintilähteiden kuten GPS:n ja sijaintipalveluiden palauttaman sijainnin ja/tai tilan."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"käytä lisää sijainnintarjoajakomentoja"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Antaa sovelluksen käyttää ylimääräisiä sijaintipalvelukomentoja. Sovellus voi käyttää tätä GPS:n tai muun sijaintilähteen toiminnan häiritsemiseen."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Antaa sovelluksen käyttää ylimääräisiä sijaintipalvelukomentoja. Sovellus saattaa tällöin häiritä GPS:n tai muiden sijaintilähteiden toimintaa."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"asenna sijainnintarjoaja"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Luo imitoituja sijaintilähteitä testaustarkoituksessa tai asenna uusi sijaintipalvelu. Sovellus voi ohittaa muiden sijaintilähteiden kuten GPS:n ja sijaintipalveluiden palauttaman sijainnin ja/tai tilan."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"tarkka sijainti (GPS- ja verkkopohjainen)"</string>
@@ -713,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Sallii sovelluksen hallinnoida verkkokäytäntöjä ja määritellä sovelluskohtaisia sääntöjä."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"verkon käytön seurannan muokkaaminen"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Antaa sovelluksen muokata, miten sovellusten verkonkäyttöä lasketaan. Ei tavallisten sovellusten käyttöön."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"Pistokemerkkien muokkaaminen"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Antaa sovelluksen muokata reitityksen pistokemerkkejä"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"käytä ilmoituksia"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Antaa sovelluksen noutaa, tutkia ja tyhjentää ilmoituksia (myös muiden sovelluksien lähettämiä)."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"sido ilmoituskuuntelijapalveluun"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Antaa sovelluksen sitoutua ilmoituskuuntelijan ylimmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ehtojen toimituspalveluun sitominen"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Antaa sovelluksen luoda sidoksen ehtojen toimituspalvelun ylätason rajapintaan. Ei tavallisten sovelluksien käyttöön."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"sitoudu Unelma-palveluun"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Antaa sovelluksen sitoutua Unelma-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Palveluntarjoajan määrityssovelluksen käynnistäminen"</string>
@@ -731,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Antaa sovelluksen muokata kosketusnäytön kalibrointiparametreja. Ei tavallisten sovellusten käyttöön."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM-varmenteiden käyttö"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Antaa sovelluksen käyttää DRM-varmenteita ja hallita niiden käyttäjiä. Ei tavallisten sovellusten käyttöön."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Vastaanota handover-siirtolähetyksiä."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Sallii handover-siirtotietojen vastaanottamisen."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Vastaanota Android Beam -siirron tilatietoja"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Antaa sovelluksen vastaanottaa tietoja nykyisistä Android Beam -siirroista"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
@@ -1006,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Antaa sovelluksen muokata selaimen historiaa ja puhelimeen tallennettuja kirjanmerkkejä. Sovellus voi poistaa tai muokata selaimen tietoja. Huomaa: kolmannen osapuolen selaimet tai muut sovellukset, jotka pystyvät selaamaan verkkoa, eivät saa käyttää tätä lupaa."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"aseta herätys"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Antaa sovelluksen asettaa hälytyksen sisäiseen herätyskellosovellukseen. Jotkin herätyskellosovellukset eivät välttämättä käytä tätä ominaisuutta."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"vastaajaviestien poistaminen"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Antaa sovelluksen poistaa viestejä saapuneista vastaajaviesteistä."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"vastaajaviestien hallinta"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Antaa sovelluksen muokata ja poistaa puhelinvastaajaan saapuneita viestejä."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"lisää vastaajaviesti"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Antaa sovelluksen lisätä viestejä saapuneisiin vastaajaviesteihin."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"kaikkien vastaajaviestien luku"</string>
@@ -1179,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"PÄÄLLÄ"</string>
<string name="capital_off" msgid="6815870386972805832">"POIS"</string>
<string name="whichApplication" msgid="4533185947064773386">"Tee toiminto käyttäen sovellusta"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Valitse aloitusruutusovellus"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Käytä oletuksena tälle toiminnolle."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Poista oletusasetus kohdassa Järjestelmäasetukset > Sovellukset > Ladattu."</string>
@@ -1281,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Salli aina"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Älä koskaan salli"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-kortti poistettu"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mobiiliverkko ei ole käytettävissä, ennen kuin käynnistät uudelleen kelvollisella laitteeseen kytketyllä SIM-kortilla."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Valmis"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-kortti lisätty"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Muodosta mobiiliverkkoyhteys käynnistämällä laite uudelleen."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Käynnistä uudelleen"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Aseta aika"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Aseta päivämäärä"</string>
@@ -1373,10 +1391,8 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"Antaa sovelluksen seurata luottamuksen tilamuutoksia."</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Luotettavan tahon tarjoaminen"</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Antaa sovelluksen tarjota luotettavan tahon."</string>
- <!-- no translation found for permlab_launch_trust_agent_settings (5859430082240410200) -->
- <skip />
- <!-- no translation found for permdesc_launch_trust_agent_settings (8185142708644913381) -->
- <skip />
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Luotettavan tahon asetusvalikon käynnistäminen"</string>
+ <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"Antaa sovelluksen käynnistää toiminnon, joka muuttaa luotettavan tahon käyttäytymistä."</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Luotettavaan tahoon sitoutuminen"</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Antaa sovelluksen sitoutua luotettavaan tahoon."</string>
<string name="permlab_recovery" msgid="3157024487744125846">"Vuorovaikutus päivitys- ja palautusjärjestelmän kanssa"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> on valittu"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> poistettiin"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (työ)"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Olet Sovellukseen lukitus -tilassa."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Käytetäänkö sovellukseen lukitusta?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Sovellukseen lukitus lukitsee näytön yhteen sovellukseen.\n\nPoistu pitämällä viimeaikaisten sovellusten painiketta $ painettuna."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"EI"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ALOITA"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Aloita sovellukseen lukitus"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Lopeta sovellukseen lukitus"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 0d3fd3d..29fc52a 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Permet à l\'application de modifier les SMS stockés sur votre téléphone ou sur votre carte SIM. Des applications malveillantes peuvent exploiter cette fonctionnalité pour supprimer vos messages."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"recevoir des messages WAP"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permet à l\'application de recevoir et de traiter les messages WAP. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"recevoir des messages par Bluetooth (profil MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Permet à l\'application de recevoir et traiter des messages par Bluetooth à l\'aide du profil MAP. Cela signifie que l\'application peut contrôler ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"récupérer les données des applications en cours d\'exécution"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Permet à l\'application de récupérer des données sur des tâches en cours d\'exécution et récemment exécutées. L\'application est ainsi susceptible d\'obtenir des données concernant les applications utilisées sur l\'appareil."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interagir entre les utilisateurs"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"créer des sources de localisation fictives à des fins de test"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Permet de créer des sources de localisation fictives à des fins de tests ou pour installer un nouveau fournisseur de position. L\'application peut ainsi modifier la position ou l\'état renvoyé par d\'autres sources de localisation telles que le GPS ou les fournisseurs de position."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accéder aux commandes de fournisseur de position géographique supplémentaires"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permet à l\'application d\'accéder à des commandes de fournisseur de position supplémentaires. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permet à l\'application d\'accéder à des commandes de localisation supplémentaires offertes par le fournisseur. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorisation d\'installer un fournisseur de services de localisation"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Permet de créer des sources de localisation fictives à des fins de tests ou pour installer un nouveau fournisseur de position. L\'application peut ainsi modifier la position ou l\'état renvoyé par d\'autres sources de localisation telles que le GPS ou les fournisseurs de position."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"position précise (GPS et réseau)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permet à l\'application de gérer les politiques du réseau et de définir celles propres à l\'application"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifier le système d\'analyse de l\'utilisation du réseau"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permet à l\'application de modifier le système d\'analyse de l\'utilisation du réseau par les autres applications. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modifier les marques d\'interface de connexion"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permet à l\'application de modifier les marques d\'interface de connexion pour le routage"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"accéder aux notifications"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet aux applications de récupérer, d\'examiner et d\'autoriser les notifications, y compris celles envoyées par d\'autres applications."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications. Ne devrait jamais être nécessaire pour les applications normales."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"s\'associer à un service de fournisseur de conditions"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service de fournisseur de conditions. Ne devrait pas être nécessaire pour les applications standards."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"associer à un service de rêve"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service de rêve. Les applications standard ne devraient pas avoir recours à cette fonctionnalité."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"faire appel à l\'application de configuration du fournisseur de services"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permet à l\'application de modifier les paramètres de calibrage de l\'écran tactile. Ne devrait jamais être nécessaire pour les applications standards."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accéder aux certificats GDN"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permet à une application de fournir et d\'utiliser les certificats de GDN. Cela ne devrait jamais être nécessaire pour les applications normales."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Recevoir des données concernant l\'état des transferts."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Autoriser la réception de données concernant l\'état des transferts."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Recevoir des données sur l\'état du transfert Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Autoriser cette application à recevoir des données sur les transferts Android Beam en cours"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permet à l\'application de modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Cette autorisation peut lui permettre d\'effacer ou de modifier les données du navigateur. Remarque : il est possible que cette autorisation ne soit pas appliquée par les navigateurs tiers ni par d\'autres applications permettant de naviguer sur le Web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"définir une alarme"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Permet à l\'application de régler la sonnerie d\'une fonction de réveil installée sur votre appareil. Cette fonctionnalité n\'est pas compatible avec toutes les applications de réveils."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"supprimer des messages vocaux"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Permet à l\'application de supprimer des messages de votre messagerie vocale."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"gérer les messages vocaux"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Autoriser l\'application à modifier et à supprimer des messages de la boîte de réception des messages vocaux."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"ajouter des messages vocaux"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permet à l\'application d\'ajouter des messages à votre messagerie vocale."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"accéder à tous les messages vocaux"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"OUI"</string>
<string name="capital_off" msgid="6815870386972805832">"NON"</string>
<string name="whichApplication" msgid="4533185947064773386">"Continuer avec"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Sélectionnez une application de l\'écran d\'accueil"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utiliser cette application par défaut pour cette action"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Pour supprimer les valeurs par défaut, accédez à Paramètres système > Applications > Téléchargements."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Toujours autoriser"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ne jamais autoriser"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Carte SIM retirée"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Le réseau mobile ne sera pas disponible avant le redémarrage avec une carte SIM valide insérée."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Terminé"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Carte SIM ajoutée."</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Redémarrez votre appareil pour accéder au réseau mobile."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Recommencer"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Définir l\'heure"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Définir la date"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"« <xliff:g id="ITEM">%1$s</xliff:g> » a été sélectionné"</string>
<string name="deleted_key" msgid="7659477886625566590">"« <xliff:g id="KEY">%1$s</xliff:g> » a été supprimé"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Utiliser la fonctionnalité de verrouillage sur l\'application?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"La fonctionnalité « Verrouiller sur l\'application » verrouille l\'écran sur une seule application.\n\nPour quitter ce mode, maintenez le doigt sur le bouton Applications récentes $."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NON"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Vous êtes en mode « Verrouiller sur l\'application »."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Utiliser la fonctionnalité « Verrouiller sur l\'application »?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"COMMENCER"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Lancer Verrouiller sur l\'application"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Quitter Verrouiller sur l\'application"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 4a712aa..8b80a96 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Permet à l\'application de modifier les SMS stockés sur votre téléphone ou sur votre carte SIM. Des applications malveillantes peuvent exploiter cette fonctionnalité pour supprimer vos messages."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"recevoir des messages texte (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permet à l\'application de recevoir et de traiter les messages WAP. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Recevoir des messages Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Permet à l\'application de recevoir et traiter des messages MAP Bluetooth. Cela signifie que l\'application peut contrôler ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"récupérer les applications en cours d\'exécution"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Permet à l\'application de récupérer des informations sur des tâches en cours d\'exécution et récemment exécutées. L\'application est ainsi susceptible d\'obtenir des informations sur les applications utilisées sur l\'appareil."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interagir entre les utilisateurs"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"Création de sources de localisation fictives à des fins de test"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Permet de créer des sources de localisation fictives à des fins de tests ou pour installer un nouveau fournisseur de position. L\'application peut ainsi modifier la position et/ou l\'état renvoyé par d\'autres sources de localisation telles que le GPS ou les fournisseurs de position."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"Accès aux commandes de fournisseur de position géographique supplémentaires"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permet à l\'application d\'accéder à des commandes de fournisseur de position supplémentaires. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permet à l\'application d\'accéder à des commandes de localisation supplémentaires offertes par le fournisseur. Elle est ainsi susceptible d\'interférer avec le bon fonctionnement du GPS ou de toute autre source de localisation."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"autoriser l\'installation d\'un fournisseur de services de localisation"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Permet de créer des sources de localisation fictives à des fins de tests ou pour installer un nouveau fournisseur de position. L\'application peut ainsi modifier la position et/ou l\'état renvoyé par d\'autres sources de localisation telles que le GPS ou les fournisseurs de position."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"position précise (GPS et réseau)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permet à l\'application de gérer les stratégies du réseau et de définir celles qui sont spécifiques à l\'application."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifier le système de comptabilisation de l\'utilisation du réseau"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permet à l\'application de modifier l\'utilisation du réseau par les autres applications. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modifier les marques de sockets"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permet à l\'application de modifier les marques de sockets pour les redirections."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"accéder aux notifications"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet aux applications de récupérer, d\'examiner et d\'autoriser les notifications, y compris celles envoyées par d\'autres applications."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications. Ne devrait jamais être nécessaire pour les applications normales."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"s\'associer à un service de fournisseur de conditions"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service de fournisseur de conditions. Ne devrait pas être nécessaire pour les applications standards."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"associer à un service d\'écran de veille interactif"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service d\'écran de veille interactif. Cette autorisation ne devrait jamais être nécessaire pour les applications standards."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"faire appel à l\'application de configuration fournie par l\'opérateur"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permettre à l\'application de modifier les paramètres de calibrage de l\'écran tactile. Ne devrait jamais être nécessaire pour les applications standards."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accéder aux certificats de GDN"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permettre à une application de fournir et d\'utiliser des certificats de GDN. Ne devrait jamais être nécessaire pour les applications standards."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Recevoir des informations concernant l\'état du transfert"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Autoriser la réception d\'informations concernant l\'état du transfert"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Recevoir des informations sur l\'état du transfert Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Autoriser cette application à recevoir des informations sur les transferts Android Beam en cours"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permet à l\'application de modifier l\'historique du navigateur ou les favoris enregistrés sur votre téléphone. Cette autorisation peut lui permettre d\'effacer ou de modifier les données du navigateur. Remarque : il est possible que cette autorisation ne soit pas appliquée par les navigateurs tiers ni par d\'autres applications permettant de naviguer sur le Web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"définir une alarme"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Permet à l\'application de régler la sonnerie d\'un réveil installé. Cette fonctionnalité n\'est pas disponible sur tous les réveils."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"supprimer des messages vocaux"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Autoriser l\'application à supprimer des messages de votre messagerie vocale"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"gérer les messages vocaux"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Autoriser l\'application à modifier et à supprimer des messages de la boîte de réception des messages vocaux"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"ajouter un message vocal"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permet à l\'application d\'ajouter des messages à votre messagerie vocale."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"accéder à tous les messages vocaux"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"OUI"</string>
<string name="capital_off" msgid="6815870386972805832">"NON"</string>
<string name="whichApplication" msgid="4533185947064773386">"Continuer avec"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Sélectionner une application de l\'écran d\'accueil"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utiliser cette application par défaut pour cette action"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Pour supprimer les valeurs par défaut, accédez à Paramètres système > Applications > Téléchargements."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Toujours autoriser"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ne jamais autoriser"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Carte SIM retirée"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Le réseau mobile ne sera pas disponible avant le redémarrage avec une carte SIM valide insérée."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"OK"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Carte SIM ajoutée."</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Redémarrez votre appareil pour accéder au réseau mobile."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Redémarrer"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Définir l\'heure"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Définir la date"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"\"<xliff:g id="ITEM">%1$s</xliff:g>\" sélectionné"</string>
<string name="deleted_key" msgid="7659477886625566590">"\"<xliff:g id="KEY">%1$s</xliff:g>\" supprimé"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Vous êtes en mode \"Verrouiller sur l\'application\"."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Utiliser la fonctionnalité Verrouiller sur l\'application ?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"La fonctionnalité Verrouiller sur l\'application verrouille l\'écran sur une seule application.\n\nPour quitter ce mode, appuyez de manière prolongée sur le bouton Applications récentes $."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NON"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ACTIVER"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Activer Verrouiller sur l\'application"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Désactiver Verrouiller sur l\'application"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 8fb9e30..ea99dd7 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"ऐप्स को आपके फ़ोन या सिम कार्ड में संग्रहीत SMS संदेशों को लिखने देता है. दुर्भावनापूर्ण ऐप्स आपके संदेशों को हटा सकते हैं."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"पाठ संदेश (WAP) प्राप्त करें"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"ऐप्स को WAP संदेशों को प्राप्त और संसाधित करने देता है. इस अनुमति में आपको भेजे गए संदेशों की निगरानी आपको दिखाए बिना करने और हटाने की क्षमता शामिल है."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth संदेश प्राप्त करें (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"ऐप्स को Bluetooth MAP संदेशों को प्राप्त करने और भेजने देती है. इसका अर्थ है कि ऐप्स आपके उपकरण पर भेजे गए संदेशों को आपको दिखाए बिना ही मॉनीटर कर सकता है या उन्हें हटा सकता है."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"चल रहे ऐप्स पुनर्प्राप्त करें"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"ऐप्स को वर्तमान में और हाल ही में चल रहे कार्यों के बारे में जानकारी को पुन: प्राप्त करने देता है. इससे ऐप्स उपकरण पर उपयोग किए गए ऐप्स के बारे में जानकारी खोज सकता है."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"उपयोगकर्ताओं के बीच सहभागिता करें"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"परीक्षण के लिए नकली स्थान स्रोत"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"परीक्षण के लिए कृत्रिम स्थान स्रोत बनाएं या एक नया स्थान प्रदाता इंस्टॉल करें. यह ऐप्स को स्थान और/या अन्य स्थान स्रोतों जैसे GPS या स्थान प्रदाताओं द्वारा लौटाई गई स्थिति को ओवरराइड करने देता है."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"अतिरिक्त स्थान प्रदाता आदेशों में पहुंचे"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"ऐप्स को अतिरिक्त स्थान प्रदाता आदेशों पर पहुंचने देता है. यह ऐप्स को GPS या अन्य स्थान स्रोतों के संचालन में बाधा पहुंचाने दे सकता है."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ऐप्स को अतिरिक्त स्थान प्रदाता आदेशों पर पहुंचने देती है. इससे ऐप्स GPS या अन्य स्थान स्रोतों के संचालन में अवरोध पहुंचा सकता है."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"किसी स्थान प्रदाता को इंस्टॉल करने की अनुमति"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"परीक्षण के लिए कृत्रिम स्थान स्रोत बनाएं या एक नए स्थान प्रदाता को इंस्टॉल करें. यह ऐप्स को स्थान और/या अन्य स्थान स्रोतों जैसे GPS या स्थान प्रदाताओं द्वारा लौटाई गई स्थिति को ओवरराइड करने देता है."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"सटीक स्थान (GPS और नेटवर्क-आधारित)"</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ऐप्स को नेटवर्क नीतियां प्रबंधित करने और ऐप्स-विशिष्ट नियमों को परिभाषित करने देता है."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"नेटवर्क उपयोग हिसाब बदलें"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ऐप्स को यह संशोधित करने देता है कि ऐप्स की तुलना में नेटवर्क उपयोग का मूल्यांकन कैसे किया जाता है. सामान्य ऐप्स द्वारा उपयोग करने के लिए नहीं."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"सॉकेट मार्क बदलें"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"ऐप्स को रूटिंग के लिए सॉकेट मार्क बदलने देता है"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"सूचनाओं तक पहुंचें"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स को सूचनाओं को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"सूचना श्रवणकर्ता सेवा से जुड़ें"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को सूचना श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"किसी स्थिति प्रदाता सेवा से आबद्ध हों"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"धारक को किसी स्थिति प्रदाता सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"मीडिया रूट सेवा से आबद्ध हों"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"धारक को मीडिया रूट सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"भावी सेवा से आबद्ध करें"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"धारक को किसी भावी सेवा के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"वाहक के द्वारा उपलब्ध कराया गया कॉन्फ़िगरेशन ऐप्स प्रारंभ करें"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"ऐप्स को टच स्क्रीन के कैलिब्रेशन पैरामीटर को बदलने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM प्रमाणपत्र एक्सेस करें"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"ऐप्लिकेशन को DRM प्रमाणपत्रों का प्रावधान और उपयोग करने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यकता नहीं होना चाहिए."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"हस्तांतरण स्थानान्तरण प्राप्त करें."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"हस्तांतरण स्थानान्तरण स्थिति की जानकारी प्राप्त करने देती है."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Android Beam स्थानान्तरण स्थिति प्राप्त करें"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"इस ऐप्लिकेशन को वर्तमान Android Beam स्थानान्तरणों के बारे में जानकारी प्राप्त करने देती है."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करें"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"स्क्रीन-अनलॉक पासवर्ड में अनुमति प्राप्त लंबाई और वर्णों को नियंत्रित करें."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"स्क्रीन-अनलॉक के प्रयासों पर निगरानी रखें"</string>
@@ -1008,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ऐप्स को आपके फ़ोन में संग्रहीत ब्राउज़र के इतिहास या बुकमार्क को संशोधित करने देता है. इससे ऐप्स ब्राउज़र डेटा को मिटा सकता है या संशोधित कर सकता है. ध्यान दें: यह अनुमति तृतीय-पक्ष ब्राउज़र या वेब ब्राउज़िंग क्षमताओं वाले अन्य ऐप्स द्वारा लागू नहीं की जा सकती."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"अलार्म सेट करें"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"ऐप्स को इंस्टॉल किए गए अलार्म घड़ी ऐप्स में अलार्म सेट करने देता है. हो सकता है कुछ अलार्म घड़ी ऐप्स में यह सुविधा न हो."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"ध्वनिमेल निकालें"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"ऐप्स को आपके ध्वनिमेल इनबॉक्स में से संदेशों को निकालने देती है."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"ध्वनिमेल प्रबंधित करें"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"ऐप्स को आपके ध्वनिमेल इनबॉक्स के संदेशों को बदलने या निकालने देती है."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"ध्वनिमेल जोड़ें"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"ऐप्स को आपके ध्वनिमेल इनबॉक्स में संदेश जोड़ने देता है."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"सभी ध्वनिमेल पढ़ें"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"चालू"</string>
<string name="capital_off" msgid="6815870386972805832">"बंद"</string>
<string name="whichApplication" msgid="4533185947064773386">"इसका उपयोग करके क्रिया पूर्ण करें"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s का उपयोग करके कार्रवाई पूर्ण करें"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"इसमें खोलें"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s में खोलें"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"इसके द्वारा संपादित करें"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s से संपादित करें"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"इससे साझा करें"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s से साझा करें"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"होम ऐप्लिकेशन चुनें"</string>
<string name="alwaysUse" msgid="4583018368000610438">"इस क्रिया के लिए डिफ़ॉल्ट रूप से उपयोग करें."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"सिस्टम सेटिंग > Apps > डाउनलोड किए गए में डिफ़ॉल्ट साफ करें."</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"हमेशा अनुमति दें"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"कभी भी अनुमति न दें"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"सिमकार्ड निकाला गया"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"मान्य सिम कार्ड डालकर पुन: प्रारंभ करने तक मोबाइल नेटवर्क अनुपलब्ध रहेगा."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"जब तक आप मान्य SIM कार्ड डालकर पुन: प्रारंभ नहीं करते, तब तक सेल्युलर नेटवर्क अनुपलब्ध रहेगा."</string>
<string name="sim_done_button" msgid="827949989369963775">"पूर्ण"</string>
<string name="sim_added_title" msgid="3719670512889674693">"सिम कार्ड जोड़ा गया"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"मोबाइल नेटवर्क पर पहुंचने के लिए अपना उपकरण पुन: प्रारंभ करें."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"सेल्युलर नेटवर्क एक्सेस करने के लिए अपना उपकरण पुन: प्रारंभ करें."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"पुन: प्रारंभ करें"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"समय सेट करें"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"दिनांक सेट करें"</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> चयनित"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> को हटा दिया गया"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्यस्थल का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"आप ऐप्स-पर-लॉक करें मोड में हैं."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"ऐप्स-पर-लॉक करें का उपयोग करें?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"ऐप्स-पर-लॉक करें, डिस्प्ले को किसी एकल ऐप्स में लॉक कर देता है.\n\nबाहर निकलने के लिए हाल ही के ऐप्स बटन $ को दबाए रखें"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"नहीं"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"प्रारंभ करें"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"ऐप्स-पर-लॉक करें प्रारंभ करें"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"ऐप्स-पर-लॉक करें से बाहर निकलें"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f3d62b2..a7f07a9 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Omogućuje aplikaciji pisanje u SMS poruke pohranjene na telefonu ili SIM kartici. Zlonamjerne aplikacije mogu izbrisati vaše poruke."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"primanje tekstnih poruka (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Aplikaciji omogućuje primanje i obradu WAP poruka. Ta dozvola uključuje mogućnost nadziranja ili brisanja vama poslanih poruka, a da vam ih ne prikaže."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"primaj Bluetooth poruke (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Aplikaciji omogućuje primanje i obradu Bluetooth MAP poruka. To znači da aplikacija može nadzirati ili brisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"dohvaćanje pokrenutih aplikacija"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Aplikaciji omogućuje dohvaćanje informacija o trenutačnim i nedavnim tekućim zadacima. To aplikaciji može omogućiti otkrivanje informacija o tome koje se aplikacije upotrebljavaju na uređaju."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakcija među korisnicima"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"omogućeno testiranje izvora lokacije"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Stvaranje lažnih izvora lokacije radi testiranja ili za instaliranje novog pružatelja usluga lokacije. To aplikaciji omogućuje zaobilaženje lokacije i/ili statusa koji vraćaju drugi izvori lokacije, primjerice GPS ili pružatelji usluga lokacije."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"pristup dodatnim naredbama davatelja lokacije"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Aplikaciji omogućuje pristup dodatnim naredbama za pružatelja usluga lokacije. To aplikaciji može omogućiti ometanje rada GPS-a ili drugih izvora lokacije."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Omogućuje aplikaciji pristup dodatnim naredbama davatelja usluga lokacije. To može omogućiti aplikaciji ometanje rada GPS-a ili drugih izvora lokacije."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"dopuštenje za instaliranje davatelja usluge lociranja"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Stvaranje lažnih izvora lokacije radi testiranja ili za instaliranje novog pružatelja usluga lokacije. To aplikaciji omogućuje zaobilaženje lokacije i/ili statusa koji vraćaju drugi izvori lokacije, primjerice GPS ili pružatelji usluga lokacije."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"precizna lokacija (GPS i mreža)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Aplikaciji omogućuje upravljanje mrežnim pravilima i određivanje pravila za aplikacije."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"izmjena evidencije mrežne upotrebe"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Omogućuje aplikaciji izmjenu načina upotrebe mreže u odnosu na aplikacije. Nije namijenjeno uobičajenim aplikacijama."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"izmijeni oznake utičnica"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Dopušta aplikaciji izmjenu oznaka utičnica za usmjeravanje"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"pristup obavijestima"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Omogućuje aplikaciji dohvaćanje, pregledavanje i brisanje obavijesti, uključujući obavijesti drugih aplikacija."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vezanje uz uslugu slušatelja obavijesti"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge slušatelja obavijesti. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"povezivanje s uslugom davatelja uvjeta"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Vlasniku omogućuje povezivanje sa sučeljem najviše razine usluge davatelja uvjeta. Nije potrebno za normalne aplikacije."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"vezanje na Dream"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Vlasniku omogućuje povezivanje sa sučeljem najviše razine za Dream. Ne bi trebalo biti potrebno za normalne aplikacije."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"pozovi operaterovu aplikaciju za konfiguraciju"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Omogućuje aplikaciji izmjenu parametara kalibracije dodirnog zaslona. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"pristup DRM certifikatima"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Aplikaciji omogućuje pružanje i korištenje DRM certifikata. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Primaj emitiranja prijenosa."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Omogućuje primanje informacija o statusu prijenosa."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Primanje statusa prijenosa Android Beama"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Omogućuje aplikaciji primanje podataka o trenutačnim prijenosima Android Beama"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Upravljajte duljinom zaporki za otključavanje zaslona i dopuštenim znakovima u tim zaporkama."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Aplikaciji omogućuje izmjenu povijesti i oznaka Preglednika pohranjenih na telefonu. To aplikaciji može omogućiti brisanje ili izmjenu podataka Preglednika. Napomena: tu dozvolu ne mogu primijeniti preglednici treće strane ili druge aplikacije s mogućnostima pregledavanja weba."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"postavljanje alarma"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Omogućuje aplikaciji postavljanje alarma na instaliranoj aplikaciji budilici. Neke aplikacije budilice možda neće primijeniti tu značajku."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"ukloni govornu poštu"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Omogućuje aplikaciji da ukloni poruke iz dolazne govorne pošte."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"upravljanje govornom poštom"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Omogućuje aplikaciji izmjenjivanje i uklanjanje poruka iz dolazne govorne pošte."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"dodaj govornu poštu"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Omogućuje aplikaciji da doda poruke u vašu govornu poštu."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"čitanje svih poruka u govornoj pošti"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"Uklj."</string>
<string name="capital_off" msgid="6815870386972805832">"Isklj."</string>
<string name="whichApplication" msgid="4533185947064773386">"Radnju dovrši pomoću stavke"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Odaberite aplikaciju na početnom zaslonu"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Koristi se kao zadana postavka za ovu lokaciju."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Izbrisati zadano u Postavkama sustava > Aplikacije > Preuzimanja."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Dopusti uvijek"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ne dopuštaj nikada"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM kartica uklonjena"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mobilna mreža bit će nedostupna do ponovnog pokretanja s umetnutom važećom SIM karticom."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Gotovo"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM kartica dodana"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Za pristup mobilnoj mreži ponovo pokrenite uređaj."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Ponovno pokreni"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Postavljanje vremena"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Postavi datum"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Odabrana je stavka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Izbrisan je broj <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"U načinu ste zaključavanja na aplikaciju."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Želite li upotrijebiti zaključavanje na aplikaciju?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Značajkom zaključavanja na aplikaciju zaključava se prikaz na pojedinačnu aplikaciju.\n\nDa biste je zatvorili, pritisnite i držite gumb za nedavne aplikacije $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NE"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"POKRENI"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Pokretanje zaključavanja na aplikaciju"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Zatvaranje zaključavanja na aplikaciju"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 72ff966..59b7115 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Lehetővé teszi az alkalmazás számára, hogy írjon a telefonon vagy a SIM kártyán lévő SMS-ekbe. A rosszindulatú alkalmazások törölhetik az üzeneteket."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"szöveges üzenetek (WAP) fogadása"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Lehetővé teszi az alkalmazás számára, hogy WAP-üzeneteket fogadjon és dolgozzon fel. Ez azt is jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth-üzenetek (MAP) fogadása"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Lehetővé teszi az alkalmazás számára, hogy Bluetooth MAP üzeneteket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás anélkül figyelheti meg vagy törölheti a beérkező üzeneteket, hogy megjelenítené azokat Önnek."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"futó alkalmazások lekérése"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Lehetővé teszi az alkalmazás számára a jelenleg futó és nemrég befejezett feladatokkal kapcsolatos információk lekérését. Ezáltal az alkalmazás engedélyt kap az eszközön használt alkalmazásokkal kapcsolatos információk felderítésére."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"felhasználók közötti interakció"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"helyforrások utánzása tesztelés céljából"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Helyforrásutánzatok létrehozása tesztelés céljából, vagy új helyszolgáltató telepítése. Ez lehetővé teszi az alkalmazás számára, hogy felülírja az olyan helyforrások által biztosított hely- és/vagy állapotadatokat, mint a GPS vagy helyszolgáltatók."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"további helyszolgáltatói parancsok elérése"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Lehetővé teszi az alkalmazás számára további helyszolgáltatói parancsok elérését. Ezáltal az alkalmazás beavatkozhat a GPS vagy más helyforrások működésébe."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Lehetővé teszi az alkalmazás számára további helyszolgáltatói parancsok elérését. Ezáltal az alkalmazás beavatkozhat a GPS vagy más helyforrások működésébe."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"engedély helyszolgáltató telepítésére"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Helyforrásutánzatok létrehozása tesztelés céljából, vagy új helyszolgáltató telepítése. Ez lehetővé teszi az alkalmazás számára, hogy felülírja az olyan helyforrások által biztosított hely- és/vagy állapotadatokat, mint a GPS vagy helyszolgáltatók."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"pontos (GPS- és hálózatalapú) tartózkodási hely"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Lehetővé teszi az alkalmazás számára, hogy kezelje a hálózati irányelveket és meghatározza az alkalmazásspecifikus szabályokat."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"hálózathasználat elszámolásának módosítása"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Lehetővé teszi az alkalmazás számára annak módosítását, hogy a hálózathasználatot hogyan számolják el az alkalmazások esetében. Normál alkalmazások nem használhatják."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"szoftvercsatorna-jelölések módosítása"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Lehetővé teszi, hogy az alkalmazás módosítsa az útválasztáshoz használt szoftvercsatorna-jelöléseket"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"hozzáférési értesítések"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Lehetővé teszi, hogy az alkalmazás értesítéseket kérdezzen le, vizsgáljon és tisztítson meg, beleértve az egyéb alkalmazások által közzétett értesítéseket is."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"csatlakozzon értesítésfigyelő szolgáltatáshoz"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lehetővé teszi a használó számára, hogy csatlakozzon egy értesítésfigyelő szolgáltatás legfelső szintű felületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"csatlakozás egy feltételbiztosító szolgáltatáshoz"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Lehetővé teszi a használó számára, hogy csatlakozzon egy feltételbiztosító szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"csatlakozás egy képernyővédő szolgáltatáshoz"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Lehetővé teszi a használó számára, hogy csatlakozzon egy képernyővédő szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"a szolgáltatói konfigurációs alkalmazás hívása"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lehetővé teszi, hogy az alkalmazás módosítsa az érintőképernyő kalibrációs paramétereit. A normál alkalmazásoknál erre elvileg soha nincs szükség."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM-tanúsítványokhoz való hozzáférés"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Engedélyezi egy alkalmazás számára a DRM-tanúsítványokhoz való hozzáférést és azok használatát. Átlagos alkalmazásoknak erre nem lehet szükségük."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Az átadás átviteli adásainak fogadása."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Lehetővé teszi az átadás átviteli állapotinformációinak fogadását."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Android Beam-átviteli állapot fogadása"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Lehetővé teszi az alkalmazás számára a folyamatban lévő Android Beam-átvitelekről szóló információk fogadását"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Lehetővé teszi az alkalmazás számára, hogy módosítsa a böngésző előzményeit vagy a telefonon tárolt könyvjelzőket. Az engedéllyel rendelkező alkalmazás törölheti vagy módosíthatja a böngésző adatait. Megjegyzés: előfordulhat, hogy ezt az engedélyt harmadik felek által üzemeltetett böngészők vagy egyéb böngészésre képes alkalmazások nem léptetik életbe."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"ébresztés beállítása"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Lehetővé teszi az alkalmazás számára, hogy ébresztőt állítson be egy telepített ébresztőóra alkalmazásban. Egyes ilyen alkalmazásokban lehet, hogy nem működik ez a funkció."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"hangpostaüzenetek eltávolítása"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Lehetővé teszi az alkalmazás számára, hogy üzeneteket távolítson el a bejövő hangpostafiókból."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"hangüzenetek kezelése"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Lehetővé teszi az alkalmazás számára, hogy üzeneteket módosítson vagy távolítson el a bejövő hangpostafiókból."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"hangposta hozzáadása"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Lehetővé teszi az alkalmazás számára, hogy üzeneteket adjon hozzá bejövő hangpostájához."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"az összes hangüzenet olvasása"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"Be"</string>
<string name="capital_off" msgid="6815870386972805832">"Ki"</string>
<string name="whichApplication" msgid="4533185947064773386">"Művelet végrehajtása a következővel:"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"A kezdőalkalmazás kiválasztása"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Ez legyen az alapértelmezett program ehhez a művelethez."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Alapértelmezés törlése itt: Rendszerbeállítások > Alkalmazások > Letöltve."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Engedélyezés mindig"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Soha nem engedélyezem"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM kártya eltávolítva"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"A mobilhálózat nem lesz elérhető, amíg újra nem indítja egy érvényes SIM kártya behelyezése után."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Kész"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM kártya hozzáadva"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"A mobilhálózathoz eléréséhez indítsa újra az eszközt."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Újraindítás"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Idő beállítása"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Dátum beállítása"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> kiválasztva"</string>
<string name="deleted_key" msgid="7659477886625566590">"A(z) <xliff:g id="KEY">%1$s</xliff:g> érték törölve"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Ön alkalmazászárolási módban van."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Használni szeretné az alkalmazászárolást?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Az alkalmazászárolás lezárja a kijelzőt az adott alkalmazásban.\n\nA kilépéshez tartsa lenyomva a legutóbbi alkalmazások gombot ($)."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NEM"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"INDÍT"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Az alkalmazászárolás indítása"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Kilépés az alkalmazászárolásból"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 6e4b44a..a2f71c6 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -295,7 +295,7 @@
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"ստանալ տեքստային հաղորդագրություններ (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Թույլ է տալիս հավելվածին ստանալ և գործարկել WAP հաղորդագրությունները: Այս թույլտվությունը ներառում է ձեզ ուղարկված հաղորդագրությունները հետևելու կամ ջնջելու կարողությունը` առանց ձեր տեսնելու:"</string>
<string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"ստանալ Bluetooth հաղորդագրությունները (MAP)"</string>
- <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Թույլ է տալիս հավելվածին ստանալ և մշակել MAP հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Թույլ է տալիս հավելվածին ստանալ և մշակել Bluetooth MAP հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"առբերել աշխատող հավելվածները"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Թույլ է տալիս հավելվածին առբերել մանրամասն տեղեկություններ առկա և վերջերս աշխատող առաջադրանքների մասին: Սա կարող է թույլ տալ հավելվածին հայտնաբերել անձնական տեղեկություններ այլ հավելվածների վերաբերյալ:"</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"հաղորդակցվել օգտվողների միջև"</string>
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"կեղծ տեղանքի աղբյուրներ փորձարկման համար"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Ստեղծել կեղծ տեղանքի աղբյուրներ` փորձարկման կամ տեղադրության նոր ծառայություն մատուցողի տեղադրման համար: Սա հնարավորություն է տալիս, որ ծրագիրը անտեսի տեղադրությունը և/կամ կարգավիճակը` տրամադրված տեղանքի այլ աղբյուրների կողմից, ինչպիսիք են GPS-ը կամ տեղադրության ծառայություն մատուցողները:"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"օգտագործել տեղադրություն տրամադրող հավելվյալ հրամաններ"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Թույլ է տալիս հավելվածին օգտագործել տեղադրության ծառայություն մատուցողների լրացուցիչ հրամանները: Սա կարող է թույլ տալհավելվածին խանգարել GPS-ի կամ այլ տեղանքի աղբյուրների աշխատանքին:"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ծրագրին թույլ է տալիս օգտագործել տեղադրության մասին տվյալների աղբյուրների կառավարման լրացուցիչ հրահանգներ: Սա կարող է ծրագրին թույլ տալ միջամտել GPS-ի կամ տեղադրության մասին տվյալների այլ աղբյուրների գործառույթներին:"</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"տեղադրության ծառայություն մատուցողի տեղադրման թույլտվություն"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Ստեղծել կեղծ տեղանքի աղբյուրներ` փորձարկման կամ տեղադրության նոր ծառայություն մատուցողի տեղադրման համար: Սա հնարավորություն է տալիս, որ հավելվածն անտեսի տեղադրությունը և/կամ կարգավիճակը` տրամադրված տեղանքի այլ աղբյուրների կողմից, ինչպիսիք են GPS-ը կամ տեղադրության ծառայություն մատուցողները:"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ճշգրիտ վայրը (ըստ GPS-ի և ցանցի)"</string>
@@ -713,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Թույլ է տալիս հավելվածին կառավարել ցանցային քաղաքականությունը և սահմանել հավելվածի հատուկ կանոնները:"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"փոփոխել ցանցի օգտագործման հաշվառումը"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Թույլ է տալիս հավելվածին փոփոխել, թե ինչպես է ցանցի օգտագործումը հաշվարկվում հավելվածների համար: Սովորական հավելվածների օգտագործման համար չէ:"</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"փոփոխել բնիկի նշանները"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Թույլ է տալիս ծրագրին փոփոխել բնիկի նշանները երթուղման համար"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"մուտք գործել ծանուցումներ"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Թույլ է տալիս հավելվածին առբերել, ուսումնասիրել և մաքրել ծանուցումներն, այդ թվում նաև այլ հավելվածների կողմից գրառվածները:"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"միանալ ծանուցումների ունկնդրիչ ծառայությանը"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Թույլ է տալիս սեփականատիրոջը միանալ ծանուցումները ունկնդրող ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"կապվել պայմանների մատակարարի ծառայությանը"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Թույլ է տալիս սեփականատիրոջը միանալ պայմանների մատակարարների բազային միջերեսին: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"Միացում էկրանապահների ծառայությանը"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Թույլ է տալիս սեփականատիրոջը միանալ էկրանապահների ծառայության վերին մակարդակի միջերեսին: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"գործարկել օպերատորի կողմից տրամադրված կազմաձևման ծրագիրը"</string>
@@ -731,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Թույլ է տալիս ծրագրին փոփոխել հպէկրանի չափաբերման կարգավորումները: Սովորական ծրագրերի համար երբեք պետք չի գալու:"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM հավաստագրերի մատչում"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Ծրագրին թույլ է տալիս տրամադրել և օգտագործել DRM վկայագրեր: Սովորական ծրագրերի համար երբեք պետք չի գալիս:"</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Ստանալ փոխանցումների հեռարձակումներ:"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Թույլ է տալիս տեղեկատվություն ստանալ փոխանցման կարգավիճակի մասին:"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Ստանալ Android Ճառագայթումով փոխանցման կարգավիճակը"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Ծրագրին թույլ է տալիս ստանալ Android Ճառագայթումով ընթացիկ փոխանցումների մասին տեղեկատվություն:"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Սահմանել գաղտնաբառի կանոնները"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Վերահսկել էկրանի ապակողպման գաղտնաբառերի թույլատրելի երկարությունն ու գրանշանները:"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Վերահսկել էկրանի ապակողպման փորձերը"</string>
@@ -1006,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Թույլ է տալիս հավելվածին փոփոխել դիտարկչի պատմությունը կամ ձեր հեռախոսում պահված էջանիշերը: Այն կարող է թույլ տալ հավելվածին ջնջել կամ փոփոխել դիտարկչի տվյալները: Նշում. այս թույլտվությունը չի կարող գործածվել կողմնակի դիտարկիչների կամ վեբ զննարկման հնարավորություններով այլ հավելվածների կողմից:"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"դնել ազդանշան"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Թույլ է տալիս հավելվածին սահմանել զարթուցիչի ծրագրում տեղադրված ազդանշանը: Զարթուցիչի որոշ հավելվածներ չեն կարող կիրառել այս հատկությունը:"</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"հեռացնել ձայնային հաղորդագրությունները"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Թույլ է տալիս հավելվածին հեռացնել հաղորդագրություններ ձեր ձայնային փոստի մուտքի արկղից:"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"կառավարել ձայնային հաղորդագրությունները"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Ծրագրին թույլ է տալիս մուտքի արկղից փոփոխել և հեռացնել ձեր ձայնային հաղորդագրությունները:"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"ավելացնել ձայնային փոստ"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Թույլ է տալիս հավելվածին ավելացնել հաղորդագրություններ ձեր ձայնային փոստի արկղում:"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"կարդալ ձայնային հաղորդագրությունները"</string>
@@ -1179,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"I"</string>
<string name="capital_off" msgid="6815870386972805832">"O"</string>
<string name="whichApplication" msgid="4533185947064773386">"Ավարտել գործողությունը` օգտագործելով"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Ընտրեք հիմնական հավելվածը"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Օգտագործել լռելյայն այս գործողության համար:"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Մաքրել լռելյայնը Համակարգի կարգավորումներ > Ծրագրեր >Ներբեռնված էջից:"</string>
@@ -1281,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Միշտ թույլատրել"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Երբեք չթույլատրել"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM քարտը հեռացված է"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Բջջային ցանցը անհասանելի կլինի, մինչև չվերագործարկեք վավեր SIM քարտ տեղադրելուց հետո:"</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Կատարված"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM քարտը ավելացվել է"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Վերագործարկեք ձեր սարքը` բջջային ցանց մուտք ունենալու համար:"</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Վերագործարկել"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Սահմանել ժամը"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Սահմանել ամսաթիվը"</string>
@@ -1735,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Ընտրված է <xliff:g id="ITEM">%1$s</xliff:g> տարրը"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> թիվը ջնջված է"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Աշխատանքային <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Դուք գտնվում եք Lock-to-app ռեժիմում:"</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Օգտագործե՞լ lock-to-app գործառույթը:"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app գործառույթը արգելափակում է ցուցադրումը առանձին ծրագրերում:\n\nԳործառույթն անջատելու համար սեղմեք և պահեք վերջին ծրագրերի կոճակը $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"Ոչ"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"Այո"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Միացնել Lock-to-app գործառույթը"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Անջատել Lock-to-app գործառույթը"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 5cc5af3..42e1d8a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Mengizinkan apl menulis ke pesan SMS yang tersimpan di ponsel atau kartu SIM. Apl berbahaya dapat menghapus pesan Anda."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"terima pesan teks (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Memungkinkan aplikasi menerima dan memproses pesan WAP. Izin ini mencakup kemampuan untuk memantau atau menghapus pesan yang dikirim kepada Anda tanpa menunjukkannya kepada Anda."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"menerima pesan Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Mengizinkan aplikasi menerima dan memproses pesan MAP Bluetooth. Artinya, aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"mengambil apl yang berjalan"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Memungkinkan aplikasi mengambil informasi tentang tugas yang dijalankan saat ini dan baru-baru ini. Izin ini memungkinkan aplikasi menemukan informasi tentang aplikasi mana yang digunakan pada perangkat."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"berinteraksi antar-pengguna"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"sumber lokasi palsu untuk menguji"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Membuat sumber lokasi palsu untuk uji coba atau memasang penyedia lokasi baru. Izin ini memungkinkan aplikasi mengganti lokasi dan/atau status yang dimunculkan sumber lokasi lain, misalnya GPS atau penyedia lokasi."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"akses perintah penyedia lokasi ekstra"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Memungkinkan aplikasi mengakses perintah penyedia lokasi ekstra. Izin ini dapat memungkinkan aplikasi mengganggu pengoperasian GPS atau sumber lokasi lain."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Memungkinkan aplikasi mengakses perintah penyedia lokasi ekstra. Tindakan ini memungkinkan aplikasi mengganggu pengoperasian GPS atau sumber lokasi lain."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"izin untuk memasang suatu penyedia lokasi"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Membuat sumber lokasi palsu untuk uji coba atau memasang penyedia lokasi baru. Izin ini memungkinkan aplikasi mengganti lokasi dan/atau status yang dimunculkan sumber lokasi lain, misalnya GPS atau penyedia lokasi."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"lokasi akurat (berbasis jaringan dan GPS)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Mengizinkan apl mengelola kebijakan jaringan dan menentukan peraturan khusus apl."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"mengubah penghitungan penggunaan jaringan"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Mengizinkan apl memodifikasi cara penggunaan jaringan diperhitungkan terhadap apl. Tidak untuk digunakan oleh apl normal."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"mengubah tanda soket"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Memungkinkan aplikasi mengubah tanda soket untuk perutean"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"mengakses pemberitahuan"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Mengizinkan aplikasi mengambil, memeriksa, dan menghapus pemberitahuan, termasuk pemberitahuan yang diposkan oleh aplikasi lain."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"mengikat layanan pendengar pemberitahuan"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Memungkinkan pemegang mengikat antarmuka tingkat teratas dari suatu layanan pendengar pemberitahuan. Tidak pernah diperlukan oleh aplikasi normal."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"mengikat ke layanan penyedia ketentuan"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Memungkinkan pemegang mengikat antarmuka tingkat tinggi dari layanan penyedia ketentuan. Tidak pernah diperlukan oleh aplikasi normal."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"mengikat ke layanan lamunan"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Memungkinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan lamunan. Tidak pernah diperlukan oleh aplikasi normal."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"memanggil aplikasi konfigurasi yang disediakan operator"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Memungkinkan aplikasi mengubah parameter kalibrasi layar sentuh. Tidak diperlukan oleh aplikasi normal."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"mengakses sertifikat DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Memungkinkan aplikasi menyediakan dan menggunakan sertifikat DRM. Tidak pernah dibutuhkan untuk aplikasi normal."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Terima siaran transfer penyerahan."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Memungkinkan penerimaan informasi status transfer penyerahan."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Menerima status transfer Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Memungkinkan aplikasi ini menerima informasi tentang transfer Android Beam saat ini"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrol panjang dan karakter yang diizinkan dalam sandi pembuka layar."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Memungkinkan aplikasi mengubah riwayat atau bookmark Browser yang tersimpan dalam ponsel Anda. Izin ini memungkinkan aplikasi menghapus atau mengubah data Browser. Catatan: izin ini tidak dapat diberlakukan oleh browser pihak ketiga atau aplikasi lain dengan kemampuan menjelajahi web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"setel alarm"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Mengizinkan apl menyetel alarm di apl jam alarm yang terpasang. Beberapa apl jam alarm mungkin tidak menerapkan fitur ini."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"buang pesan suara"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Memungkinkan aplikasi membuang pesan dari kotak masuk pesan suara."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"mengelola kotak pesan"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Memungkinkan aplikasi memodifikasi dan membuang pesan dari kotak masuk pesan suara Anda."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"tambahkan kotak pesan"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Mengizinkan apl menambahkan pesan ke kotak masuk untuk pesan suara Anda."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"baca semua kotak pesan"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"AKTIF"</string>
<string name="capital_off" msgid="6815870386972805832">"MATI"</string>
<string name="whichApplication" msgid="4533185947064773386">"Tindakan lengkap menggunakan"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Pilih aplikasi beranda"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Gunakan secara default untuk tindakan ini."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Menghapus default di Setelan sistem > Apl > Terunduh."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Selalu Izinkan"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Jangan Pernah Izinkan"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Kartu SIM dihapus"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Jaringan seluler tidak akan tersedia sampai Anda memulai lagi dengan memasukkan kartu SIM yang valid."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Kartu SIM ditambahkan"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Mulai ulang perangkat Anda untuk mengakses jaringan selular."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Mulai Ulang"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Setel waktu"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Setel tanggal"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dihapus"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Kantor <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Gunakan lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app mengunci layar dalam satu aplikasi tunggal.\n\nUntuk keluar, tekan lama tombol aplikasi terbaru $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"TIDAK"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Anda dalam mode Kunci ke Aplikasi."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Gunakan kunci ke aplikasi?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"MULAI"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Mulai Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Keluar dari Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index f086031..e6e6c85 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Consente all\'applicazione la scrittura nei messaggi SMS memorizzati sul telefono o sulla scheda SIM. Le applicazioni dannose potrebbero cancellare i tuoi messaggi."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"ricezione messaggi di testo (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Consente all\'applicazione di ricevere ed elaborare messaggi WAP. Questa autorizzazione include la facoltà di monitorare o eliminare i messaggi che ti vengono inviati senza mostrarteli."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"ricevi messaggi Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Consente all\'app di ricevere ed elaborare i messaggi Bluetooth MAP. Questo significa che l\'app può monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"recupero applicazioni in esecuzione"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Consente all\'applicazione di recuperare informazioni sulle attività attualmente e recentemente in esecuzione. Ciò potrebbe consentire all\'applicazione di scoprire informazioni sulle applicazioni in uso sul dispositivo."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interazione tra gli utenti"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"fonti di geolocalizzazione fittizie per test"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Crea fonti di geolocalizzazione fittizie per i test o installa un nuovo fornitore di posizione. Ciò consente all\'applicazione di ignorare la posizione e/o lo stato restituito da altre fonti di geolocalizzazione, come il GPS o fornitori di posizione."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accesso a comandi aggiuntivi del provider di localizz."</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Consente all\'applicazione di accedere a ulteriori comandi del fornitore di posizione. Ciò potrebbe consentire all\'applicazione di interferire con il funzionamento del GPS o di altre fonti di geolocalizzazione."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Consente all\'app di accedere a ulteriori comandi del fornitore di posizione. Ciò potrebbe consentire all\'app di interferire con il funzionamento del GPS o di altre fonti di localizzazione."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorizzazione a installare un provider di localizzazione"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Crea fonti di geolocalizzazione fittizie per i test o installa un nuovo fornitore di posizione. Ciò consente all\'applicazione di ignorare la posizione e/o lo stato restituito da altre fonti di geolocalizzazione, come il GPS o fornitori di posizione."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"posizione precisa (GPS e basata sulla rete)"</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Consente all\'applicazione di gestire le norme di rete e definire le regole specifiche delle applicazioni."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modifica calcolo dell\'utilizzo della rete"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Consente all\'applicazione di modificare il calcolo dell\'utilizzo della rete tra le applicazioni. Da non usare per normali applicazioni."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modifica di contrassegni socket"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Consente all\'app di modificare i contrassegni socket per il routing"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"accesso a notifiche"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Consente all\'app di recuperare, esaminare e cancellare notifiche, comprese quelle pubblicate da altre app."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincolo a un servizio listener di notifica"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Consente al titolare di vincolarsi all\'interfaccia di primo livello di un servizio listener di notifica. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"collegamento a un servizio provider di condizioni"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio provider di condizioni. Non dovrebbe essere mai necessaria per le normali app."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"associa a servizio di routing multimediale"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Consente di eseguire l\'associazione all\'interfaccia di primo livello di un servizio di routing multimediale. Generalmente non necessario per le normali app."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"associa a servizio dream"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Consente all\'utente di associare l\'interfaccia di primo livello di un servizio dream. Questa impostazione non è mai necessaria per le app normali."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"richiamo dell\'app di configurazione operatore-provider"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Consente all\'app di modificare i parametri di calibrazione del touch screen. Questa opzione non deve essere utilizzata per le app normali."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accesso a certificati DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Consente a un\'app di fornire e utilizzare ceritificati DRM. Questa opzione non deve essere utilizzata per app normali."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Ricevi trasmissioni del trasferimento."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Consente di ricevere informazioni sullo stato del trasferimento."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Ricevi lo stato dei trasferimenti Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Consente all\'applicazione di ricevere informazioni sugli attuali trasferimenti Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Impostazione regole password"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Controllo tentativi di sblocco dello schermo"</string>
@@ -1006,10 +1004,10 @@
<string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"scrittura segnalibri e cronologia web"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Consente all\'applicazione di modificare la cronologia o i segnalibri del Browser memorizzati sul tablet. Ciò potrebbe consentire all\'applicazione di cancellare o modificare i dati del Browser. Nota. È possibile che questa autorizzazione non sia applicabile da browser di terze parti o altre applicazioni con funzionalità di navigazione web."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Consente all\'applicazione di modificare la cronologia o i segnalibri del Browser memorizzati sul telefono. Ciò potrebbe consentire all\'applicazione di cancellare o modificare i dati del Browser. Nota. È possibile che questa autorizzazione non sia applicabile da browser di terze parti o altre applicazioni con funzionalità di navigazione web."</string>
- <string name="permlab_setAlarm" msgid="1379294556362091814">"impostazione allarme"</string>
- <string name="permdesc_setAlarm" msgid="316392039157473848">"Consente all\'applicazione di impostare un allarme in un\'applicazione sveglia installata. È possibile che alcune applicazioni sveglia non possano implementare questa funzione."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"rimuovi messaggi vocali"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Consente all\'app di rimuovere messaggi dalla segreteria."</string>
+ <string name="permlab_setAlarm" msgid="1379294556362091814">"impostazione sveglia"</string>
+ <string name="permdesc_setAlarm" msgid="316392039157473848">"Consente all\'applicazione di impostare una sveglia in un\'applicazione sveglia installata. È possibile che alcune applicazioni sveglia non possano implementare questa funzione."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"gestisci messaggi della segreteria"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Consente all\'app di modificare e rimuovere messaggi dalla segreteria."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"aggiunta di un messaggio vocale"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Consente all\'applicazione di aggiungere messaggi alla casella della segreteria."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"accesso alla segreteria"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"ON"</string>
<string name="capital_off" msgid="6815870386972805832">"OFF"</string>
<string name="whichApplication" msgid="4533185947064773386">"Completa l\'azione con"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"Completamento azione con %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Apri con"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Apri con %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Modifica con"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Modifica con %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Condividi con"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Condividi con %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Seleziona un\'app home"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Usa come predefinita per questa azione."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Cancella l\'applicazione predefinita in Impostazioni di sistema > Applicazioni > Scaricate."</string>
@@ -1226,7 +1231,7 @@
<string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"Suoneria silenziosa impostata"</string>
<string name="volume_call" msgid="3941680041282788711">"Volume chiamate"</string>
<string name="volume_bluetooth_call" msgid="2002891926351151534">"Volume chiamate Bluetooth"</string>
- <string name="volume_alarm" msgid="1985191616042689100">"Volume allarme"</string>
+ <string name="volume_alarm" msgid="1985191616042689100">"Volume sveglia"</string>
<string name="volume_notification" msgid="2422265656744276715">"Volume notifiche"</string>
<string name="volume_unknown" msgid="1400219669770445902">"Volume"</string>
<string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"Volume Bluetooth"</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Consenti sempre"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Non consentire mai"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Scheda SIM rimossa"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"La rete mobile non sarà disponibile finché non eseguirai il riavvio con una scheda SIM valida inserita."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"La rete cellulare non sarà disponibile fino a quando riavvii il dispositivo con inserita una scheda SIM valida."</string>
<string name="sim_done_button" msgid="827949989369963775">"Fine"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Scheda SIM aggiunta"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Riavvia il dispositivo per accedere alla rete mobile."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Riavvia il dispositivo per accedere alla rete cellulare."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Riavvia"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Imposta ora"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Imposta data"</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Elemento selezionato: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminato"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> lavoro"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Utilizzare Lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"La funzione Lock-to-app consente di bloccare la visualizzazione in un\'unica app.\n\nPer uscire, premi e tieni premuto il pulsante delle app recenti $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Sei in modalità Blocca su app."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Utilizzare Blocca su app?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"AVVIA"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Avvia Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Esci da Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a85d9c5..2b497ae 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"מאפשר לאפליקציה לכתוב להודעות SMS המאוחסנות בטלפון או בכרטיס ה-SIM שלך. אפליקציות זדוניות עלולות למחוק את ההודעות שלך."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"קבלת הודעות טקסט (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"מאפשר לאפליקציה לקבל ולעבד הודעות WAP. אישור זה כולל את היכולת לעקוב אחר הודעות שנשלחו אליך ולמחוק אותן מבלי להציג לך אותן."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"קבלת הודעות Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"הרשאה זו מאפשרת לאפליקציה לקבל ולעבד הודעות MAP של Bluetooth. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות הנשלחות למכשיר שלך או למחוק אותן מבלי להראות לך אותן."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"אחזור אפליקציות פעילות"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"מאפשר לאפליקציה לאחזר מידע לגבי משימות הפועלות כרגע ושפעלו לאחרונה. ייתכן שהדבר יתיר לאפליקציה לגלות מידע לגבי האפליקציות שבהן נעשה שימוש במכשיר."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"אינטראקציה בין משתמשים"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"צור מקורות מיקום מדומים לצורך בדיקה"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"צור מקורות מיקום מדומים לבדיקה, או התקן ספק מיקום חדש. פעולה זו מאפשרת לאפליקציה לעקוף את המיקום ו/או הסטטוס המוחזרים על ידי מקורות מיקום אחרים כמו GPS או ספקי מיקום."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"גישה לפקודות ספק מיקום נוספות"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"מאפשר לאפליקציה לגשת לפקודות נוספות של ספק שירות המיקום. אישור זה עשוי לאפשר לאפליקציה לשבש את פעולת ה-GPS או מקורות מיקום אחרים."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"מאפשרת לאפליקציה לגשת לפקודות נוספות של ספק המיקום. הרשאה זו עשויה לאפשר לאפליקציה לשבש את פעולת ה-GPS או מקורות מיקום אחרים."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"הרשאה להתקין ספק מיקום"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"צור מקורות מיקום מדומים לבדיקה, או התקן ספק מיקום חדש. פעולה זו מאפשרת לאפליקציה לעקוף את המיקום ו/או הסטטוס המוחזרים על ידי מקורות מיקום אחרים כמו GPS או ספקי מיקום."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"מיקום מדויק (מבוסס GPS ורשת)"</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"מאפשר לאפליקציה לנהל מדיניות הרשת להגדיר כללים ספציפיים-לאפליקציה."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"שנה ניהול חשבונות של שימוש ברשת"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"הרשאה זו מאפשרת לאפליקציה לשנות את אופן החישוב של נתוני שימוש ברשת מול כל אפליקציה. לא מיועד לשימוש באפליקציות רגילות."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"שינוי של סימני Socket"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"ההרשאה הזו מאפשרת לאפליקציה לשנות סימני Socket עבור ניתוב"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"גישה להתראות"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"מאפשר לאפליקציה לאחזר, לבדוק ולמחוק התראות, כולל כאלה שפורסמו על ידי אפליקציות אחרות."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"איגוד לשירות של מאזין להתראות"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של שירות מאזין להתראות. הרשאה זו אף פעם אינה נחוצה לאפליקציות רגילים."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"איגוד לשירות ספק תנאי"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"מאפשרת לבעלים לאגד לממשק ברמה העליונה של שירות ספק תנאי. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"איגוד לשירות ניתוב מדיה"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"מאפשרת לבעלים לאגוד לממשק ברמה העליונה של שירות ניתוב מדיה. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"איגוד לשירות Dream"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"מאפשרת לבעלים לבצע איגוד לממשק הרמה העליונה של שירות Dream. הרשאה זו אף פעם אינה נחוצה לאפליקציות רגילות."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"הפעלה של אפליקציית תצורה שסופקה על ידי ספק"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"מאפשרת לאפליקציה לשנות את פרמטרי הכיול של מסך המגע. לעולם לא אמורה להיות נחוצה לאפליקציות רגילות."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"גישה אל אישורי DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"מאפשרת לאפליקציה לנהל תצורה של אישורי DRM ולהשתמש בהם. לעולם לא אמורה להיות נחוצה עבור אפליקציה רגילה."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"קבל שידורים על העברת שליטה."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"מאפשר קבלה של מידע על סטטוס העברת שליטה."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"קבלת סטטוס העברה של Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"מאפשר לאפליקציה הזו לקבל מידע על העברות Android Beam נוכחיות"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"שלוט באורך ובתווים המותרים בסיסמאות לביטול נעילת מסך."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"עקוב אחר ניסיונות לביטול נעילת מסך"</string>
@@ -1008,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"מאפשר לאפליקציה לשנות את ההיסטוריה או ה-Bookmarks של הדפדפן המאוחסנים בטלפון. הדבר עשוי לאפשר לאפליקציה למחוק או לשנות נתוני דפדפן. שים לב: אישור זה אינו ניתן לאכיפה על ידי דפדפני צד שלישי או אפליקציות אחרות בעלות יכולות גלישה באינטרנט."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"הגדרת התראה"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"מאפשר לאפליקציה להגדיר התראה באפליקציה מותקנת של שעון מעורר. אפליקציות מסוימות של שעון מעורר אינן מיישמות תכונה זו."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"הסרה של הודעות דואר קולי"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"מאפשרת לאפליקציה להסיר הודעות מתיבת הדואר הנכנס של דואר קולי."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"ניהול של הודעות דואר קולי"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"מאפשרת לאפליקציה לשנות ולהסיר הודעות מתיבת הדואר הנכנס של דואר קולי."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"הוסף דואר קולי"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"מאפשר לאפליקציה להוסיף הודעות לתיבת הדואר הקולי."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"קריאת כל הדואר הקולי"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"מופעל"</string>
<string name="capital_off" msgid="6815870386972805832">"כבוי"</string>
<string name="whichApplication" msgid="4533185947064773386">"השלמת פעולה באמצעות"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"השלם את הפעולה באמצעות %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"פתח באמצעות"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"פתח באמצעות %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"ערוך באמצעות"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"ערוך באמצעות %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"שתף באמצעות"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"שתף באמצעות %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"בחר אפליקציה לדף הבית"</string>
<string name="alwaysUse" msgid="4583018368000610438">"השתמש כברירת מחדל עבור פעולה זו."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"נקה את הגדרת המחדל ב\'הגדרות מערכת\' < Google Apps < \'הורדות\'."</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"אפשר תמיד"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"לעולם אל תאפשר"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"כרטיס ה-SIM הוסר"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"הרשת הסלולרית לא תהיה זמינה עד שתפעיל מחדש לאחר הכנסת כרטיס SIM חוקי."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"הרשת הסלולרית לא תהיה זמינה עד שתבצע אתחול לאחר הכנסה של כרטיס SIM חוקי."</string>
<string name="sim_done_button" msgid="827949989369963775">"סיום"</string>
<string name="sim_added_title" msgid="3719670512889674693">"כרטיס ה-SIM נוסף"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"הפעל מחדש את המכשיר כדי לגשת אל הרשת הסלולרית."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"אתחל את המכשיר כדי לגשת אל הרשת הסלולרית."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"הפעל מחדש"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"הגדרת שעה"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"הגדר תאריך"</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> נבחר"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> נמחק"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"עבודה <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"האם להשתמש ב\'נעל באפליקציה\'?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"\'נעל באפליקציה\' נועל את המסך באפליקציה יחידה.\n\nכדי לצאת, לחץ על לחצן האפליקציות האחרונות $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"לא"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"אתה במצב \'נעילה באפליקציה\'."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"האם להשתמש ב\'נעילה באפליקציה\'?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"הפעל"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"הפעל את \'נעל באפליקציה\'"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"צא מ\'נעל באפליקציה\'"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9e513a5..58e2381 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"携帯端末やSIMカードに保存されているSMSメッセージへの書き込みをアプリに許可します。この許可を悪意のあるアプリに利用されると、メッセージが削除される恐れがあります。"</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"テキストメッセージ(WAP)の受信"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAPメッセージの受信と処理をアプリに許可します。これにより、アプリが端末に届いたメッセージを表示することなく監視または削除できるようになります。"</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetoothメッセージの受信(MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Bluetooth MAPメッセージの受信と処理をアプリに許可します。これにより、端末に届いたメッセージをアプリが表示することなく監視または削除するおそれがあります。"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"実行中のアプリの取得"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"現在実行中または最近実行したタスクに関する情報の取得をアプリに許可します。これにより、その端末でどのアプリを使用しているかをアプリから識別できるようになる可能性があります。"</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"ユーザー間の交流"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"仮の位置情報でテスト"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"テスト用に仮の位置情報源を作成するか、新しい位置情報提供元をインストールします。これにより、他の位置情報源(GPS、位置情報提供元など)から返された位置情報やステータスの上書きをアプリに許可することになります。"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"位置情報提供者の追加コマンドアクセス"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"位置情報提供元の追加のコマンドにアクセスすることをアプリに許可します。許可すると、アプリがGPSなどの位置情報源の動作を妨害する恐れがあります。"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"位置情報提供元の追加のコマンドにアクセスすることをアプリに許可します。許可すると、アプリがGPSなどの位置情報源の動作を妨害する恐れがあります。"</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"位置情報提供元のインストールを許可する"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"テスト用に仮の位置情報源を作成するか、新しい位置情報提供元をインストールします。これにより、他の位置情報源(GPS、位置情報提供元など)から返された位置情報やステータスをアプリが上書きできるようになる可能性があります。"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"正確な位置情報(GPSとネットワーク基地局)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ネットワークポリシーを管理しアプリ固有のルールを定義することをアプリに許可します。"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ネットワークの課金の変更"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"アプリに対するネットワーク利用の計算方法を変更することをアプリに許可します。通常のアプリでは使用しません。"</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"ソケットマークの変更"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"ルーティングのソケットマークを変更することをアプリに許可します。"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"通知にアクセス"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"通知(他のアプリから投稿されたものも含む)を取得、調査、クリアすることをアプリに許可します。"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"通知リスナーサービスにバインド"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"通知リスナーサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"コンディションプロバイダサービスへのバインド"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"コンディションプロバイダサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"ドリームサービスにバインド"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"ドリームサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"携帯通信会社が提供する設定アプリの呼び出し"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"タッチスクリーンの調整パラメータの変更をアプリに許可します。通常のアプリでは必要ありません。"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM証明書へのアクセス権"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM証明書のプロビジョニングと使用をアプリに許可します。通常のアプリでは不要です。"</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"ハンドオーバー転送ブロードキャストの受信"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"ハンドオーバー転送ステータス情報を受信できるようにします。"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Androidビーム転送のステータスを受信"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"現在のAndroidビーム転送に関する情報を受信することをこのアプリに許可します。"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"画面ロック解除パスワードの長さと使用できる文字を制御します。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"携帯端末に保存されているブラウザの履歴やブックマークの変更をアプリに許可します。これにより、アプリがブラウザデータを消去または変更できるようになる可能性があります。注: この許可は、サードパーティブラウザまたはウェブブラウジング機能を備えたその他のアプリでは適用されない場合があります。"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"アラームの設定"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"インストール済みアラームアプリのアラームを設定することをアプリに許可します。この機能が実装されていないアラームアプリもあります。"</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"ボイスメールの削除"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"ボイスメール受信トレイからメッセージを削除することをアプリに許可します。"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"ボイスメールの管理"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"ボイスメール受信トレイからメッセージを修正、削除することをアプリに許可します。"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"ボイスメールの追加"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"ボイスメール受信トレイにメッセージを追加することをアプリに許可します。"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"すべてのボイスメールの読み取り"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"ON"</string>
<string name="capital_off" msgid="6815870386972805832">"OFF"</string>
<string name="whichApplication" msgid="4533185947064773386">"アプリケーションを選択"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"ホームアプリを選択"</string>
<string name="alwaysUse" msgid="4583018368000610438">"常にこの操作で使用する"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"[システム設定]>[アプリ]>[ダウンロード済み]でデフォルト設定をクリアします。"</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"常に許可する"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"許可しない"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIMカードが取り外されました"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"有効なSIMカードを挿入して再起動するまでは、モバイルネットワークは利用できません。"</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"完了"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIMカードが追加されました"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"モバイルネットワークにアクセスするには端末を再起動してください。"</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"再起動"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"時刻設定"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"日付設定"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g>を選択しました"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g>を削除しました"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"仕事の<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"現在アプリロックモードです。"</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"アプリロックの使用"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"アプリロックでは表示を単一のアプリにロックします。\n\n終了するには[最近使ったアプリ]ボタン($)を押し続けます"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"開始しない"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"開始する"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"アプリロックを開始"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"アプリロックを終了"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index a7a3a9d..aa886de 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"მდებარეობის წყაროების იმიტირება ტესტირებისთვის"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"აპს შეეძლება ტესტირებისთვის ყალბი ლოკაციების შექმნა, ან მდებარეობის ახალი პროვაიდერის დაყენება. ეს უფლებას მისცემს აპს, შეცვალოს მდებარეობის სხვა წყაროების მიერ, მაგ. GPS ან მდებარეობის პროვაიდერების მიერ მოწოდებული მდებარეობა და/ ან სტატუსი."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"მდებარეობის პროვაიდერის დამატებით ბრძანებებზე წვდომა"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"აპს შეეძლება წვდომა ჰქონდეს მდებარეობის სერვისის დამატებით ბრძანებებზე. შესაძლოა აპმა ეს გამოიყენოს GPS-ისა და მდებარეობის სხვა წყაროების მუშაობის პროცესში ჩარევისთვის."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"აპს შეეძლება წვდომა ჰქონდეს მდებარეობის სერვისის დამატებით ბრძანებებზე. შესაძლოა აპმა ეს გამოიყენოს GPS-ისა და მდებარეობის სხვა წყაროების მუშაობის პროცესში ჩარევისთვის."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"მდებარეობის პროვაიდერის ინსტალაციის უფლება"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"აპს შეეძლება ტესტირებისთვის ყალბი ლოკაციების შექმნა, ან მდებარეობის ახალი პროვაიდერის დაყენება. აპს საშუალება მიეცემა გადააკეთოს სხვა წყაროების მაგ.: GPS ან მდებარეობის პროვაიდერების მოწოდებული მდებარეობა ან/და სტატუსი."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ზუსტი მდებარეობა (GPS და ქსელის კოორდინატების მიხედვით)"</string>
@@ -713,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"აპს საშუალება ექნება მართოს ქსელის პოლიტიკა და დააწესოს წესები ცალკეული აპებისთვის."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ქსელის გამოყენების აღრიცხვის შეცვლა"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"აპს შეეძლება, შეცვალოს ქსელის გამოყენების აღრიცხვა აპებთან მიმართებაში. არ გამოიყენება ჩვეულებრივ აპებში."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"სოკეტის ნიშნების შეცვლა"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"საშუალებას აძლევს აპს შეცვალოს მარშრუტიზაციის სოკეტის ნიშნები"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"წვდომა შეტყობინებებთან"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"აპს შეეძლება მოიძიოს, გამოიკვლიოს და წაშალოს შეტყობინებები, მათ შორის სხვა აპების მიერ გამოქვეყნებული."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"შეტყობინებების მოსმენის სერვისთან დაკავშირება"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"მფლობელს შეეძლება შეტყობინებების მსმენლის სერვისის ზედა დონის ინტერფეისთან დაკავშირება. არ უნდა მოხდეს მისი გამოყენება ჩვეუელებრივი აპებისთვის.ფ"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"მდგომარეობის პროვაიდერის სერვისებთან შეკავშირება"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"მფლობელს შეეძლება შეკავშირდეს მდგომარეობის პროვაიდერის სერვისების ზედა დონის ინტერფეისთან. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დასჭირდეს."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"dream სერვისთან მიბმა"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"მფლობელს შეეძლება მიებას dream სერვისის ზედა დონის ინტერფეისი. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დაჭირდეს."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ოპერატორის მიერ მოწოდებული კოფიგურაციის აპის გამოხმობა"</string>
@@ -731,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"საშუალებას აძლევს აპს შეცვალოს სენსორული ეკრანის კალიბრაციის პარამეტრები. ჩვეულებრივ აპებს წესით არ უნდა დაჭირდეს."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM სერთიფიკატებზე წვდომა"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"საშუალებას აძლევს აპლიკაციას დანერგოს და გამოიყენოს DRM სერთიფიკატები. ეს უფლება ჩვეულებრივ აპებს არ ჭირდება."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"ჰენდოვერის ტრანსფერის მაუწყებლობების მიღება."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"იძლევა ჰენდოვერის ტრანსფერის სტატუსის მიღების საშუალებას."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Receive Android Beam transfer status"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Allows this application to receive information about current Android Beam transfers"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"პაროლის წესების დაყენება"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"გააკონტროლეთ ეკრანის განბლოკვის პაროლში დაშვებული სიმბოლოები და მისი სიგრძე."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ეკრანის განბლოკვის მცდელობების გაკონტროლება"</string>
@@ -1006,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"აპს შეეძლება, შეცვალოს ბრაუზერის ისტორია და თქვენ ტელეფონში შენახული სანიშნეები. ამან შეიძლება უფლება მისცეს აპს, წაშალოს ან შეცვალოს ბრაუზერის მონაცემები. შენიშვნა: ეს ნებართვა არ შეიძლება შესრულდეს მესამე მხარის ბრაუზერების ან ვებ დათვალიერების შესაძლებლობის მქონე სხვა აპლიკაციების მიერ."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"მაღვიძარას დაყენება"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"აპს შეეძლება მაღვიძარას დაყენება დაინსტალირებული მაღვიძარას აპლიკაციაში. ამ ფუნქციას მაღვიძარას ზოგიერთი აპი არ იყენებს."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"ხმოვანი ფოსტების ამოშლა"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"აპს შეეძლება ამოშალოს შეტყობინებები თქვენი ხმოვანი ფოსტის შემოსულებში."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"manage voicemails"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Allows the app to modify and remove messages from your voicemail inbox."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"ხმოვანი ფოსტის დამატება"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"აპს შეეძლება დაამატოს შეტყობინებები თქვენი ხმოვანი ფოსტის შემოსულებში."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"მთელი ხმოვანი ფოსტის წაკითხვა"</string>
@@ -1179,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"ჩართ."</string>
<string name="capital_off" msgid="6815870386972805832">"გამორთ."</string>
<string name="whichApplication" msgid="4533185947064773386">"რა გამოვიყენოთ?"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"აირჩიეთ საშინაო აპი"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ამ ქმედებისთვის ნაგულისხმევად გამოყენება."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"ნაგულისხმევი პარამეტრების წაშლა სისტემის პარამეტრებში > აპებში > ჩამოტვირთულებში."</string>
@@ -1281,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"ნებართვის მიცემა - ყოველთვის"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"არასოდეს მისცე უფლება"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM ბარათი ამოღებულია"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"მობილური კავშირი არ იქნება ხელმისაწვდომი, ვიდრე არ ჩადებთ ქმედით SIM ბარათს და გადატვირთავთ."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"დასრულდა"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM ბარათი დაემატა"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"გადატვირთეთ თქვენი მოწყობილობა მობილურ ქსელზე წვდომისთვის."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"გადატვირთვა"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"დროის დაყენება"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"თარიღის დაყენება"</string>
@@ -1373,10 +1391,8 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"საშუალებას აძლევს აპლიკაციას მოუსმინოს ცვლილებებს სანდო მდგომარეობაში."</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"სანდო აგენტის წარმოდგენა."</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"საშუალებას აძლევს აპლიკაციას წარმოადგინოს სანდო აგენტი."</string>
- <!-- no translation found for permlab_launch_trust_agent_settings (5859430082240410200) -->
- <skip />
- <!-- no translation found for permdesc_launch_trust_agent_settings (8185142708644913381) -->
- <skip />
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"ნდობის აგენტის პარამეტრების მენიუს გამოძახება."</string>
+ <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"აძლევს აპლიკაციას ნებართვას წამოიწყოს აქტივობა, რომელიც ნდობის აგენტის ქცევას ცვლის."</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"სანდო აგენტის სერვისზე მიმაგრება."</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"საშუალებას აძლევს აპლიკაციას მიემაგროს სანდო აგენტის სერვისს."</string>
<string name="permlab_recovery" msgid="3157024487744125846">"განახლებასთან და აღდგენის სისტემასთან ინტერაქცია"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"არჩეულია <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> წაიშალა"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"თქვენ იმყოფებით აპის ფიქსაციის რეჟიმში."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"გსურთ „აპში ჩაკეტვის“ გამოყენება?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"„აპში ჩაკეტვა“ კეტავს ეკრანს ერთ აპში.\n\nგასასვლელად დააჭირეთ და არ აუშვათ ღილაკს „ბოლო აპები“ $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"არა"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"დაწყება"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"„აპში ჩაკეტვის“ დაწყება"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"„აპში ჩაკეტვიდან“ გასვლა"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 70b3e53..ece0a47 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"ក្លែងប្រភពទីតាំងសម្រាប់សាកល្បង"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"បង្កើតប្រភពទីតាំងក្លែងក្លាយសម្រាប់សាកល្បង ឬដំឡើងក្រុមហ៊ុនផ្ដល់ទីតាំងថ្មី។ វាអនុញ្ញាតឲ្យកម្មវិធីបដិសេធទីតាំង និង/ឬស្ថានភាពបានត្រឡប់ដោយប្រភពទីតាំងផ្សេងដូចជា GPS ឬក្រុមហ៊ុនផ្ដល់ទីតាំង។"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ចូលដំណើរការពាក្យបញ្ជាក្រុមហ៊ុនផ្ដល់ទីតាំង"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"ឲ្យកម្មវិធីចូលពាក្យបញ្ជាក្រុមហ៊ុនផ្ដល់ទីតាំងបន្ថែម។ កម្មវិធីព្យាបាទអាចប្រើវាដើម្បីជ្រៀតជ្រែកជាមួយប្រតិបត្តិការ GPS ឬប្រភពទីតាំងផ្សេងទៀត។"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ឲ្យកម្មវិធីចូលដំណើរការពាក្យបញ្ជាកម្មវិធីផ្ដល់ទីតាំងបន្ថែម។ វាអាចអនុញ្ញាតឲ្យកម្មវិធីទាក់ទងជាមួយប្រតិបត្តិការជីភីអេស ឬប្រភពទីតាំងផ្សេង។"</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"សិទ្ធិ ដើម្បីដំឡើងក្រុមហ៊ុនផ្ដល់ទីតាំង"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"បង្កើតប្រភពទីតាំងក្លែងក្លាយសម្រាប់សាកល្បង ឬដំឡើងក្រុមហ៊ុនផ្ដល់ទីតាំងថ្មី។ វាអនុញ្ញាតឲ្យកម្មវិធីបដិសេធទីតាំង និង/ឬស្ថានភាពបានត្រឡប់ដោយប្រភពទីតាំងផ្សេងៗដូចជា GPS ឬក្រុមហ៊ុនផ្ដល់ទីតាំង។"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ទីតាំងពិតប្រាកដ (GPS និងមានមូលដ្ឋានលើបណ្ដាញ)"</string>
@@ -713,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ឲ្យកម្មវិធីគ្រប់គ្រងគោលនយោបាយបណ្ដាញ និងកំណត់ក្បួនជាក់លាក់សម្រាប់កម្មវិធី។"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"កែគណនីប្រើបណ្ដាញ"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ឲ្យកម្មវិធីកែវិធីគិតថ្លៃសេវាកម្មប្រើបណ្ដាញតាមកម្មវិធី។ មិនសម្រាប់ប្រើដោយកម្មវិធីធម្មតា។"</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"កែប្រែសញ្ញារន្ធ"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"ឲ្យកម្មវិធីកែសញ្ញារន្ធសម្រាប់នាំផ្លូវ"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"ចូលដំណើរការការជូនដំណឹង"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"ឲ្យកម្មវិធីទៅយក ពិនិត្យ និងសម្អាតការជូនដំណឹង រួមមានប្រកាសដោយកម្មវិធីផ្សេងៗ។"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ចងទៅសេវាកម្មស្ដាប់ការជូនដំណឹង"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ឲ្យម្ចាស់ចងចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មកម្មវិធីស្ដាប់ការជូនដំណឹង។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ភ្ជាប់ទៅសេវាកម្មក្រុមហ៊ុនផ្ដល់លក្ខខណ្ឌ"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅចំណុចប្រទាក់កម្រិតកំពូលរបស់សេវាកម្មក្រុមហ៊ុនផ្ដល់លក្ខខណ្ឌ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"ភ្ជាប់ទៅសេវាផ្លូវមេឌៀ"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅចំណុចប្រទាក់ពេញនិយមនៃសេវាកម្មផ្លូវមេឌៀ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"ភ្ជាប់ទៅសេវាកម្មស្រមោលស្រមៃ"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"អនុញ្ញាតឲ្យម្ចាស់ភ្ជាប់ទៅចំណុចប្រទាក់កម្រិតកំពូលនៃសេវាកម្មស្រមើស្រមៃ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ដកហូតកម្មវិធីកំណត់រចនាសម្ព័ន្ធដែលបានផ្ដល់ដោយក្រុមហ៊ុនបញ្ជូន"</string>
@@ -731,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"ឲ្យកម្មវិធីកែប៉ារ៉ាម៉ែត្រកែចំណុចនៃការប៉ះអេក្រង់។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"ចូលមើលវិញ្ញាបនបត្រ DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"ឲ្យកម្មវិធីផ្ដល់ និងប្រើវិញ្ញាបនបត្រ DRM ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"ទទួលបានការផ្សាយផ្ទេរ។"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"អនុញ្ញាតឲ្យទទួលបានព័ត៌មានស្ថានភាពផ្ទេរ។"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"ទទួលស្ថានភាពផ្ទេរ Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"ឲ្យកម្មវិធីទទួលព័ត៌មានអំពីការផ្ទេរ Android Beam បច្ចុប្បន្ន"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"កំណត់ក្បួនពាក្យសម្ងាត់"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ពិនិត្យប្រវែង និងតួអក្សរដែលបានអនុញ្ញាតក្នុងពាក្យសម្ងាត់ចាក់សោអេក្រង់។"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ពិនិត្យការព្យាយាមដោះសោអេក្រង់"</string>
@@ -1006,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ឲ្យកម្មវិធីកែប្រវត្តិ ឬចំណាំរបស់កម្មវិធីអ៊ីនធឺណិតដែលបានរក្សាទុកក្នុងទូរស័ព្ទរបស់អ្នក។ កម្មវិធីព្យាបាទអាចប្រើវាដើម្បីលុប ឬកែទិន្នន័យនៃកម្មវិធីអ៊ីនធឺណិតរបស់អ្នក។ ចំណាំ៖ សិទ្ធិនេះអាចត្រូវបានបង្ខំដោយកម្មវិធីអ៊ីនធឺណិតភាគីទីបី ឬកម្មវិធីផ្សេងដែលមានសមត្ថភាពរុករកបណ្ដាញ។ស"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"កំណត់សំឡេងរោទ៍"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"ឲ្យកម្មវិធីកំណត់សំឡេងរោទ៍ក្នុងកម្មវិធីនាឡិការោទ៍បានដំឡើង។ កម្មវិធីនាឡិការោទ៍មួយចំនួនអាចមិនអនុវត្តលក្ខណៈនេះ។"</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"លុបសារជាសំឡេង"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"អនុញ្ញាតឲ្យកម្មវិធីលុបសារចេញពីប្រអប់ទទួលសារជាសំឡេងរបស់អ្នក។"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"គ្រប់គ្រងសារជាសំឡេង"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"ឲ្យកម្មវិធីកែប្រែ និងលុបសារចេញពីប្រអប់ទទួលសារជាសំឡេងរបស់អ្នក។"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"បន្ថែមសារជាសំឡេង"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"ឲ្យកម្មវិធីបន្ថែមសារទៅប្រអប់ទទួលសារជាសំឡេងរបស់អ្នក។"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"អានសារជាសំឡេងទាំងអស់"</string>
@@ -1179,6 +1179,15 @@
<string name="capital_on" msgid="1544682755514494298">"បើក"</string>
<string name="capital_off" msgid="6815870386972805832">"បិទ"</string>
<string name="whichApplication" msgid="4533185947064773386">"បញ្ចប់សកម្មភាពដោយប្រើ"</string>
+ <!-- String.format failed for translation -->
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <string name="whichViewApplication" msgid="3272778576700572102">"បើកជាមួយ"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"បើកជាមួយ %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"កែសម្រួលជាមួយ"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"កែសម្រួលជាមួយ %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"ចែករំលែកជាមួយ"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"ចែករំលែកជាមួយ"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"ជ្រើសកម្មវិធីដើម"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ប្រើតាមលំនាំដើមសម្រាប់សកម្មភាពនេះ។"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"សម្អាតលំនាំដើមក្នុងការកំណត់ប្រព័ន្ធ > កម្មវិធី > ទាញយក។"</string>
@@ -1281,10 +1290,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"អនុញ្ញាតជានិច្ច"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"កុំអនុញ្ញាត"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"បានដកស៊ីមកាតចេញ"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញចល័តនឹងប្រើលែងបានរហូតដល់អ្នកចាប់ផ្ដើមជាមួយស៊ីមកាតដែលបាបញ្ចូលត្រឹមត្រូវ។"</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"បណ្ដាញចល័តនឹងមិនអាចប្រើបាន លុះត្រាតែអ្នកចាប់ផ្ដើមឡើងវិញដោយបញ្ចូលស៊ីមកាតត្រឹមត្រូវ។"</string>
<string name="sim_done_button" msgid="827949989369963775">"រួចរាល់"</string>
<string name="sim_added_title" msgid="3719670512889674693">"បានបន្ថែមស៊ីមកាត"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"ចាប់ផ្ដើមឧបករណ៍របស់អ្នកឡើងវិញ ដើម្បីចូលដំណើរការបណ្ដាញចល័ត។"</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"ចាប់ផ្ដើមឧបករណ៍របស់អ្នក ដើម្បីចូលប្រើបណ្ដាញចល័ត។"</string>
<string name="sim_restart_button" msgid="4722407842815232347">"ចាប់ផ្ដើមឡើងវិញ"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់ម៉ោង"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់កាលបរិច្ឆេទ"</string>
@@ -1735,10 +1744,25 @@
<string name="item_is_selected" msgid="949687401682476608">"បានជ្រើស <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"បានលុប <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"កន្លែងធ្វើការ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"អ្នកស្ថិតក្នុងរបៀបចាក់សោទៅកម្មវិធី។"</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"ប្រើការចាក់សោកម្មវិធី?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"ចាក់សោកម្មវិធីគឺចាក់សោការបង្ហាញក្នុងកម្មវិធីតែមួយ។\n\nដើម្បីចាកចេញ ចុច និងសង្កត់ប៊ូតុងកម្មវិធីថ្មីៗ $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"ទេ"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ចាប់ផ្ដើម"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"ចាប់ផ្ដើមការចាក់សោកម្មវិធី"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"ចេញពីការចាក់សោកម្មវិធី"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index ada1848..b799362 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"앱이 휴대전화 또는 SIM 카드에 저장된 SMS 메시지에 쓸 수 있도록 허용합니다. 이 경우 악성 앱이 이 기능을 이용하여 메시지를 삭제할 수 있습니다."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"문자 메시지 받기(WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"앱이 WAP 메시지를 수신하고 처리할 수 있도록 허용합니다. 이는 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 모니터링 또는 삭제할 수도 있다는 것을 의미합니다."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"블루투스 메시지(MAP) 수신"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"앱이 블루투스 MAP 메시지를 수신하고 처리하도록 허용합니다. 이는 앱이 나에게 보여주지 않고 내 기기에 전송된 메시지를 모니터링하거나 삭제할 수 있음을 의미합니다."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"실행 중인 앱 검색"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"앱이 현재 실행 중이거나 최근에 실행된 작업에 대한 정보를 검색할 수 있도록 허용합니다. 이 경우 앱이 기기에서 사용되는 다른 앱에 대한 정보를 검색할 수 있습니다."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"여러 사용자와의 상호작용"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"테스트를 위해 위치 정보제공자로 가장"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"테스트용 가상 위치 소스를 만들거나 새로운 위치 정보 제공업체를 설치합니다. 이 경우 앱이 GPS 또는 위치 정보 제공업체 등 기타 위치 소스가 반환한 위치 또는 상태를 덮어쓸 수 있습니다."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"추가 위치 제공업체 명령에 액세스"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"앱이 추가 위치 정보 제공업체 명령에 액세스하도록 허용합니다. 이 경우 앱이 GPS 또는 기타 위치 소스의 작동을 방해하게 될 수 있습니다."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"앱이 추가 위치 정보 제공 기능의 명령에 액세스하도록 허용합니다. 이 경우 앱이 GPS 또는 기타 위치 소스의 작동을 방해할 수 있습니다."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"위치 정보 공급자 설치 권한"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"테스트용 가상 위치 소스를 만들거나 새로운 위치 정보 제공업체를 설치합니다. 이 경우 앱이 GPS 또는 위치 정보 제공업체 등 기타 위치 소스가 반환한 위치 또는 상태를 덮어쓸 수 있습니다."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"정확한 위치(GPS 및 네트워크 기반)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"앱이 네트워크 정책을 관리하고 앱별 규칙을 정의할 수 있도록 허용합니다."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"네트워크 사용량 계산 수정"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"애플리케이션이 애플리케이션의 네트워크 사용량을 계산하는 방식을 수정할 수 있도록 허용합니다. 일반 애플리케이션에서는 사용하지 않습니다."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"소켓 마크 수정"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"앱이 라우팅의 소켓 마크를 수정하도록 합니다."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"알림 액세스"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"앱이 다른 앱에서 게시한 알림을 비롯하여 알림을 검색하고 살펴보며 삭제할 수 있도록 허용합니다."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"알림 수신기 서비스 사용"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"권한을 가진 프로그램이 알림 수신기 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"조건 제공자 서비스 사용"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"권한을 가진 프로그램이 조건 제공자 서비스의 최상위 인터페이스를 사용하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"드림 서비스에 연결"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"권한을 가진 프로그램이 드림 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"이동통신사에서 제공한 구성 앱 호출"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"앱이 터치 스크린의 보정 매개변수를 수정할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM 인증서에 액세스"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"애플리케이션이 DRM 인증서를 프로비저닝하고 사용하도록 허용합니다. 일반 앱에서는 필요하지 않습니다."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"핸드오버 전송 브로드캐스트를 수신합니다."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"핸드오버 전송 상태 정보를 받도록 허용합니다."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Android Beam 전송 상태 수신"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"이 애플리케이션이 현재 Android Beam 전송 관련 정보를 수신하도록 허용합니다."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"앱이 휴대전화에 저장된 브라우저 기록 또는 북마크를 수정할 수 있도록 허용합니다. 이 경우 앱이 브라우저 데이터를 삭제 또는 수정할 수 있습니다. 참고: 이 권한은 타사 브라우저 또는 브라우저 기능을 가진 기타 애플리케이션에 적용되지 않습니다."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"알람 설정"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"앱이 설치된 알람 시계 앱에서 알람을 설정할 수 있도록 허용합니다. 일부 알람 시계 앱에는 이 기능이 구현되지 않을 수 있습니다."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"음성 메시지 삭제"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"앱이 음성사서함에서 메시지를 삭제하도록 허용합니다."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"음성사서함 관리"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"앱이 음성사서함에서 메시지를 수정하고 삭제하도록 허용합니다."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"음성사서함 추가"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"앱이 음성사서함에 메시지를 추가할 수 있도록 허용합니다."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"모든 음성사서함 읽기"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"ON"</string>
<string name="capital_off" msgid="6815870386972805832">"OFF"</string>
<string name="whichApplication" msgid="4533185947064773386">"작업을 수행할 때 사용하는 애플리케이션"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"홈 앱 선택"</string>
<string name="alwaysUse" msgid="4583018368000610438">"이 작업에 대해 기본값으로 사용"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"시스템 설정 > 앱 > 다운로드로 이동하여 기본 설정을 지웁니다."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"항상 허용"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"허용 안함"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM 카드 제거됨"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"유효한 SIM 카드를 삽입하여 다시 시작할 때까지 모바일 네트워크를 사용할 수 없습니다."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"완료"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM 카드 추가됨"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"모바일 네트워크에 액세스하려면 기기를 다시 시작하세요."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"다시 시작"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"시간 설정"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"날짜 설정"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g>이(가) 선택됨"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 삭제됨"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"앱 잠금 기능을 사용 중입니다."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"앱 잠금 기능을 사용하시겠습니까?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"앱 잠금 기능은 단일 앱의 화면을 잠급니다.\n\n종료하려면 최근 앱 버튼 $를 길게 누릅니다."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"아니요"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"시작"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"앱 잠금 기능 시작"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"앱 잠금 기능 종료"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index fa1041a..1d6bff0 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"ຈຳລອງແຫລ່ງຂໍ້ມູນສະຖານທີ່ເພື່ອການທົດສອບ"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"ສ້າງແຫລ່ງຂໍ້ມູນຈຳລອງຂອງສະຖານທີ່ ເພື່ອການທົດສອບ ຫຼືຕິດຕັ້ງແຫລ່ງຂໍ້ມູນສະຖານທີ່ໃໝ່. ນີ້ຈະອະນຸຍາດໃຫ້ແອັບຯສາມາດຂຽນທັບຂໍ້ມູນຂອງສະຖານທີ່ ແລະ/ຫຼື ຂໍ້ມູນທີ່ສົ່ງກັບມາຈາກແຫລ່ງຂໍ້ມູນສະຖານທີ່ອື່ນ ເຊັ່ນ: GPS ຫຼືແຫລ່ງຂໍ້ມູນສະຖານທີ່ອື່ນໄດ້."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ເຂົ້າເຖິງຄຳສັ່ງຜູ່ໃຫ້ບໍລິການພິກັດສະຖານທີ່"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"ອະນຸຍາດໃຫ້ແອັບຯ ເຂົ້າເຖິງຄຳສັ່ງເພີ່ມເຕີມຂອງຜູ່ໃຫ້ບໍລິການສະຖານທີ່. ນີ້ອາດຈະເປັນການເຮັດໃຫ້ແອັບຯ ລົບກວນການເຮັດວຽກຂອງ GPS ຫຼືແຫລ່ງຂໍ້ມູນສະຖານທີ່ອື່ນໆໄດ້."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ອະນຸຍາດໃຫ້ແອັບຯເຂົ້າເຖິງຄຳສັ່ງເພີ່ມເຕີມຂອງຜູ່ໃຫ້ບໍລິການສະຖານທີ່. ນີ້ອາດຈະເປັນການເຮັດໃຫ້ແອັບຯ ລົບກວນການເຮັດວຽກຂອງ GPS ຫຼືແຫລ່ງຂໍ້ມູນສະຖານທີ່ອື່ນໆໄດ້."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"ສິດໃນການຕິດຕັ້ງແຫຼ່ງສະໜອງສະຖານທີ່"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"ສ້າງສະຖານທີ່ຈຳລອງເພື່ອການທົດລອງ ຫຼືຕິດຕັ້ງແຫຼ່ງຂໍ້ມູນສະຖານທີ່ໃໝ່. ສິ່ງນີ້ເຮັດໃຫ້ແອັບຯສາມາດຂຽນທັບສະຖານທີ່ ແລະ/ຫຼື ສະຖານະທີ່ໄດ້ຈາກແຫຼ່ງສະຖານທີ່ອື່ນເຊັ່ນ: GPS ຫຼືຜູ່ສະໜອງສະຖານທີ່ຕ່າງໆ."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ສະຖານທີ່ແນ່ນອນ (ອ້າງອີງຈາກ GPS ແລະເຄືອຂ່າຍ)"</string>
@@ -713,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ອະນຸຍາດໃຫ້ແອັບຯຈັດການກັບນະໂຍບາຍເຄືອຂ່າຍ ແລະກຳນົດກົດລະບຽບສະເພາະຂອງແອັບຯ."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ແກ້ໄຂການຄຳນວນການນຳໃຊ້ເຄືອຂ່າຍ"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂວິທີການບັນທຶກບັນຊີ ການນຳໃຊ້ເຄືອຂ່າຍຂອງແອັບຯ. ແອັບຯທົ່ວໄປບໍ່ຈຳເປັນຕ້ອງໃຊ້."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"ດັດແປງຊັອກເກັດມາກ"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂຊັອກເກັດທີ່ໝາຍໄວ້ສຳລັບກຳນົດເສັ້ນທາງ"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"ເຂົ້າເຖິງການແຈ້ງເຕືອນ"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"ອະນຸຍາດໃຫ້ແອັບຯດຶງຂໍ້ມູນ, ກວດສອບ ແລະລຶບລ້າງການແຈ້ງເຕືອນ ຮວມທັງພວກທີ່ໂພສໂດຍແອັບຯອື່ນໆນຳ."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ເຊື່ອມໂຍງກັບບໍລິການໂຕຟັງການແຈ້ງເຕືອນ"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງສ່ວນຕິດຕໍ່ລະດັບເທິງສຸດ ຂອງຜູ່ຟັງບໍລິການການແຈ້ງເຕືອນ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ເຊື່ອມໂຍງກັບບໍລິການຜູ່ສະໜອງເງື່ອນໄຂ"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງສ່ວນຕິດຕໍ່ລະດັບສູງສຸດຂອງບໍລິການສະໜອງເງື່ອນໄຂ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"ເຊື່ອມໂຍງກັບບໍລິການເສັ້ນທາງມີເດຍ"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"ອະນຸຍາດໃຫ້ຜູ່ໃຊ້ເຊື່ອມໂຍງກັບສ່ວນຕິດຕໍ່ຜູ່ໃຊ້ລະດັບສູງສຸດຂອງບໍລິການເສັ້ນທາງມີເດຍ. ແອັບຯທົ່ວໄປບໍ່ຄວນຕ້ອງໃຊ້."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"ຜູກກັບບໍລິການ dream"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດ ຂອງບໍລິການ dream. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ຮ້ອງຂໍແອັບຯປັບຄ່າທີ່ສະໜອງໂດຍຜູ່ໃຫ້ບໍລິການ"</string>
@@ -731,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂຄ່າການວັດແທ້ໜ້າຈໍສຳຜັດ. ແອັບຯທຳມະດາບໍ່ຄວນໃຊ້."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"ເຂົ້າເຖິງໃບຮັບຮອງ DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນຈັດຫາ ແລະນຳໃຊ້ໃບຮັບຮອງ DRM. ແອັບຯທຳມະດາບໍ່ຄວນຕ້ອງການໃຊ້."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"ຮັບການກະຈາຍຂໍ້ມູນການໂອນຍ້າຍການສົ່ງຕໍ່."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"ອະນຸຍາດການຮັບຂໍ້ມູນສະຖານະການສົ່ງຕໍ່."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"ຮັບສະຖານະການໂອນຂໍ້ມູນ Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນນີ້ຮັບຂໍ້ມູນກ່ຽວກັບການໂອນຂໍ້ມູນ Android Beam ໃນປັດຈຸບັນ"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ຄວບຄຸມຄວາມຍາວຂອງໂຕອັກສອນທີ່ສາມາດໃຊ້ກັບລະຫັດປົດລັອກໜ້າຈໍ"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
@@ -1006,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ອະນຸຍາດໃຫ້ແອັບຯ ແກ້ໄຂປະຫວັດໂປຣແກຣມທ່ອງເວັບ ຫຼືບຸກມາກທີ່ເກັບໄວ້ໃນໂທລະສັບຂອງທ່ານ. ນີ້ອາດອະນຸຍາດໃຫ້ແອັບຯລຶບ ຫຼືແກ້ໄຂຂໍ້ມູນໂປຣແກຣມທ່ອງເວັບ. ໝາຍເຫດ: ການກຳນົດສິດນີ້ ອາດບໍ່ໄດ້ຖືກບັງຄັບໃຊ້ໃນໂປຣແກຣມທ່ອງເວັບພາກສ່ວນທີສາມ ຫຼືແອັບພລິເຄຊັນອື່ນທີ່ມີຄວາມສາມາດທ່ອງເວັບ."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"ຕັ້ງການແຈ້ງເຕືອນ"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"ອະນຸຍາດໃຫ້ແອັບຯຕັ້ງໂມງປຸກໃນແອັບຯໂມງປຸກທີ່ຕິດຕັ້ງໄວ້. ບາງແອັບຯໂມງປຸກອາດບໍ່ມີຄຸນສົມບັດແບບນີ້ເທື່ອ."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"ລຶບຂໍ້ຄວາມສຽງອອກ"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"ອະນຸຍາດໃຫ້ແອັບຯລຶບຂໍ້ຄວາມຈາກອິນບັອກຂໍ້ຄວາມສຽງຂອງທ່ານໄດ້."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"ຈັດການຂໍ້ຄວາມສຽງ"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂແລະລຶບຂໍ້ຄວາມອອກຈາກອິນບັອກຂໍ້ຄວາມສຽງຂອງທ່ານ."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"ເພີ່ມຂໍ້ຄວາມສຽງ"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດເພີ່ມຂໍ້ຄວາມໃສ່ອິນບັອກຂໍ້ຄວາມສຽງຂອງທ່ານໄດ້."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ອ່ານຂໍ້ຄວາມສຽງທັງໝົດ"</string>
@@ -1179,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"ເປີດ"</string>
<string name="capital_off" msgid="6815870386972805832">"ປິດ"</string>
<string name="whichApplication" msgid="4533185947064773386">"ດຳເນີນການໂດຍໃຊ້"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"ສຳເລັດການດຳເນີນການໂດຍໃຊ້ %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"ເປີດໂດຍໃຊ້"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"ເປີດໂດຍໃຊ້ %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"ແກ້ໄຂໃນ"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"ແກ້ໄຂໃນ %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"ແບ່ງປັນກັບ"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"ແບ່ງປັນກັບ %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"ເລືອກແອັບຯ Home"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ໃຊ້ໂດຍຄ່າເລີ່ມຕົນສຳລັບການເຮັດວຽກນີ້."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"ລຶບລ້າງຄ່າເລີ່ມຕົ້ນ ໃນ ການຕັ້ງຄ່າລະບົບ > ແອັບຯ > ດາວໂຫລດແລ້ວ."</string>
@@ -1281,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"ອະນຸຍາດທຸກຄັ້ງ"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"ບໍ່ອະນຸຍາດເດັດຂາດ"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"ຖອດ SIM card ອອກແລ້ວ"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"ເຄືອຂ່າຍມືຖືຈະບໍ່ສາມາດໃຊ້ໄດ້ ຈົນກວ່າທ່ານຈະປິດແລ້ວເປີດໃໝ່ພ້ອມກັບໃສ່ SIM card ທີ່ຖືກຕ້ອງ."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"ເຄືອຂ່າຍມືຖືຈະບໍ່ສາມາດໃຊ້ໄດ້ຈົນກວ່າທ່ານຈະຣີສະຕາດພ້ອມກັບໃສ່ SIM ທີ່ສາມາດໃຊ້ໄດ້."</string>
<string name="sim_done_button" msgid="827949989369963775">"ແລ້ວໆ"</string>
<string name="sim_added_title" msgid="3719670512889674693">"ເພີ່ມຊິມກາດແລ້ວ"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"ປິດແລ້ວເປີດອຸປະກອນຂອງທ່ານ ເພື່ອເຂົ້າເຖິງເຄືອຂ່າຍມືຖື."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"ຣີສະຕາດອຸປະກອນຂອງທ່ານເພື່ອເຂົ້າເຖິງເຄືອຂ່າຍມືຖື."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"ຣີສະຕາດ"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"ຕັ້ງເວລາ"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"ກໍານົດວັນທີ"</string>
@@ -1735,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ຖືກເລືອກແລ້ວ"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ຖືກລຶບແລ້ວ"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"ບ່ອນເຮັດວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"ທ່ານຢູ່ໃນໂໝດ Lock-to-App."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"ນຳໃຊ້ lock-to-app ບໍ່?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app ຈະລັອກໜ້າຈໍໄວ້ຢູ່ກັບແອັບຯດຽວ.\n\nເພື່ອອອກຈາກມັນ ກະລຸນາກົດປຸ່ມແອັບທີ່ຫາກໍໃຊ້ຄ້າງໄວ້ $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"ບໍ່"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ເລີ່ມ"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"ເລີ່ມຕົ້ນ Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"ອອກຈາກ Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 0047018..d6f1311 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Leidžiama programai rašyti SMS pranešimus, išsaugotus jūsų telefone ar SIM kortelėje. Kenkėjiškos programos gali ištrinti jūsų pranešimus."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"gauti teksto pranešimus (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Leidžiama programai gauti ir apdoroti WAP pranešimus. Šis leidimas apima galimybę stebėti ar ištrinti jums siunčiamus pranešimus jums jų neparodžius."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"gauti „Bluetooth“ pranešimus (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Programai leidžiama gauti ir apdoroti „Bluetooth“ MAP pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"nuskaityti vykdomas programas"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Leidžiama programai nuskaityti informaciją apie šiuo ir pastaruoju metu vykdomas užduotis. Taip programa gali atrasti informacijos, kokios programos naudojamos įrenginyje."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"sąveikauti su naudotojais"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"imituoti vietos šaltinius bandymui"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Kurti bandomuosius imituojančius vietos nustatymo šaltinius arba įdiegti naują vietos nustatymo paslaugų teikėją. Programai leidžiama nepaisyti vietos ir (arba) būsenos, kurią pateikia kiti vietos nustatymo šaltiniai, pvz., GPS arba vietos nustatymo paslaugų teikėjai."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"pasiekti papildomas vietos teikimo įrankio komandas"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Leidžiama programai pasiekti papildomas vietos nustatymo paslaugų teikėjų komandas. Dėl to programa gali trukdyti veikti GPS ar kitiems vietos nustatymo šaltiniams."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Programai leidžiama pasiekti papildomas vietovės nustatymo paslaugų teikėjų komandas. Dėl to programa gali trukdyti veikti GPS ar kitiems vietovės nustatymo šaltiniams."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"leidimas įdiegti vietos teikimo įrankį"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Kurti bandomuosius imituojančius vietos nustatymo šaltinius arba įdiegti naują vietos nustatymo paslaugų teikėją. Programai leidžiama nepaisyti vietos ir (arba) būsenos, kurią pateikia kiti vietos nustatymo šaltiniai, pvz., GPS arba vietos nustatymo paslaugų teikėjai."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"tiksli vieta (pagrįsta pagal GPS ir tinklą)"</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Leidžiama programai valdyti tinklo politiką ir apibrėžti konkrečios programos taisykles."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"keisti tinklo naudojimo apskaitą"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Leidžiama programai keisti, kaip tinklas naudojamas, palyginti su programomis. Neskirta naudoti įprastoms programoms."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modifikuoti lizdų ženklus"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Programai leidžiama modifikuoti maršrutui parinkti skirtus lizdų ženklus"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"pasiekti pranešimus"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Programai leidžiama gauti, patikrinti ir išvalyti pranešimus, įskaitant pranešimus, kuriuos paskelbė kitos programos."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"susisaistyti su pranešimų skaitymo priemonės paslauga"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Leidžiama turėtojui susisaistyti su pranešimų skaitymo priemonės paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"susaistyti su sąlygos teikėjo paslauga"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Turėtojui leidžiama susaistyti programą su sąlygos teikėjo paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to niekada neturėtų prireikti."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"susaistyti su medijos maršruto paslauga"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Leidžiama savininką susaistyti su aukščiausio lygio medijos maršruto paslaugos sąsaja. Niekada neturėtų būti reikalinga įprastoms programoms."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"susisaistyti su mėgstama paslauga"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Savininkui leidžiama susisaistyti su mėgstamos paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"iškviesti operatoriaus pateiktą konfigūravimo programą"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Leidžiama programai keisti jutiklinio ekrano kalibravimo parametrus. Neturėtų prireikti naudojant įprastas programas."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"gali pasiekti DRM sertifikatus"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Programai leidžiama pasiekti ir naudoti DRM sertifikatus. Neturėtų prireikti naudojant įprastas programas."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Gauti perdavimo transliacijas."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Leidžiama gauti perdavimo būsenos informaciją."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Gauti „Android“ perdavimo funkcijos perkėlimo būseną"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Programai leidžiama gauti informaciją apie dabartinius „Android“ perdavimo funkcijos perkėlimus"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir leidžiamus naudoti simbolius."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
@@ -1008,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Leidžiama programai keisti naršyklės istoriją ar žymes, išsaugotas telefone. Dėl to programai gali būti leidžiama ištrinti ar keisti naršyklės duomenis. Pastaba: šis leidimas nesuteikiamas trečiosios šalies naršyklėms ar kitoms programoms, kuriomis galima naršyti žiniatinklį."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"nustatyti pavojaus signalą"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Leidžiama programai nustatyti signalą įdiegtoje žadintuvo programoje. Kai kuriose žadintuvo programose ši funkcija gali nebūti nevykdoma."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"pašalinti balso pašto pranešimus"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Programai leidžiama pašalinti pranešimus iš balso pašto gautųjų."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"tvarkyti balso paštą"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Programai leidžiama keisti ir šalinti pranešimus iš balso pašto gautųjų."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"pridėti balso pašto pranešimų"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Leidžia programai pridėti pranešimų prie jūsų balso pašto gautųjų."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"skaityti visus balso pašto pranešimus"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"ĮJ."</string>
<string name="capital_off" msgid="6815870386972805832">"IŠJ."</string>
<string name="whichApplication" msgid="4533185947064773386">"Užbaigti veiksmą naudojant"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"Užbaigti veiksmą naudojant %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Atidaryti naudojant"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Atidaryti naudojant %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Redaguoti naudojant"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Redaguoti naudojant %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Bendrinti naudojant"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Bendrinti naudojant %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Pasirinkite programą, paleidžiamą spustelėjus pagrindinio ekrano mygtuką"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Šiam veiksmui tai naudoti pagal numatytuosius nustatymus."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Numatytuosius nustatymus išvalykite nuėję į „Sistemos nustatymai“ > „Programos“ > „Atsisiųsta“."</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Visada leisti"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Niekada neleisti"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM kortelė pašalinta"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mobilusis tinklas bus nepasiekiamas, kol nepaleisite iš naujo įdėję tinkamą SIM kortelę."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"Negalėsite pasiekti korinio tinklo, kol iš naujo paleisite įrenginį įdėję tinkamą SIM kortelę."</string>
<string name="sim_done_button" msgid="827949989369963775">"Atlikta"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM kortelė pridėta"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Jei norite pasiekti mobiliojo ryšio tinklą, reikia iš naujo paleisti įrenginį."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Iš naujo paleiskite įrenginį, kad pasiektumėte korinį tinklą."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Paleisti iš naujo"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Nustatyti laiką"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Nustatyti datą"</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Pasirinkta: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Ištrinta: <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Įjungėte programos užrakinimo funkcijos režimą."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Naudoti programos užrakinimo funkciją?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Naudojant programos užrakinimo funkciją ekrane užrakinama viena programa.\n\nJei norite išeiti, paspauskite ir palaikykite paspaudę naujausių programų mygtuką $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NE"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ĮJUNGTI"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Įjungti programos užrakinimo funkciją"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Išeiti iš programos užrakinimo funkcijos"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index d23670d..c2a78c8 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Ļauj lietotnei rakstīt īsziņās, kas ir saglabātas tālrunī vai SIM kartē. Ļaunprātīgas lietotnes var dzēst jūsu ziņojumus."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"saņemt īsziņas (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Ļauj lietotnei saņemt un apstrādāt WAP ziņojumus. Šī atļauja ietver iespēju pārraudzīt vai dzēst jums nosūtītos ziņojumus, neparādot tos jums."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"saņemt Bluetooth ziņojumus (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Ļauj lietotnei saņemt un apstrādāt Bluetooth MAP ziņojumus. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"izgūt izmantotās lietotnes"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Ļauj lietotnei izgūt informāciju par pašreiz un nesen darbinātajiem uzdevumiem. Tādējādi lietotne var atklāt informāciju par ierīcē izmantotajām lietojumprogrammām."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"darboties visos lietotāju kontos"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"imitēt atrašanās vietu avotus pārbaudes nolūkos"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Izveido neīstus atrašanās vietas noteikšanas avotus testēšanas nolūkiem vai instalē jaunu atrašanās vietas noteikšanas nodrošinātāju. Tas ļauj lietotnei ignorēt atrašanās vietu un/vai statusu, ko norādīja citi atrašanās vietas noteikšanas avoti, piemēram, GPS vai atrašanās vietas noteikšanas nodrošinātāji."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"piekļūt atrašanās vietas nodrošinātāja papildu komandām"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Ļauj lietotnei piekļūt papildu atrašanās vietas noteikšanas nodrošinātāju komandām. Tas var ļaut lietotnei traucēt GPS vai citu atrašanās vietas noteikšanas avotu darbību."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ļauj lietotnei piekļūt papildu atrašanās vietas noteikšanas nodrošinātāju komandām. Tas var ļaut lietotnei traucēt GPS vai citu atrašanās vietas noteikšanas avotu darbību."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"atļauja instalēt atrašanās vietas sniedzēju"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Izveido neīstus atrašanās vietas noteikšanas avotus testēšanas nolūkiem vai instalē jaunu atrašanās vietas noteikšanas nodrošinātāju. Tas ļauj lietotnei ignorēt atrašanās vietu un/vai statusu, ko norādīja citi atrašanās vietas noteikšanas avoti, piemēram, GPS vai atrašanās vietas noteikšanas nodrošinātāji."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"precīza atrašanās vieta (GPS un tīklā)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Ļauj lietotnei pārvaldīt tīkla politikas un noteikt lietotnes kārtulas."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Tīkla lietojuma uzskaites mainīšana"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ļauj lietotnei mainīt to, kā tīkla lietojums tiek uzskaitīts saistībā ar lietotnēm. Atļauja neattiecas uz parastām lietotnēm."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"Ligzdu atzīmju izmaiņas"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Ļauj lietotnei mainīt maršrutēšanai paredzēto ligzdu atzīmes."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"piekļuve paziņojumiem"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Ļauj lietotnei izgūt, pārbaudīt un dzēst paziņojumus, tostarp lietotņu publicētos paziņojumus."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"saites izveidošana ar paziņojumu uztvērēja pakalpojumu"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ļauj īpašniekam izveidot saiti ar paziņojumu uztvērēja pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"Saistīšana ar nosacījumu sniedzēja pakalpojumu"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ļauj īpašniekam izveidot savienojumu ar drukas nosacījumu sniedzēja pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"piesaistīt ekrānsaudzētāja pakalpojumu"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Ļauj īpašniekam piesaistīt ekrānsaudzētāja pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Operatora nodrošinātas konfigurācijas lietotnes izsaukšana"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Ļauj lietotnei pārveidot skārienekrāna kalibrēšanas parametrus. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Piekļuve digitālā satura tiesību pārvaldības sertifikātiem"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Ļauj lietojumprogrammai nodrošināt un izmantot digitālā satura tiesību pārvaldības sertifikātus. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Saņemiet ziņojumus par nodošanu."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Ļauj saņemt informāciju par nodošanas statusu."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Saņemt Android Beam pārsūtīšanas statusu"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Ļauj šai lietojumprogrammai saņemt informāciju par pašreizēju Android Beam pārsūtīšanu"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolē ekrāna atbloķēšanas parolē atļautās rakstzīmes un garumu."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Ļauj lietotnei mainīt tālrunī saglabāto pārlūkprogrammas vēsturi vai grāmatzīmes. Tas var ļaut lietotnei dzēst vai pārveidot pārlūkprogrammas datus. Piezīme: šo atļauju nevar piemērot trešo pušu pārlūkprogrammas vai citas lietojumprogrammas ar tīmekļa pārlūkošanas iespējām."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"iestatīt modinātāju"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Ļauj lietotnei iestatīt signālu instalētajā modinātājpulksteņa lietotnē. Dažās modinātājpulksteņu lietotnēs šo funkciju, iespējams, nevar ieviest."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"noņemt balss pastu"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Ļauj lietotnei noņemt ziņojumus no jūsu balss pasta iesūtnes."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"pārvaldīt balss pastu"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Ļauj lietotnei rediģēt un noņemt ziņojumus no jūsu balss pasta iesūtnes."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"pievienot balss pastu"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ļauj lietotnei pievienot ziņojumus jūsu balss pasta iesūtnei."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"lasīt visus balss pasta ziņojumus"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"IESLĒGT"</string>
<string name="capital_off" msgid="6815870386972805832">"IZSLĒGT"</string>
<string name="whichApplication" msgid="4533185947064773386">"Pabeigt darbību, izmantojot"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Sākuma ekrāna lietotnes atlase"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Pēc noklusējuma izmantot šai darbībai."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Notīriet noklusējuma iestatījumus šeit: Sistēmas iestatījumi > Lietotnes > Lejupielādētās."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Vienmēr atļaut"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Neatļaut nekad"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM karte ir izņemta."</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mobilais tīkls nebūs pieejams līdz brīdim, kad restartēsiet ierīci ar ievietotu derīgu SIM karti."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Gatavs"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM karte ir pievienota."</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Ierīces restartēšana, lai piekļūtu mobilo sakaru tīklam."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Restartēt"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Laika iestatīšana"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Datuma iestatīšana"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Atlasīts: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> tika dzēsts."</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbā: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Vai izmantot bloķēšanu darbībai vienā lietotnē?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Konfigurācija \"Bloķēšana darbībai vienā lietotnē\" nobloķē ekrānu vienā lietotnē.\n\nLai izietu, nospiediet un turiet pogu “Pēdējās izmantotās lietotnes” $."</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NĒ"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Jūs izmantojat režīmu “Bloķēšana darbībai vienā lietotnē”."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Vai izmantot funkciju \"Fiksēt lietotni\"?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"SĀKT"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Sākt bloķēšanu darbībai vienā lietotnē"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Iziet no bloķēšanas darbībai vienā lietotnē"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index efe2235..5dc40e4 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"тест хийх байршлын эх үүсвэрийг үүсгэх"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Тестэд ашиглах хуурамч байршлын эх үүсвэрийг үүсгэх болон шинэ байршил өгөгчийг суулгах боломжтой. Ингэснээр апп нь GPS эсвэл байршил өгөгч зэрэг бусад байршлын эх үүсвэрээс ирсэн байршил болон статусыг өөрчлөх боломжтой."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"байршил нийлүүлэгчийн нэмэлт тушаалд хандах"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Апп нь байршил нийлүүлэгчийн нэмэлт тушаалд хандах боломжтой. Энэ нь апп-д GPS эсвэл бусад байршлын үйлчилгээний ажиллагаанд нөлөөлөх боломжийг олгоно."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Апп нь байршил нийлүүлэгчийн нэмэлт тушаалд хандах боломжтой. Энэ нь апп-д GPS эсвэл бусад байршлын үйлчилгээний ажиллагаанд нөлөөлөх боломжийг олгоно."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"байршил нийлүүлэгчийг суулгах зөвшөөрөх"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Тестэд ашиглах хуурамч байршлын эх үүсвэрийг үүсгэх болон шинэ байршил өгөгчийг суулгах боломжтой. Ингэснээр апп нь GPS эсвэл байршил өгөгч зэрэг бусад байршлын эх үүсвэрээс ирсэн байршил болон статусыг өөрчлөх боломжтой."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"Тодорхой байршил(GPS болон сүлжээнд суурилсан)"</string>
@@ -713,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Апп нь сүлжээний бодлогыг удирдах болон апп-д зориулсан дүрмийг тогтоох боломжтой."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"сүлжээний хэрэглээний тайланг өөрчлөх"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Апп нь апп-уудын сүлжээ ашиглалтын талаарх тооцоог өөрчлөх боломжтой. Энгийн апп-д ашиглагдахгүй."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"соккетын тэмдгүүдийг өөрчлөх"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Апп-д чиглэлийн соккетын тэмдгийг өөрчлөх боломж олгоно"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"мэдэгдэлд хандах"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Апп нь бусад апп-уудын илгээсэн мэдэгдлүүдийг дуудах, шалгах, болон цэвэрлэх боломжтой."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"мэдэгдэл сонсогч үйлчилгээтэй холбох"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Эзэмшигч нь мэдэгдэл сонсох үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"нөхцөл нийлүүлэгч үйлчилгээнд холбох"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Эзэмшигчид нөхцөл нийлүүлэгч үйлчилгээний дээд-түвшний интерфейстэй холбох боломж олгоно. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"медиа маршрут үйлчилгээтэй холбох"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Эзэмшигчид медиа маршрут үйлчилгээний дээр түвшний интерфэйст холбогдох боломж олгоно. Энгийн апп-д шаардагдахгүй."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"дрийм үйлчилгээнд холбох"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Эзэмшигч нь дрийм үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"үүрэн компанийн нийлүүлсэн тохируулгын апп-г өдөөх"</string>
@@ -731,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Мэдрэгчтэй дэлгэцний калибрешн параметрийг өөрчлөхийг апп-д зөвшөөрнө. Энгийн апп-д шаардлагагүй."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"хандалтын DRM сертификат"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Аппликешнд DRM сертификатыг ашиглах болон нийлүүлэхийг зөвшөөрнө. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Дамжуулалтын цацалтыг хүлээн авах."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Дамжуулалтын статусын мэдээллийг хүлээн авах боломж олгоно."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Андройд Бийм дамжуулалтын статусыг хүлээн авах"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Одоогийн Андройд Бийм дамжуулалтын мэдээллийг хүлээн авахыг аппликешнд зөвшөөрөх"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Нууц үгний дүрмийг тохируулах"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Дэлгэц түгжих нууц үгэнд зөвшөөрөгдсөн тэмдэгт болон уртыг удирдах"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Дэлгэц тайлах оролдлогыг хянах"</string>
@@ -1006,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Апп нь таны утсан дээр хадгалагдсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөх боломжтой. Энэ нь апп-д Хөтчийн датаг арилгах эсвэл өөрчлөх боломжийг олгоно. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадвартай аппликешнд ажиллахгүй байх боломжтой."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"сэрүүлэг тохируулах"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Апп нь суулгагдсан сэрүүлэгний апп дээр сэрүүлэг тохируулах боломжтой. Зарим сэрүүлэгний апп нь энэ функцийг дэмжихгүй байж болзошгүй."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"дуут шууданг устгах"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Апп нь таны дуут шуудангийн ирсэн мэйлээс зурвас хасах боломжтой."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"дуут шууданг удирдах"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Апп нь таны дуут шуудангийн ирсэн мэйлээс зурвас хасах боломжтой."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"дуут шуудан нэмэх"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Таны дуут шуудангийн ирсэн мэйлд зурвас нэмэхийг апп-д зөвшөөрөх."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"бүх дуут шууданг унших"</string>
@@ -1179,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"Идэвхтэй"</string>
<string name="capital_off" msgid="6815870386972805832">"Идэвхгүй"</string>
<string name="whichApplication" msgid="4533185947064773386">"Үйлдлийг дуусгах"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s ашиглан үйлдлийг гүйцээх"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Нээх"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ашиглан нээх"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Засварлах"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ашиглан засварлах"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Хуваалцах"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s ашиглан хуваалцах"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Нүүр апп-г сонгоно уу"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Энэ ажиллагааг үндсэн болгох."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Систем тохиргоо > Апп > Татаж авсан хэсгийн үндсэн утгуудыг цэвэрлэх"</string>
@@ -1281,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Байнга зөвшөөрөх"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Хэзээ ч зөвшөөрөхгүй"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM карт хасагдсан"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Зөв SIM карт хийгээд дахин асаатал та мобайл сүлжээг ашиглах боломжгүй."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"Та хүчинтэй SIM суулгаж, дахин асаах хүртэл үүрэн сүлжээг ашиглах боломжгүй."</string>
<string name="sim_done_button" msgid="827949989369963775">"Дуусгах"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM карт нэмэгдсэн"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Мобайл сүлжээнд хандах бол төхөөрөмжөө дахин асаан уу."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Үүрэн сүлжээнд хандах бол төхөөрөмжөө дахин асаан уу."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Дахин эхлүүлэх"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Цагийн тохируулах"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Огноо оруулах"</string>
@@ -1735,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> сонгогдсон"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> устсан"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Та Апп-дотор-түгжих горимд байна."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Апп-дотор-түгжих-г ашиглах уу?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Апп-дотор-түгжих нь дэлгэцийг нэг апп дотор түгжинэ.\n\nГарахын тулд саяхны апп-ууд товчийг дараад барина уу $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"ҮГҮЙ"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ЭХЛҮҮЛЭХ"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Апп-дотор-түгжих-г эхлүүлэх"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Апп-дотор-түгжих-с гарах"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index bb3f364..3027606 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"gunakan sumber lokasi olok-olok untuk pengujian"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Buat sumber lokasi palsu untuk menguji atau memasang pembekal lokasi baharu. Ini membenarkan apl untuk membatalkan lokasi dan/atau status yang dikembalikan oleh sumber lokasi lain seperti GPS atau pembekal lokasi."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"akses perintah tambahan pembekal lokasi"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Membenarkan apl untuk mengakses arahan pembekal lokasi tambahan. Ini boleh membenarkan apl untuk campur tangan dengan operasi GPS atau sumber lokasi lain."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Membenarkan apl mengakses arahan pembekal lokasi tambahan. Ini boleh membenarkan apl untuk campur tangan dengan operasi GPS atau sumber lokasi lain."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"kebenaran untuk memasang pembekal lokasi"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Buat sumber lokasi palsu untuk menguji atau memasang pembekal lokasi baharu. Ini membenarkan apl untuk membatalkan lokasi dan/atau status yang dikembalikan oleh sumber lokasi lain seperti GPS atau pembekal lokasi."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"lokasi tepat (GPS dan berasaskan rangkaian)"</string>
@@ -713,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Membenarkan apl mengurus dasar rangkaian dan menentukan peraturan khusus apl."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ubah suai perakaunan penggunaan rangkaian"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Membenarkan apl untuk mengubah suai bagaimana penggunaan rangkaian diambil kira terhadap apl. Bukan untuk digunakan oleh apl biasa."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"ubah tanda soket"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Membenarkan apl mengubah suai tanda soket untuk laluan"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"pemberitahuan akses"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Membenarkan apl untuk mendapatkan semula, memeriksa dan memadam bersih pemberitahuan, termasuk yang disiarkan oleh apl lain."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ikat kepada perkhidmatan pendengar pemberitahuan"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pendengar pemberitahuan. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"terikat kepada perkhidmatan pembekal keadaan"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pembekal keadaan. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"terikat kepada perkhidmatan impian"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan impian. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gunakan apl konfigurasi yang disediakan oleh pembawa"</string>
@@ -731,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Membenarkan apl mengubah suai parameter penentukuran skrin sentuh. Ini tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"akses sijil DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Membenarkan aplikasi memperuntuk dan menggunakan sijil DRM. Tidak sekali-kali diperlukan untuk apl biasa."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Terima siaran pemindahan penyerahan."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Membenarkan penerimaan maklumat status pemindahan penyerahan."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Terima status pemindahan Pancaran Android"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Membenarkan aplikasi ini menerima maklumat mengenai pemindahan Pancaran Android semasa"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
@@ -1006,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Membenarkan apl mengubah suai sejarah atau penanda halaman Penyemak Imbas yang tersimpan pada telefon anda. Ini boleh membenarkan apl untuk memadam atau mengubah suai data Penyemak Imbas. Nota: kebenaran ini tidak boleh dikuatkuasakan oleh penyemak imbas pihak ketiga atau aplikasi lain dengan keupayaan menyemak imbas web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"tetapkan penggera"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Membenarkan apl untuk menetapkan penggera dalam apl penggera jam yang dipasang. Sesetengah applikasi jam penggera tidak boleh melaksanakan ciri ini."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"alih keluar mel suara"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Membenarkan apl mengalih keluar mesej dari peti masuk mel suara anda."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"urus mel suara"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Membenarkan apl mengubah suai dan mengalih keluar mesej dari peti masuk mel suara anda."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"tambah mel suara"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Membenarkan apl untuk menambahkan mesej pada peti masuk mel suara anda."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"baca semua mel suara"</string>
@@ -1179,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"HIDUP"</string>
<string name="capital_off" msgid="6815870386972805832">"MATIKAN"</string>
<string name="whichApplication" msgid="4533185947064773386">"Selesaikan tindakan menggunakan"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Pilih apl laman utama"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Gunakannya secara lalai untuk tindakan ini."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Padam bersih lalai dalam tetapan Sistem > Apl > Dimuat turun."</string>
@@ -1281,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Sentiasa Benarkan"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Jangan Benarkan"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Kad SIM dikeluarkan"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Rangkaian mudah alih tidak akan tersedia sehingga anda mula semula dengan kad SIM yang sah dimasukkan."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Kad SIM ditambah"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Mulakan semula peranti anda untuk mengakses rangkaian mudah alih."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Mulakan semula"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Tetapkan masa"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Tetapkan tarikh"</string>
@@ -1373,10 +1391,8 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"Membenarkan aplikasi mendengar perubahan dalam keadaan amanah."</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Sediakan ejen amanah."</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Membenarkan aplikasi menyediakan ejen amanah."</string>
- <!-- no translation found for permlab_launch_trust_agent_settings (5859430082240410200) -->
- <skip />
- <!-- no translation found for permdesc_launch_trust_agent_settings (8185142708644913381) -->
- <skip />
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Lancarkan menu tetapan ejen amanah."</string>
+ <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"Membenarkan aplikasi melancarkan aktiviti yang mengubah tingkah laku ejen amanah."</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Mengikat kepada perkhidmatan ejen amanah"</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Membenarkan aplikasi terikat kepada perkhidmatan ejen amanah."</string>
<string name="permlab_recovery" msgid="3157024487744125846">"Berinteraksi dengan kemas kini dan sistem pemulihan"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dipadamkan"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Kerja <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Anda berada dalam mod Kunci ke Apl."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Gunakan kunci ke apl?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Kunci ke apl mengunci paparan dalam apl tunggal.\n\nUntuk keluar tekan dan tahan butang apl terbaru $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"TIDAK"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"MULA"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Mulakan Kunci ke apl"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Keluar kunci ke apl"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 9a7d66e..c71f0cfa 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Lar appen skrive til SMS-meldinger som er lagret på telefonen eller SIM-kortet ditt. Ondsinnede apper kan komme til å slette meldingene dine."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"motta tekstmeldinger (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Lar appen motta og behandle WAP-meldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til deg uten at du har sett dem."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"motta Bluetooth-meldinger (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Appen gis tillatelse til å motta og behandle Bluetooth MAP-meldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din, uten at du får se dem."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"hente apper som kjører"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Lar appen hente informasjon om oppgaver som kjører og som nylig har kjørt. Dette kan tillate appen å oppdage informasjon om hvilke apper som brukes på enheten."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"samhandling på tvers av brukere"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"lage simulerte posisjonskilder for testing"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Opprette fiktive posisjonskilder for testing eller installere en ny posisjonsangiver. Dette gjør at appen kan overstyre posisjonen eller statusen som rapporteres av ekte posisjonskilder, som for eksempel GPS eller posisjonsangivere."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"bruke ekstra posisjonskommandoer"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Lar appen få tilgang til flere kommandoer fra posisjonsangivere. Dette kan gjøre at appen forstyrrer GPS-funksjonen eller andre posisjonskilder."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Appen gis tillatelse til å bruke ekstra kommandoer fra posisjonsleverandører. Dette kan gi appen tillatelse til å påvirke bruken av GPS eller andre posisjonskilder."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"installere posisjonskilder"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Opprette fiktive posisjonskilder for testing eller installere en ny posisjonsangiver. Dette gjør at appen kan overstyre posisjonen eller statusen som rapporteres av ekte posisjonskilder, som for eksempel GPS eller posisjonsangivere."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"presis posisjon (GPS- og nettverksbasert)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Lar appen administrere retningslinjene for nettverket og definere appspesifikke regler."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Modifisering av regnskapsføring av nettverksbruk"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Lar appen endre hvordan nettverksbruk regnes ut for apper. Ikke beregnet på vanlige apper."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"endring av kontaktmerker"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Gir appen tillatelse til å endre kontaktmerker for ruting"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"tilgang til varsler"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Lar appen hente, gjennomgå og fjerne varsler, inkludert de som sendes fra andre apper."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"binding til en varsellyttertjeneste"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lar innehaveren binde seg til det øverste grensesnittnivået for en varsellyttertjeneste. Skal aldri være nødvendig for vanlige apper."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"binde seg til en leverandørtjeneste for betingelser"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Gir innehaveren tillatelse til å binde til toppnivået av brukergrensesnittet for en leverandørtjeneste for betingelser. Dette skal ikke være nødvendig for vanlige apper."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"binde til en drømmetjeneste"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Tillater eieren å binde seg til det øverste nivået av grensesnittet til en drømmetjeneste. Kreves aldri for vanlige apper."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"starte konfigurasjonsappen som ble levert av operatøren"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lar appen endre kalibrasjonsparametrene for berøringsskjermen. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"tilgang til DRM-sertifikater"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Tillater at en app klargjøre og bruke DRM-sertifikater. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"motta kunngjøringer om kringkastninger."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Gjør det mulig å motta statusinformasjon om overføring."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Motta overføringsstatus for Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Lar appen motta informasjon om aktuelle Android Beam-overføringer"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller tillatt lengde og tillatte tegn i passord for opplåsing av skjerm."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Lar appen endre nettleserens logg eller bokmerker lagret på telefonen din. Dette kan føre til at appen sletter eller endrer nettleserdata. Vær oppmerksom på at denne tillatelsen kanskje ikke benyttes av tredjepartsnettlesere eller andre apper med mulighet for nettsurfing."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"stille alarm"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Lar appen stille inn alarmen for en installert alarmklokke-app. Enkelte alarmklokke-apper implementerer kanskje ikke denne funksjonen."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"fjerne talepostmeldinger"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Appen kan fjerne meldinger fra talepostkassen."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"administrere talepostkassen"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Lar appen endre og fjerne meldinger fra talepostkassen."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"legge til talepost"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Lar appen legge til meldinger i talepostkassen din."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"lese alle meldingene i talepostkassen"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"På"</string>
<string name="capital_off" msgid="6815870386972805832">"Av"</string>
<string name="whichApplication" msgid="4533185947064773386">"Fullfør med"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Velg en startside-app"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Bruk som standardvalg."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Fjern app angitt som standard i systeminnstillingene > Apper > Nedlastet."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Alltid tillat"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Aldri tillat"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-kort er fjernet"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Det mobile nettverket forblir utilgjengelig inntil du starter på nytt med et gyldig SIM-kort."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Ferdig"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-kort er lagt til"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Start enheten på nytt for å få tilgang til det mobile nettverket."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Start på nytt"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Stille klokken"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Angi dato"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> er valgt"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Jobb-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Lås til app-modusen er aktivert."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Vil du bruke lås-til-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lås-til-app låser skjermen i en enkelt app.\n\nFor å avslutte trykker du på og holder nede nylige apper-knappen $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NEI"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Start lås-til-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Avslutt lås-til-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f61cd4c..ff66fc9 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Hiermee kan de app naar de op uw telefoon of simkaart opgeslagen sms\'jes schrijven. Schadelijke apps kunnen uw berichten mogelijk verwijderen."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"tekstberichten (WAP) ontvangen"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Hiermee kan de app WAP-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar uw apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth-berichten (MAP) ontvangen"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Hiermee kan de app Bluetooth MAP-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar uw apparaat zijn verzonden, kan controleren of verwijderen zonder ze aan u te laten zien."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"actieve apps ophalen"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Hiermee kan de app informatie ophalen over actieve en recent uitgevoerde taken. Zo kan de app informatie vinden over welke apps op het apparaat worden gebruikt."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interactie tussen gebruikers"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"neplocatiebronnen voor test"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Voorbeeld-locatiebronnen maken voor tests of een nieuwe locatieprovider instellen. Hiermee kan de app de locatie en/of status overschrijven van andere locatiebronnen zoals GPS of locatieproviders."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"toegang tot extra opdrachten van locatieaanbieder"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Hiermee krijgt de app toegang tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van GPS of andere locatiebronnen te verstoren."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Hiermee kan de app toegang krijgen tot extra opdrachten voor de locatieprovider. De app kan hiermee de werking van GPS of andere locatiebronnen te verstoren."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"toestemming om een locatieprovider te installeren"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Voorbeeld-locatiebronnen maken voor tests of een nieuwe locatieprovider instellen. Hiermee kan de app de locatie en/of status overschrijven van andere locatiebronnen zoals GPS of locatieproviders."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"precieze locatie (GPS- en netwerkgebaseerd)"</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Hiermee kan de app het netwerkbeleid beheren en app-specifieke regels definiëren."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"verrekening van netwerkgebruik aanpassen"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Hiermee kan een app aanpassen hoe het netwerkgebruik wordt toegekend aan apps. Dit wordt niet gebruikt door normale apps."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"socketmarkeringen aanpassen"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Hiermee kan de app socketmarkeringen voor routeren aanpassen"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"toegang tot meldingen"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Hiermee kan de app meldingen ophalen, onderzoeken en wissen, waaronder meldingen die zijn verzonden door andere apps."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"koppelen aan een listener-service voor meldingen"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Hiermee kan de houder koppelen aan de hoofdinterface van een listener-service voor meldingen. Nooit vereist voor normale apps."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"binden aan de service van een provider van voorwaarden"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Hiermee kan de houder binden aan de hoofdinterface van de service van een provider van voorwaarden. Nooit vereist voor normale apps."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"binden aan een service voor mediaroutering"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Hiermee kan de houder binden aan de hoofdinterface van een service voor mediaroutering. Nooit vereist voor normale apps."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"verbinding maken met een droomservice"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een droomservice. Nooit vereist voor normale apps."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"de door de provider geleverde configuratie-app aanroepen"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Hiermee kan de app de kalibratieparameters van het aanraakscherm aanpassen. Nooit vereist voor normale apps."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"toegang tot DRM-certificaten"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Toestaan dat een app DRM-certificaten registreert en gebruikt. Nooit vereist voor normale apps."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Overdrachtsuitzendingen over de handover ontvangen."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Hiermee kan informatie over de overdrachtsstatus van de handover worden ontvangen."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Android Beam-overdrachtsstatus ontvangen"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Hiermee kan deze app informatie over huidige Android Beam-overdrachten ontvangen"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -1008,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bladwijzers die zijn opgeslagen op uw telefoon. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"een alarm instellen"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Hiermee kan de app een alarm instellen in een geïnstalleerde wekkerapp. Deze functie wordt door sommige wekkerapps niet geïmplementeerd."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"voicemails verwijderen"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Hiermee kan de app berichten verwijderen uit de inbox van uw voicemail."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"voicemails beheren"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Hiermee kan de app berichten in de inbox van uw voicemail aanpassen en verwijderen."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"voicemail toevoegen"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Hiermee kan de app berichten toevoegen aan de inbox van uw voicemail."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"alle voicemails lezen"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"AAN"</string>
<string name="capital_off" msgid="6815870386972805832">"UIT"</string>
<string name="whichApplication" msgid="4533185947064773386">"Actie voltooien met"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"Actie voltooien via %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Openen met"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Openen met %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Bewerken met"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Bewerken met %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Delen met"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Delen met %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Een startscherm-app selecteren"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Standaard gebruiken voor deze actie."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Standaardinstelling wissen via Systeeminstellingen > Apps > Gedownload."</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Altijd toestaan"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nooit toestaan"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Simkaart verwijderd"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Het mobiele netwerk is niet beschikbaar totdat u het apparaat opnieuw start met een geldige simkaart."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"Het mobiele netwerk is pas beschikbaar zodra u het apparaat opnieuw start met een geldige simkaart."</string>
<string name="sim_done_button" msgid="827949989369963775">"Gereed"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Simkaart aangesloten"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Start uw apparaat opnieuw voor toegang tot het mobiele netwerk."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Start uw apparaat opnieuw voor toegang tot het mobiele netwerk."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Opnieuw starten"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Tijd instellen"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum instellen"</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> geselecteerd"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> verwijderd"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Lock-to-app gebruiken?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Met Lock-to-app wordt het scherm vergrendeld in één app.\n\nAls u dit wilt afsluiten, houdt u de knop \'Recente apps\' $ ingedrukt"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NEE"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"U bevindt zich in de App-slotmodus."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"App-slot gebruiken?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Lock-to-app starten"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Lock-to-app afsluiten"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index d054a1b..749abe2 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Pozwala aplikacji na zapisywanie wiadomości SMS przechowywanych w telefonie lub na karcie SIM. Szkodliwe aplikacje mogą usunąć wiadomości."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"odbieranie wiadomości tekstowych (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Pozwala aplikacji na odbieranie i przetwarzanie wiadomości WAP. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"odbieranie komunikatów Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Pozwala aplikacji na odbieranie i przetwarzanie komunikatów Bluetooth MAP. Oznacza to, że może ona bez Twojej wiedzy monitorować i usuwać komunikaty przesyłane do Twojego urządzenia."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"pobieranie uruchomionych aplikacji"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Pozwala aplikacji na pobieranie informacji o aktualnie i niedawno działających zadaniach. Dzięki temu aplikacja może uzyskać informacje o tym, które aplikacje są używane na urządzeniu."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakcje między użytkownikami"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"udawanie źródeł położenia dla testów"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Tworzenie pozorowanych źródeł lokalizacji dla potrzeb testów lub instalacji nowego dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą zastąpić lokalizację i/lub stan zwracany przez inne źródła lokalizacji, takie jak GPS lub dostawcy danych o lokalizacji."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Pozwala aplikacji na dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą wpływać na działanie urządzenia GPS lub innych źródeł lokalizacji."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Pozwala aplikacji na dostęp do dodatkowych poleceń dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą wpływać na działanie GPS-u lub innych źródeł lokalizacji."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"uprawnienia do instalowania dostawcy danych o lokalizacji"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Tworzenie pozorowanych źródeł lokalizacji dla potrzeb testów lub instalacji nowego dostawcy informacji o lokalizacji. Aplikacje z tym uprawnieniem mogą zastąpić lokalizację i/lub stan zwracany przez inne źródła lokalizacji, takie jak GPS lub dostawcy danych o lokalizacji."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"dokładna lokalizacja (na podstawie sygnału GPS i sieci)"</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Pozwala aplikacji na zarządzanie zasadami dotyczącymi sieci i definiowanie reguł aplikacji."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modyfikowanie sposobu naliczania użycia sieci"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Pozwala aplikacji na zmienianie sposobu rozliczania wykorzystania sieci przez aplikacje. Nieprzeznaczone dla zwykłych aplikacji."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"zmiana oznaczeń gniazd"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Zezwala aplikacji na zmianę oznaczeń gniazd na potrzeby trasowania"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"dostęp do powiadomień"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Umożliwia aplikacji pobieranie, sprawdzanie i usuwanie powiadomień, także tych, które pochodzą z innych aplikacji."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"utwórz połączenie z usługą odbiornika powiadomień"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi odbiornika powiadomień. Nie powinno być nigdy potrzebne dla zwykłych aplikacji."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"powiąż z usługą dostawcy warunków"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi dostawcy warunków. Nieprzeznaczone dla zwykłych aplikacji."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"powiązanie z usługą kierowania multimediów"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi kierowania multimediów. Nieprzeznaczone dla zwykłych aplikacji."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"powiąż z usługą wygaszacza ekranu"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi wygaszacza ekranu. Nie powinno być nigdy potrzebne dla zwykłych aplikacji."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"wywoływanie aplikacji konfiguracyjnej udostępnionej przez operatora"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Zezwala aplikacji na modyfikowanie parametrów kalibracji ekranu dotykowego. Nieprzeznaczone dla zwykłych aplikacji."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"dostęp do certyfikatów DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Zezwala aplikacji na dodanie i używanie certyfikatów DRM. Nieprzeznaczone dla zwykłych aplikacji."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Otrzymywanie informacji o transferze."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Pozwala na odbieranie informacji o stanie transferu."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Uzyskiwanie informacji o stanie transmisji Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Zezwala tej aplikacji na otrzymywanie informacji o aktualnych transmisjach Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
@@ -1008,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Pozwala aplikacji na modyfikowanie historii i zakładek przeglądarki zapisanych na telefonie. Aplikacja będzie mogła usunąć lub zmodyfikować dane przeglądarki. Uwaga: to uprawnienie może nie być egzekwowane przez przeglądarki innych firm oraz inne aplikacje z możliwością przeglądania internetu."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"ustawianie alarmu"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Pozwala aplikacji na ustawienie alarmu w zainstalowanej aplikacji budzika. Funkcja ta może nie być zaimplementowana w niektórych aplikacjach tego typu."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"usuwaj wiadomości głosowe"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Pozwala aplikacji na usuwanie wiadomości z Twojej skrzynki głosowej."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"zarządzanie wiadomościami poczty głosowej"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Zezwala aplikacji na modyfikowanie i usuwanie Twoich odebranych wiadomości poczty głosowej."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"dodawanie poczty głosowej"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Pozwala aplikacji na dodawanie wiadomości do skrzynki odbiorczej poczty głosowej."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"odczyt całej poczty głosowej"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"Wł"</string>
<string name="capital_off" msgid="6815870386972805832">"Wył"</string>
<string name="whichApplication" msgid="4533185947064773386">"Wykonaj czynność przez..."</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"Wykonaj czynność w aplikacji %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Otwórz w aplikacji"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Otwórz w aplikacji %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Edytuj w aplikacji"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edytuj w aplikacji %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Udostępnij w aplikacji"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Udostępnij w aplikacji %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Wybierz aplikację ekranu głównego"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Domyślne dla tej czynności"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Wyczyść wartości domyślne w: Ustawienia systemu > Aplikacje > Pobrane."</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Zawsze zezwalaj"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nigdy nie zezwalaj"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM wyjęta"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Sieć komórkowa będzie niedostępna do chwili ponownego uruchomienia urządzenia z użyciem ważnej karty SIM."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"Sieć komórkowa będzie niedostępna do chwili, gdy ponownie uruchomisz urządzenie po włożeniu ważnej karty SIM."</string>
<string name="sim_done_button" msgid="827949989369963775">"Gotowe"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Dodano kartę SIM"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Uruchom ponownie urządzenie, aby uzyskać dostęp do sieci komórkowej."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Uruchom urządzenie ponownie, by uzyskać dostęp do sieci komórkowej."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Uruchom ponownie"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Ustaw godzinę"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Ustaw datę"</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Wybrałeś <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> usunięte"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (praca)"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Chcesz użyć funkcji lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Po włączeniu funkcji lock-to-app na ekranie będzie wyświetlona pojedyncza aplikacja.\n\nAby wyłączyć tę funkcję, naciśnij i przytrzymaj przycisk ostatnio używanych aplikacji $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NIE"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Jesteś w trybie Zablokuj na aplikacji."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Chcesz użyć funkcji Zablokuj na aplikacji?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Włącz funkcję lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Wyłącz funkcję lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 03bc385..907ee26 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Permite que a aplicação escreva mensagens SMS armazenadas no telemóvel ou no cartão SIM. As aplicações maliciosas podem eliminar as suas mensagens."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"receber mensagens de texto (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Permite que a aplicação receba e processe mensagens WAP. Esta autorização inclui a capacidade de monitorizar ou eliminar mensagens enviadas para si sem as apresentar."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"receber mensagens Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Permite à aplicação receber e processar mensagens MAP Bluetooth, o que significa que a aplicação poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem lhas mostrar."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"obter aplicações em execução"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Permite que a aplicação recupere informações acerca de tarefas executadas atual e recentemente. Isto pode permitir que a aplicação descubra informações acerca de quais as aplicações utilizadas no dispositivo."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interagir entre utilizadores"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"fontes de localização fictícias para teste"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Criar fontes de localização fictícias para fins de teste ou instalar um novo fornecedor de localização. Isto permite que a aplicação substitua a localização e/ou o estado devolvido por outras fontes de localização como, por exemplo, GPS ou fornecedores de localização."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"aceder a comandos adicionais do fornecedor de localização"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite que a aplicação aceda a comandos adicionais do fornecedor de localização. Isto pode permitir que a aplicação interfira com o funcionamento do GPS ou de outras fontes de localização."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que a aplicação aceda a comandos adicionais do fornecedor de localização. Esta opção pode permitir que a aplicação interfira com o funcionamento do GPS ou de outras fontes de localização."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorização para instalar um fornecedor de localização"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Criar fontes de localização fictícias para fins de teste ou instalar um fornecedor de localização novo. Isto permite que a aplicação substitua a localização e/ou o estado devolvido por outras fontes de localização como, por exemplo, GPS ou fornecedores de localização."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"localização exata (baseada no GPS e na rede)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite que a aplicação faça a gestão de políticas de rede e defina regras específicas de aplicações."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar contabilização da utilização da rede"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que a aplicação modifique o modo como a utilização da rede é contabilizada em relação a aplicações. Nunca é necessário para aplicações normais."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modificar marcas de socket"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permite que a aplicação modifique as marcas de socket para encaminhamento"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"aceder às notificações"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que a aplicação obtenha, examine e limpe notificações, incluindo as que foram publicadas por outras aplicações."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincular a um serviço de escuta de notificações"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o titular vincule a interface de nível superior de um serviço de escuta de notificações. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vincular a um serviço de fornecedor de condição"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite que o titular vincule a interface de nível superior de um serviço de fornecedor de condição. Nunca deverá ser necessário para aplicações normais."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"vincular-se a um serviço de sonho"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Permite ao detentor ficar vinculado à interface de nível superior de um serviço de sonho. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar a aplicação de configuração fornecida pela operadora"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite à aplicação modificar os parâmetros de calibragem do ecrã tátil. Esta funcionalidade nunca deverá ser necessária para aplicações normais."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Aceder a certificados DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite que uma aplicação forneça e utilize certificados DRM. Nunca deverá ser necessário para aplicações normais."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Receber transmissões de transferência da entrega."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Permite a receção de informações do estado de transferência da entrega."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Receber estado de transferência do Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Permite que esta aplicação receba informações acerca das transferências atuais do Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que a aplicação modifique o histórico do Navegador ou marcadores guardados no telemóvel. Isto pode permitir que a aplicação apague ou modifique dados do Navegador. Nota: esta autorização pode não ser aplicada por navegadores de terceiros ou outras aplicações com capacidades de navegação na Web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"definir um alarme"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que a aplicação defina um alarme numa aplicação de despertador instalada. Algumas aplicações de despertador podem não integrar esta funcionalidade."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"remover mensagens de correio de voz"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Permite que a aplicação remova mensagens da sua caixa de entrada de correio de voz."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"gerir mensagens de correio de voz"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Permite que a aplicação modifique e remova mensagens da sua caixa de entrada de correio de voz."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"adicionar correio de voz"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que a aplicação adicione mensagens à sua caixa de entrada de correio de voz."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ler todo o correio de voz"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"Ativado"</string>
<string name="capital_off" msgid="6815870386972805832">"Desativado"</string>
<string name="whichApplication" msgid="4533185947064773386">"Concluir ação utilizando"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Selecionar uma aplicação de página inicial"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utilizar por predefinição para esta acção."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Limpar a predefinição nas Definições do Sistema > Aplicações > Transferidas."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permitir Sempre"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nunca Permitir"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"A rede de telemóvel estará indisponível até que reinicie o aparelho com um cartão SIM válido inserido."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Cartão SIM adicionado"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Reinicie o aparelho para aceder à rede de telemóvel."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selecionado"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Está no modo Lock-to-App."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Utilizar o Lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"A funcionalidade Lock-to-app bloqueia o ecrã numa única aplicação.\n\nPara sair, prima sem soltar o botão $ das aplicações recentes"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NÃO"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"INICIAR"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Iniciar o Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Sair do Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 87c2f4f..3f0ba6e 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"fontes de locais fictícios para teste"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Criar fontes de localização simuladas para testar ou instalar um novo provedor de localização. Isso permite que o aplicativo substitua a localização e/ou o status retornado por outras fontes de localização, como o GPS ou provedores de localização."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"acessar comandos extras do provedor de localização"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite que o aplicativo acesse comandos do provedor não relacionados à localização. Isso pode permitir que o aplicativo interfira no funcionamento do GPS ou de outras fontes de localização."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite que o aplicativo acesse comandos do provedor não relacionados à localização. Isso pode permitir que o aplicativo interfira no funcionamento do GPS ou de outras fontes de localização."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"autorização para instalar um provedor de localização"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Criar fontes de localização simuladas para testar ou instalar um novo provedor de localização. Isso permite que o aplicativo substitua a localização e/ou o status retornado por outras fontes de localização, como o GPS ou provedores de localização."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"localização precisa (GPS e com base na rede)"</string>
@@ -713,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite que o aplicativo gerencie políticas de rede e definia regras específicas para o aplicativo."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificar contagem de uso da rede"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite que o aplicativo modifique como o uso da rede é contabilizado em relação aos aplicativos. Não deve ser usado em aplicativos normais."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modificar marcas de soquetes"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permite que o aplicativo modifique marcas de soquetes para roteamento"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"acessar notificações"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que o aplicativo recupere, examine e limpe notificações, inclusive as postadas por outros aplicativos."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"sujeitar a um serviço ouvinte de notificações"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o proprietário sujeite a interface de nível superior a um serviço ouvinte de notificações. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"associar a um serviço provedor de condições"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite que o proprietário use a interface de nível superior de um serviço provedor de condições. Não deve ser necessário para aplicativos comuns."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"conectar-se a um serviço de sonho"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Permite que o sistema autorizado se conecte à interface de nível superior de um serviço de sonho. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar o aplicativo de configuração fornecido pela operadora"</string>
@@ -731,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite que o aplicativo modifique os parâmetros de calibragem da tela sensível ao toque. Não deve ser necessário para aplicativos normais."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"acessar certificados de DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite que o aplicativo provisione e use certificados de DRM. Não deve ser necessário para aplicativos comuns."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Receba transmissões de transferência/entrega."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Permite receber informações do status de transferência/entrega."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Receber status de transferência do Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Permite que este aplicativo receba informações sobre as atuais transferências do Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
@@ -906,7 +908,7 @@
<string name="lockscreen_transport_pause_description" msgid="7659088786780128001">"Botão \"Pausar\""</string>
<string name="lockscreen_transport_play_description" msgid="5888422938351019426">"Botão \"Reproduzir\""</string>
<string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"Botão \"Parar\""</string>
- <string name="emergency_calls_only" msgid="6733978304386365407">"Apenas chamadas de emergência"</string>
+ <string name="emergency_calls_only" msgid="6733978304386365407">"Só chamadas de emergência"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Rede bloqueada"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"O cartão SIM está bloqueado pelo PUK."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Consulte o Guia do usuário ou entre em contato com o Serviço de atendimento ao cliente."</string>
@@ -1006,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que o aplicativo modifique o histórico ou os favoritos do navegador armazenados no telefone. Pode permitir que o aplicativo apague ou modifique os dados do navegador. Observação: pode não ser aplicável a navegadores de terceiros e outros aplicativos com capacidade de navegação na web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"definir um alarme"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que o aplicativo defina um alarme em um aplicativo despertador instalado. Alguns aplicativos despertador podem não implementar este recurso."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"remover correios de voz"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Permite que o aplicativo remova mensagens da caixa de entrada do correio de voz."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"gerenciar correios de voz"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Permite que o aplicativo modifique e remova mensagens da caixa de entrada do correio de voz."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"adicionar correio de voz"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que o aplicativo adicione mensagens a sua caixa de entrada do correio de voz."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ler todo o correio de voz"</string>
@@ -1179,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"LIG"</string>
<string name="capital_off" msgid="6815870386972805832">"DESL"</string>
<string name="whichApplication" msgid="4533185947064773386">"Complete a ação usando"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Selecione um aplicativo de tela inicial"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Usar como padrão para esta ação."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Padrão claro em Configurações do sistema > Aplicativos > Baixado."</string>
@@ -1281,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Sempre permitir"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nunca permitir"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Cartão SIM removido"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"A rede móvel ficará indisponível até que você reinicie com um cartão SIM válido inserido."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Concluído"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Cartão SIM adicionado"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Reinicie o dispositivo para acessar a rede móvel."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Reiniciar"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
@@ -1373,10 +1391,8 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite que o aplicativo detecte alterações no estado de confiança."</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Fornecer um agente de confiança."</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Permite que um aplicativo forneça um agente de confiança."</string>
- <!-- no translation found for permlab_launch_trust_agent_settings (5859430082240410200) -->
- <skip />
- <!-- no translation found for permdesc_launch_trust_agent_settings (8185142708644913381) -->
- <skip />
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Abra o menu de configurações do agente de confiança."</string>
+ <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"Permite que um aplicativo inicie uma atividade que altera o comportamento do agente de confiança."</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Associar a um serviço de agente de confiança"</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite que o aplicativo se associe a um serviço de agente de confiança."</string>
<string name="permlab_recovery" msgid="3157024487744125846">"Interagir com o sistema de atualizações e recuperação"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selecionado"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> excluído"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Usar fixar em aplicativo?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"\"Fixar em aplicativo\" congela a exibição em um único aplicativo.\n\nPara sair, pressione e segure o botão de aplicativos recentes $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NÃO"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Você está no modo Fixar no app."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Usar Fixar no app?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"INICIAR"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Iniciar Fixar em aplicativo"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Sair de Fixar em aplicativo"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index e761df9..e0435bf 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -504,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"surse de locaţii pentru testare"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Creează surse de locaţii pentru testare sau instalează un furnizor de locaţie nou. Acest lucru permite aplicaţiei să înlocuiască locaţia şi/sau starea returnate de alte surse de locaţii, cum ar fi GPS sau furnizorii de locaţii."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accesare comenzi suplimentare ale furnizorului locaţiei"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Permite aplicaţiei să acceseze comenzi suplimentare pentru furnizorul locaţiei. Aplicaţia ar putea să utilizeze această permisiune pentru a influenţa operaţiile GPS sau ale altor surse de locaţii."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Permite aplicației să acceseze comenzi suplimentare pentru furnizorul locației. Aplicația ar putea să utilizeze această permisiune pentru a influența operațiile GPS sau ale altor surse de locații."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"permisiune pentru instalarea unui furnizor de locaţii"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Creează surse de locaţii pentru testare sau instalează un furnizor de locaţie nou. Acest lucru permite aplicaţiei să înlocuiască locaţia şi/sau starea returnate de alte surse de locaţii, cum ar fi GPS sau furnizorii de locaţii."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"locaţia exactă (bazată pe reţea şi GPS)"</string>
@@ -713,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Permite aplicaţiei să gestioneze politicile de reţea şi să definească regulile specifice aplicaţiilor."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"modificaţi modul de calcul al utilizării reţelei"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Permite aplicaţiei să modifice modul în care este calculată utilizarea reţelei pentru aplicaţii. Nu se utilizează de aplicaţiile obişnuite."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"modificarea mărcilor socketurilor"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Permite aplicației să modifice mărcile socketurilor pentru rutare."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"accesare notificări"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"conectare la un serviciu de citire a notificărilor"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de citire a notificărilor. În mod normal aplicațiile nu ar trebui să aibă nevoie de această permisiune."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"conectare la un serviciu furnizor de condiții"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu furnizor de condiții. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"se conectează la un serviciu de vis"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Permite deținătorului să se conecteze la interfața superioară a unui serviciu de vis. Această opțiune nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"apelarea aplicației de configurare furnizată de operator"</string>
@@ -731,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite aplicației să modifice parametrii de calibrare a ecranului tactil. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accesează certificatele DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite unei aplicații să furnizeze și să utilizeze certificate DRM. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Primiți difuzări despre transfer."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Permite primirea informațiilor despre starea transferului."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Primiți starea transferului prin Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Permite acestei aplicații să primească informații despre transferurile actuale Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
@@ -1006,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite aplicaţiei să modifice istoricul Browserului sau marcajele stocate pe telefon. În acest fel, aplicaţia poate şterge sau modifica datele din Browser. Notă: această permisiune nu poate fi aplicată de browsere terţă parte sau de alte aplicaţii cu capacităţi de navigare pe web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"setează o alarmă"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Permite aplicaţiei să seteze o alarmă într-o aplicaţie de ceas cu alarmă instalată. Este posibil ca unele aplicaţii de ceas cu alarmă să nu implementeze această funcţie."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"eliminați mesaje vocale"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Permite aplicației să elimine mesaje din secțiunea de mesaje vocale primite."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"gestionarea mesajelor vocale"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Permite aplicației să modifice și să elimine mesaje din secțiunea de mesaje vocale primite."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"adăugare mesagerie vocală"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite aplicaţiei să adauge mesaje în Mesaje primite în mesageria vocală."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"acces la toate mesajele vocale"</string>
@@ -1179,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"DA"</string>
<string name="capital_off" msgid="6815870386972805832">"NU"</string>
<string name="whichApplication" msgid="4533185947064773386">"Finalizare acţiune utilizând"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Selectați o aplicație de pe ecranul de pornire"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Se utilizează în mod prestabilit pentru această acţiune."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Ștergeţi setările prestabilite din Setări de sistem > Aplicaţii > Descărcate."</string>
@@ -1281,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Permiteţi întotdeauna"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nu permiteţi niciodată"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Card SIM eliminat"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Reţeaua mobilă va fi indisponibilă până când reporniţi cu o cartelă SIM validă introdusă."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Terminat"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Card SIM adăugat"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Reporniţi dispozitivul pentru a accesa reţeaua mobilă."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Reporniţi"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Setaţi ora"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Setaţi data"</string>
@@ -1373,10 +1391,8 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"Permite unei aplicații să detecteze modificările în starea de încredere."</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Indicați un agent de încredere."</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Permite unei aplicații să indice un agent de încredere."</string>
- <!-- no translation found for permlab_launch_trust_agent_settings (5859430082240410200) -->
- <skip />
- <!-- no translation found for permdesc_launch_trust_agent_settings (8185142708644913381) -->
- <skip />
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Lansați meniul de setări pentru agentul de încredere."</string>
+ <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"Permite unei aplicații să lanseze o activitate care schimbă comportamentul agentului de încredere."</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Asocierea la un serviciu „agenți de încredere”."</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Permite unei aplicații să se asocieze la un serviciu „agent de încredere”."</string>
<string name="permlab_recovery" msgid="3157024487744125846">"Interacțiune cu sistemul de recuperare și de actualizare"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selectat"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> a fost șters"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de serviciu"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Utilizați Blocarea aplicației?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Blocarea aplicației blochează ecranul într-o singură aplicație.\n\nPentru a ieși, apăsați lung pe butonul pentru aplicații recente $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NU"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Sunteți în modul Blocare la aplicație."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Utilizați Blocarea la aplicație?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"PORNIȚI"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Porniți Blocarea aplicației"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Ieșiți din Blocarea aplicației"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d74a21e..db3e0d5 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Приложение сможет изменять SMS, сохраненные на телефоне или SIM-карте. Вредоносные программы смогут удалять ваши сообщения."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"Прием WAP-сообщений"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Приложение сможет получать и обрабатывать WAP-сообщения. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"получать сообщения Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Получение и обработка сообщений Bluetooth MAP. Отслеживание и удаление непрочитанных сообщений."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"Получение данных о запущенных приложениях"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Приложение сможет получать информацию о недавно запущенных и выполняемых задачах, а следовательно, и о приложениях, используемых на устройстве."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Взаимодействие с аккаунтами всех пользователей"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"Установка фиктивного местоположения для отладки"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Приложение сможет создавать фиктивные местоположения для тестирования или установки нового источника геоданных и переопределять местоположение и/или статус, возвращаемые другими источниками, такими как система GPS."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"Доступ к дополнительным командам управления источниками геоданных"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Приложение получит доступ к дополнительным командам управления источниками геоданных и сможет вмешиваться в работу системы GPS или других источников геоданных."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Доступ к дополнительным командам управления источниками геоданных и вмешательство в работу системы GPS или других источников геоданных."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"Добавление источника геоданных"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Приложение сможет создавать фиктивные местоположения для тестирования или установки нового источника геоданных и переопределять местоположение и/или статус, возвращаемые другими источниками, такими как система GPS или службы геопозиционирования."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"Точное местоположение (на основе сети и сигналов GPS)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Приложение сможет управлять сетевыми политиками и определять правила для отдельных приложений."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"Изменение учета использования сети"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Приложение сможет изменять порядок расчета использования сетевых ресурсов различными программами. Это разрешение не используется обычными приложениями."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"Изменение отметок сокетов"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Приложение сможет изменять отметки сокетов для маршрутизации."</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"Доступ к уведомлениям"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Приложение сможет получать, проверять и удалять уведомления, включая те, что опубликованы другими приложениями."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"Подключение к службе просмотра уведомлений"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Приложение сможет подключаться к базовому интерфейсу службы просмотра уведомлений. Это разрешение не используется обычными приложениями."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"Подключение к серверам поставщиков условий"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Приложение сможет подключаться к базовому интерфейсу поставщиков условий. Это разрешение обычно используется только специальными приложениями."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"Подключение к службе экранных заставок"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Подключение к базовому интерфейсу службы экранных заставок. Это разрешение не используется обычными приложениями."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Запуск приложения настроек, предоставленного оператором"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Приложение сможет изменять параметры калибровки сенсорного экрана. Это разрешение обычно используется только специальными приложениями."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"Доступ к сертификатам DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Приложение сможет синхронизировать и использовать сертификаты DRM (разрешение актуально только для специальных приложений)."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Получение уведомлений о передаче данных."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Получение сведений о состоянии передачи данных."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Получение статуса передачи Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Получение информации о текущих передачах Android Beam."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролировать длину и символы при вводе паролей для снятия блокировки экрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Приложение сможет изменять историю или закладки браузера, сохраненные на телефоне, а также удалять и изменять данные браузера. Обратите внимание: браузеры независимых поставщиков или другие приложения для просмотра веб-страниц могут не применять это разрешение."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"Установка будильника"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Приложение сможет настраивать будильник. Функция поддерживается не во всех программах."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"Удаление голосовых сообщений"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Удаление сообщений голосовой почты."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"Управление голосовой почтой"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Изменение и удаление сообщений из голосовой почты."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"Добавление голосовых сообщений"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Приложение сможет добавлять голосовые сообщения в папку \"Входящие\"."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"Доступ к голосовой почте"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"I"</string>
<string name="capital_off" msgid="6815870386972805832">"O"</string>
<string name="whichApplication" msgid="4533185947064773386">"Что использовать?"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Выберите приложение"</string>
<string name="alwaysUse" msgid="4583018368000610438">"По умолчанию для этого действия"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Удаляет настройки по умолчанию в меню \"Настройки > Приложения > Загруженные\"."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Всегда разрешать"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Не разрешать"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-карта удалена"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Пока вы не вставите действующую SIM-карту, мобильная сеть будет недоступна."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-карта добавлена"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Перезагрузите устройство для доступа к мобильной сети."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Перезапуск"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Настройка времени"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Настройка даты"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Выбран элемент <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Цифра <xliff:g id="KEY">%1$s</xliff:g> удалена"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Рабочий <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Включена блокировка в приложении"</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Использовать блокировку в приложении?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Функция блокирует переход в другие приложения.\n\nЧтобы выключить блокировку, нажмите и удерживайте кнопку \"Недавние приложения\" $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"НЕТ"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ДА"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Запуск блокировки в приложении"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Выключить блокировку"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 7343e17..eb1a4c9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Umožňuje aplikácii písať do správ SMS uložených v telefóne alebo na karte SIM. Škodlivé aplikácie môžu vaše správy odstrániť."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"prijímať textové správy (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Umožňuje aplikácii prijímať a spracovávať správy WAP. Toto povolenie zahŕňa možnosť sledovať vaše správy alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"prijímanie správ Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Umožňuje aplikácii prijímať a spracovávať správy MAP rozhrania Bluetooth. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"načítať spustené aplikácie"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Umožňuje aplikácii načítať informácie o aktuálne či nedávno spustených úlohách. Toto povolenie môže aplikácii umožniť objaviť informácie o tom, ktoré aplikácie sa na zariadení používajú."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakcie naprieč používateľmi"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"simulácia zdrojov polohy na účely testovania"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Vytváranie simulovaných zdrojov polohy na testovanie alebo inštalácia nového poskytovateľa informácií o polohe. Aplikácii to umožní nahradiť polohu a stav, ktoré vracajú iné zdroje informácií o polohe, ako sú napríklad systém GPS alebo poskytovatelia informácií o polohe."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"prístup k ďalším príkazom poskytovateľa polohy"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Umožňuje aplikácii pristupovať k ďalším príkazom poskytovateľa informácií o polohe. Aplikácii to môže umožniť zasahovať do činnosti systému GPS alebo iných zdrojov informácií o polohe."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Umožňuje aplikácii pristupovať k ďalším príkazom poskytovateľa informácií o polohe. Aplikácii to môže umožniť zasahovať do činnosti systému GPS alebo iných zdrojov informácií o polohe."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"Oprávnenie na inštaláciu poskytovateľa polohy"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Vytváranie simulovaných zdrojov polohy na testovanie alebo inštalácia nového poskytovateľa informácií o polohe. Aplikácii to umožní nahradiť polohu a stav, ktoré vracajú iné zdroje informácií o polohe, ako sú napríklad systém GPS alebo poskytovatelia informácií o polohe."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"zistiť presnú polohu (pomocou GPS a siete)"</string>
@@ -679,7 +677,7 @@
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"zapnúť alebo vypnúť synchronizáciu"</string>
<string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Umožňuje aplikácii upraviť nastavenia synchronizácie v účte. Pomocou tohto povolenia je možné napríklad povoliť synchronizáciu aplikácie Ľudia s účtom."</string>
- <string name="permlab_readSyncStats" msgid="7396577451360202448">"čítanie štatistických údajov o synchronizácii"</string>
+ <string name="permlab_readSyncStats" msgid="7396577451360202448">"čítať štatistické údaje o synchronizácii"</string>
<string name="permdesc_readSyncStats" msgid="1510143761757606156">"Umožňuje aplikácii čítať štatistické informácie o synchronizácii v účte vrátane histórie uskutočnených synchronizácií a informácií o množstve synchronizovaných údajov."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čítať odoberané informačné kanály"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Umožňuje aplikácii získať podrobnosti o aktuálne synchronizovaných informačných kanáloch."</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Umožňuje aplikácii spravovať pravidlá siete a definovať pravidlá pre konkrétnu aplikáciu."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"zmeniť kontrolu používania siete"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Umožňuje aplikácii upraviť používanie siete jednotlivými aplikáciami. Bežné aplikácie toto nastavenie nepoužívajú."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"upravenie značiek soketov"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Umožňuje aplikácii upraviť značky soketov pre smerovanie"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"prístup k upozorneniam"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikácii načítať, zobrazovať a mazať upozornenia vrátane tých, ktoré boli uverejnené inými aplikáciami."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"naviazanie sa na službu na počúvanie upozornení"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteľovi naviazať sa na najvyššiu úroveň služby na počúvanie upozornení. Bežné aplikácie by toto nastavenie nemali nikdy požadovať."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"viazanie na službu poskytovateľa podmienky"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby poskytovateľa podmienky. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"viazať sa so službou Dream service"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby Dream service. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolanie aplikácie pre konfiguráciu poskytnutú operátorom"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Umožňuje aplikácii upraviť parametre kalibrácie dotykovej obrazovky. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"prístup k certifikátom DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Umožňuje aplikácii vydávať a používať certifikáty DRM. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Príjem vysielania pre prenos spojenia"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Povoľuje príjem informácií o stave prenosu spojenia."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Prijímať stav prenosu funkcie Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Povoľuje tejto aplikácii prijímať informácie o aktuálnych prenosoch funkcie Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Ovládanie dĺžky hesiel na odomknutie obrazovky a v nich používané znaky."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Umožňuje aplikácii upraviť históriu prehliadača alebo záložky uložené v telefóne. Aplikácia s týmto povolením môže vymazať alebo upraviť údaje prehliadača. Poznámka: Toto povolenie nemôžu vynucovať prehliadače tretích strán ani žiadne ďalšie aplikácie umožňujúce prehliadanie webu."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"nastaviť budík"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Umožňuje aplikácii nastaviť budík v nainštalovanej aplikácii budík. Niektoré aplikácie budíka nemusia túto funkciu implementovať."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"odstraňovanie hlasových správ"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Povoľuje aplikácii odstraňovať správy z hlasovej schránky."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"správa hlasových správ"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Povoľuje aplikácii upravovať a odstraňovať správy z hlasovej schránky."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"pridať hlasovú schránku"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Umožní aplikácii pridávať správy do doručenej pošty hlasovej schránky."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"čítanie všetkých hlasových schránok"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"I"</string>
<string name="capital_off" msgid="6815870386972805832">"O"</string>
<string name="whichApplication" msgid="4533185947064773386">"Dokončiť akciu pomocou aplikácie"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Vyberte domovskú aplikáciu"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Použiť ako predvolené nastavenie pre túto akciu."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Vymazať predvolené nastavenia v sekcii Nastavenia systému > Aplikácie > Stiahnuté položky."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Vždy povoliť"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nikdy nepovoliť"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Karta SIM bola odobraná"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mobilná sieť nebude k dispozícii, kým nevložíte platnú kartu SIM a zariadenie nereštartujete."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Hotovo"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Bola pridaná karta SIM"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Ak chcete získať prístup k mobilnej sieti, reštartujte svoje zariadenie."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Reštartovať"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastaviť čas"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastaviť dátum"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Bola vybratá položka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Číslo <xliff:g id="KEY">%1$s</xliff:g> bolo odstránené"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Práca – <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Použiť uzamknutie na aplikáciu?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Funkcia Uzamknutie na aplikáciu uzamkne displej na zobrazovanie jednej aplikácie.\n\nTúto funkciu ukončíte stlačením a podržaním tlačidla nedávnych aplikácií $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NIE"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Nachádzate sa v režime Uzamknutie v aplikácii."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Použiť Uzamknutie v aplikácii?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"SPUSTIŤ"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Spustiť funkciu Uzamknutie na aplikáciu"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Ukončiť funkciu Uzamknutie na aplikáciu"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index d0d3cea..11ed9db 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Programu omogoča zapisovanje v sporočila SMS, shranjena v telefonu ali na kartici SIM. Zlonamerni programi lahko izbrišejo vaša sporočila."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"prejemanje sporočil (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Aplikaciji omogoča prejemanje in obdelavo sporočil WAP. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"prejemanje sporočil Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Aplikaciji omogoča prejemanje in obdelavo sporočil Bluetooth MAP. To pomeni, da lahko aplikacija nadzira in izbriše sporočila, poslana v napravo, ne da bi vam jih prikazala."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"dobivanje programov, ki se izvajajo"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Aplikaciji omogoča prejemanje podatkov o trenutnih in nedavno izvajajočih se opravilih. S tem lahko aplikacija odkrije podatke o aplikacijah, ki se uporabljajo v napravi."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interakcija z uporabniki"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"simulirani viri lokacije za preverjanje"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Ustvarjanje simuliranih virov lokacije za preverjanje ali namestitev novega ponudnika lokacije. S tem lahko aplikacija preglasi lokacijo in/ali stanje, ki ga vrnejo drugi viri lokacije, kot so GPS in ponudniki lokacij."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"dostopanje do ukazov ponudnika dodatnih lokacij"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Aplikaciji omogoča, da dostopa do dodatnih ukazov ponudnika lokacij. S tem lahko moti delovanje sistema GPS ali drugih virov lokacije."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Aplikaciji omogoča dostop do dodatnih ukazov ponudnika lokacij. S tem lahko aplikacija moti delovanje sistema GPS ali drugih virov lokacije."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"dovoljenje za namestitev ponudnika lokacije"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Ustvarjanje simuliranih virov lokacije za preverjanje ali namestitev novega ponudnika lokacije. S tem lahko aplikacija preglasi lokacijo in/ali stanje, ki ga vrnejo drugi viri lokacije, kot so GPS in ponudniki lokacij."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"natančna lokacija (na podlagi podatkov GPS in omrežja)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Programu omogoča upravljanje pravilnikov o omrežju in določanje pravil za program."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"spremeni obračunavanje uporabe omrežja"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Programu omogoča, da spremeni uporabo omrežja na podlagi programov. Ni za uporabo z navadnimi programi."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"spreminjanje oznak vtičnic"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Aplikaciji omogoča spreminjanje oznak vtičnic za usmerjanje"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"dostop do obvestil"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Dovoli aplikaciji, da prenese, razišče in izbriše obvestila, tudi tista, ki so jih objavile druge aplikacije."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"poveži se s storitvijo poslušalca obvestil"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lastniku omogoča povezovanje z vmesnikom storitve poslušalca obvestil najvišje ravni. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"povezovanje s storitvijo ponudnika pogojev"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Imetniku omogoča povezovanje z vmesnikom storitve ponudnika pogojev najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"povezava s storitvijo sanjarjenja"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Imetniku omogoča povezovanje z vmesnikom storitve sanjarjenja najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"sprožitev operaterjeve aplikacije za konfiguracijo"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Aplikaciji dovoli spreminjanje parametrov za umerjanje zaslona na dotik. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"dostop do potrdil za upravljanje digitalnih pravic"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Aplikaciji omogoča pripravo in uporabo potrdil za upravljanje digitalnih pravic. To naj ne bi bilo nikoli potrebno za običajne aplikacije."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Prejemanje oddaj o prenosu predaje."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Omogoča prejemanje podatkov o stanju prenosa predaje."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Prejemanje stanja prenosov s funkcijo Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Omogoči tej aplikaciji prejemanje podatkov o trenutnih prenosih s funkcijo Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Aplikaciji omogoča spreminjanje zgodovine ali zaznamkov brskalnika v telefonu. S tem lahko aplikacija izbriše ali spremeni podatke v brskalniku. Opomba: Tega dovoljenja ne morejo uveljavljati drugi brskalniki ali aplikacije, s katerimi je mogoče brskati po spletu."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"nastavitev alarma"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Programu omogoča nastavitev alarma v nameščenem programu budilke. Nekateri programi budilke morda nimajo te funkcije."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"odstranjevanje sporočil iz odzivnika"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Aplikaciji omogoča odstranjevanje sporočil iz odzivnika."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"upravljanje sporočil v odzivniku"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Aplikaciji omogoča spreminjanje in odstranjevanje sporočil iz odzivnika."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"dodajanje odzivnika"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Programu omogoča dodajanje sporočil prejetim sporočilom odzivnika."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"branje vseh sporočil v odzivniku"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"VKLOPLJENO"</string>
<string name="capital_off" msgid="6815870386972805832">"IZKLOPLJENO"</string>
<string name="whichApplication" msgid="4533185947064773386">"Dokončanje dejanja z"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Izberite aplikacijo za začetno stran"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Privzeta uporaba za to dejanje."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Izbrišite privzeti program v sistemskih nastavitvah > Programi > Preneseno."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Vedno dovoli"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Nikoli ne dovoli"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Kartica SIM odstranjena"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mobilno omrežje ne bo na voljo, dokler naprave vnovič ne zaženete z veljavno kartico SIM."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Dokončano"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Kartica SIM dodana"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Za dostop do mobilnega omrežja znova zaženite napravo."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Vnovičen zagon"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastavi uro"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavi datum"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Izbrano: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Številka <xliff:g id="KEY">%1$s</xliff:g> je izbrisana"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za delo"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Ste v načinu zaklepanja v aplikacijo."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Želite uporabiti zaklepanje v aplikacijo?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Zaklepanje v aplikacijo zaklene zaslon v eni aplikaciji.\n\nČe želite zapustiti ta način, pritisnite in pridržite gumb za nedavne aplikacije $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NE"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ZAŽENI"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Zagon zaklepanja v aplikacijo"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Izhod iz zaklepanja v aplikacijo"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 7a884d2..e5cad4e 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Дозвољава апликацији да уписује податке у SMS поруке сачуване на телефону или SIM картици. Злонамерне апликације могу да избришу поруке."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"пријем текстуалних порука (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Дозвољава апликацији да прима и обрађује WAP поруке. Ова дозвола укључује могућност праћења или брисања порука које вам се шаљу, а које вам се не приказују."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"пријем Bluetooth порука (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Дозвољава апликацији да прима и обрађује Bluetooth MAP поруке. То значи да апликација може да надгледа или брише поруке које се шаљу на уређај, а да вам их не прикаже."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"преузимање покренутих апликација"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Дозвољава апликацији да преузима информације о актуелним и недавно покренутим задацима. Ово може да омогући апликацији да открије информације о томе које се апликације користе на уређају."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"интеракција између корисника"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"лажни извори локација у сврхе тестирања"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Прављење лажних извора локација у сврху тестирања или инсталирање новог добављача локације. Ово омогућава апликацији да замени локацију и/или статус који пријављују други извори локација, као што су GPS или добављачи локације."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"приступ додатним командама добављача локације"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Дозвољава апликацији да приступа додатним командама добављача локације. Ово може да омогући апликацији да омета рад GPS уређаја или других извора локације."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Омогућава апликацији да приступа додатним командама даваоца услуга локације. То може да омогући апликацији да утиче на рад GPS-а или других извора локације."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"дозвола за инсталирање добављача локације"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Прављење лажних извора локација у сврху тестирања или инсталирање новог добављача локације. Ово омогућава апликацији да замени локацију и/или статус који пријављују други извори локација, као што су GPS или добављачи локације."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"прецизна локација (заснована на GPS-у и мрежи)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Дозвољава апликацији да управља смерницама за мрежу и одређује посебна правила за апликацију."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"измените обрачунавање коришћења мреже"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Дозвољава апликацији да измени начин на који апликације користе мрежу. Не користе је уобичајене апликације."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"измена ознака утичнице"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Дозвољава апликацији да мења ознаке утичнице за усмеравање"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"приступ обавештењима"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозвољава апликацији да преузима, испитује и брише обавештења, укључујући она која постављају друге апликације."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"повезивање са услугом монитора обавештења"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Дозвољава власнику да се повеже са интерфејсом услуге монитора обавештења највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"повежи са услугом добављача услова"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Дозвољава власнику да се повеже са интерфејсом највишег нивоа услуге добављача услова. Не би требало никада да буде потребно за уобичајене апликације."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"повезивање са услугом сањарења"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Дозвољава власнику да се повеже са интерфејсом услуге сањарења највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"позивање апликације са конфигурацијом коју одређује оператер"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Дозвољава апликацији да модификује параметре калибрације додирног екрана. Не би требало да буде потребно за нормалне апликације."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"приступ DRM сертификатима"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Дозвољава апликацији да додељује и користи DRM сертификате. Никада не би требало да се користи за уобичајене апликације."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Пријем емитовања трансфера."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Дозвољава пријем информација о статусу трансфера."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Пријем статуса пребацивања помоћу Android пребацивања"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Дозвољава овој апликацији да прима информације о актуелним пребацивањима помоћу Android пребацивања"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролишите дужину и знакове дозвољене у лозинкама за откључавање екрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Дозвољава апликацији да мења историју Прегледача или обележиваче ускладиштене на телефону. Ово може да омогући апликацији да брише или мења податке Прегледача. Напомена: Ова дозвола се можда на примењује на прегледаче треће стране и друге апликације са могућношћу веб прегледања."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"подешавање аларма"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Дозвољава апликацији да подеси аларм у инсталираној апликацији будилника. Неке апликације будилника можда не примењују ову функцију."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"уклањање говорне поште"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Дозвољава апликацији да уклања поруке из примљених порука говорне поште."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"управљање порукама говорне поште"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Дозвољава апликацији да мења и уклања поруке из пријемног сандучета говорне поште."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"додавање говорне поште"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Дозвољава апликацији да додаје поруке у пријемно сандуче говорне поште."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"читај сву говорну пошту"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"ДА"</string>
<string name="capital_off" msgid="6815870386972805832">"НЕ"</string>
<string name="whichApplication" msgid="4533185947064773386">"Довршавање радње помоћу"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Изаберите апликацију за почетну страницу"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Подразумевано користи за ову радњу."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Обришите подразумевано подешавање у менију Подешавања система > Апликације > Преузето."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Увек дозволи"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Никада не дозволи"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM картица је уклоњена"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Мобилна мрежа неће бити доступна док не покренете систем поново уз уметање важеће SIM картице."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM картица је додата"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Рестартујте уређај да бисте могли да приступите мобилној мрежи."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Поново покрени"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Подешавање времена"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Подешавање датума"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Изабрали сте <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Избрисали сте <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> на послу"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Желите ли да користите закључавање у апликацији?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Закључавање у апликацији закључава екран у само једној апликацији.\n\nДа бисте изашли притисните и држите дугме за недавне апликације $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"НЕ"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Користите режим Закључавање на апликацију."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Желите ли да користите Закључај на апликацију?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ПОКРЕНИ"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Покрени закључавање у апликацији"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Излазак из Закључавања у апликацији"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 71fdf64..a13ac99 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Tillåter att appen skriver till SMS som lagras på mobilen eller SIM-kortet. Skadliga appar kan radera dina meddelanden."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"ta emot textmeddelanden (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Tillåter att appen tar emot och hanterar WAP-meddelanden. Med den här behörigheten kan appen övervaka eller ta bort meddelanden som skickats till dig utan att visa dem för dig."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"ta emot Bluetooth-meddelanden (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Tillåter att appen tar emot och hanterar Bluetooth MAP-meddelanden. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"hämta appar som körs"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Tillåter att appen hämtar information om nyligen körda och pågående aktiviteter. Detta kan innebära att appen tillåts ta reda på vilka appar som används på enheten."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"interagera mellan användare"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"skenplatser för att testa"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Skapa skenplatser för tester eller installera en ny platsleverantör. Detta innebär att appen tillåts åsidosätta den plats och/eller status som returneras av andra platskällor, till exempel GPS eller platsleverantörer."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"få åtkomst till extra kommandon för platsleverantör"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Tillåter att appen får åtkomst till extra kommandon för platsleverantör. Detta kan innebära att appen tillåts störa funktionen för GPS eller andra platskällor."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Tillåter att appen får åtkomst till extra kommandon för platsleverantör. Detta kan innebära att appen tillåts störa funktionen för GPS eller andra platskällor."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"behörighet att installera en platsleverantör"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Skapa skenplatser för tester eller installera en ny platsleverantör. Detta innebär att appen tillåts åsidosätta den plats och/eller status som returneras av andra platskällor, som GPS eller platsleverantörer."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"exakt plats (GPS- och nätverksbaserad)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Tillåter att appen hanterar nätverkspolicyer och definierar appspecifika regler."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ändra nätverksredovisningen"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Tillåter att appen ändrar hur nätverksanvändning redovisas för appar. Används inte av vanliga appar."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"ändra socketmarkeringar"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Appen tillåts att ändra socketmarkeringar för routing"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"få åtkomst till meddelanden"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillåter att appen hämtar, granskar och raderar meddelanden, även sådana som skickats av andra appar."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"binda till en meddelandelyssnare"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en meddelandelyssnare. Ska inte behövas för vanliga appar."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind till en leverantörstjänst"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en leverantörstjänst. Ska inte behövas för vanliga appar."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"binda till en drömtjänst"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en drömtjänst. Ska inte behövas för vanliga appar."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"anropa konfigurationsappen från operatören"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Tillåter att appen ändrar kalibreringsparametrarna för pekskärmen. Detta behövs aldrig för vanliga appar."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"tillgång till DRM-certifikat"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Tillåter att en app tillhandahåller och använder DRM-certifikat. Behövs inte för vanliga appar."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Ta emot överföringssändningar."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Tillåter att information om överföringsstatus tas emot."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Ta emot status för Android Beam-överföring"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Tillåter att appen tar emot information om aktuella Android Beam-överföringar"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Tillåter att appen ändrar historiken för besökta sidor i webbläsaren eller bokmärken som sparats på telefonen. Det kan innebära att appen kan ta bort eller ändra webbläsarinformation. Observera att den här behörigheten kanske inte är tillämplig för webbläsare från tredje part eller andra appar med surffunktion."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"ställa in ett alarm"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Tillåter att appen ställer in ett alarm i en befintlig alarmapp. Vissa alarmappar har inte den här funktionen."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"ta bort röstmeddelanden"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Tillåter att appen tar bort meddelanden från röstbrevlådans inkorg."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"hantera meddelanden i röstbrevlådan"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Tillåter att appen ändrar och tar bort meddelanden från röstbrevlådans inkorg."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"lägg till röstbrevlåda"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Gör att appen lägger till meddelanden i röstbrevlådans inkorg."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"läsa alla röstmeddelanden"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"PÅ"</string>
<string name="capital_off" msgid="6815870386972805832">"AV"</string>
<string name="whichApplication" msgid="4533185947064773386">"Slutför åtgärd genom att använda"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Välj en app på startskärmen"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Använd som standard för denna åtgärd."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Rensa standardinställningar i Systeminställningar > Appar > Hämtat."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Tillåt alltid"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Tillåt aldrig"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-kortet togs bort"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Det mobila nätverket kommer inte att vara tillgängligt förrän du startar om med ett giltigt SIM-kort."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Klar"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-kort lades till"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Du måste starta om enheten för att ansluta till det mobila nätverket."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Starta om"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Ange tid"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Ange datum"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> har markerats"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> har tagits bort"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> för arbetet"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Läget Lås till app används."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Vill du använda Lås till app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Med funktionen Lås till app låses skärmen i en enskild app.\n\nAvsluta genom att trycka länge på knappen för de senaste apparna $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"NEJ"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"STARTA"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Starta Lås till app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Avsluta Lås till app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c1ad24c..84489da 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Huruhusu programu kuandika SMS zinazohifadhiwa kwenye simu yako au SIM kadi. programu hasidi zinaweza kufuta SMS zako."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"pokea ujumbe wa maandishi wa WAP"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Inaruhusu programu kupokea na kuchakata ujumbe wa WAP. Idhini hii inajumuisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwako bila ya kukuonyesha."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"pokea ujumbe wa Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Inaruhusu programu kupokea na kuchakata ujumbe wa Bluetooth MAP. Hii inamaanisha programu inaweza kufuatilia au kufuta ujumbe unaotumwa kwenye kifaa chako pasipo kukuonyesha ujumbe huo."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"rudisha programu zinazoendeshwa"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Inaruhusu programu kurudisha taarifa kuhusu kazi zinazoendeshwa sasa na hivi karibuni. Hii inaweza kuruhusu programu kugundua taarifa kuhusu ni programu zipi zinazotumika kwenye kifaa."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"kuwasiliana na watumiaji wengine"</string>
@@ -305,7 +303,7 @@
<string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"leseni kamili ili kushirikiana na watumiaji"</string>
<string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Inaruhusu miingialiano yote inayowezekana kwa watumiaji."</string>
<string name="permlab_manageUsers" msgid="1676150911672282428">"dhibiti watumiaji"</string>
- <string name="permdesc_manageUsers" msgid="8409306667645355638">"Inaruhusu programu kudhibiti watumiaji kwenye kifaa, pamoja na hoji, uundaji na ufutaji."</string>
+ <string name="permdesc_manageUsers" msgid="8409306667645355638">"Huruhusu programu kudhibiti watumiaji kwenye kifaa, ikiwa ni pamoja na hoja, uundaji na ufutaji."</string>
<string name="permlab_getDetailedTasks" msgid="6229468674753529501">"epua maelezo ya programu zinazoendeshwa"</string>
<string name="permdesc_getDetailedTasks" msgid="153824741440717599">"Huruhusu programu kuepua maelezo tondoti kuhusu kazi za sasa na zinazoendelea hivi karibuni. Programu hasidi huenda zikagundua maelezo ya kibinafsi kuhusu programu zingine."</string>
<string name="permlab_reorderTasks" msgid="2018575526934422779">"Agiza tena programu za kuendeshwa"</string>
@@ -414,11 +412,11 @@
<string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bandika kwenye huduma ya mtoa huduma za njia"</string>
<string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Huruhusu mmiliki kubandika kwenye watoa huduma za njia waliosajiliwa. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"jiunge na msimamizi wa kifaa"</string>
- <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Inamruhusu mmiliki kutuma malengo kwa msimamizi wa kifaa. Haipaswi kuhitajika kwa programu za kawaida."</string>
+ <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Humruhusu mmiliki kutuma kidhibiti cha kifaa malengo. Programu za kawaida hazikihitaji."</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"bandika kwenye zana za data ya runinga"</string>
<string name="permdesc_bindTvInput" msgid="2371008331852001924">"Inaruhusu kishikiliaji kubandika kwenye kusano la kiwango cha juu cha zana za data kwenye runinga. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ongeza au ondoa msimamizi wa kifaa"</string>
- <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Inaruhusu mmiliki kuongeza au kuondoa wasimamizi wa kifaa waliopo. Kamwe kisihitajike kwa ajili ya programu za kawaida."</string>
+ <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Huruhusu mmiliki kuongeza au kuondoa vidhibiti vya kifaa vinavyotumika. Programu za kawaida hazivihitaji."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"badilisha uelekezo wa skrini"</string>
<string name="permdesc_setOrientation" msgid="3046126619316671476">"Inaruhusu programu kubadilisha mzunguko wa skrini wakati wowote. Kamwe hazihitajiki kwa programu za kawaida."</string>
<string name="permlab_setPointerSpeed" msgid="9175371613322562934">"Badilisha kasi ya pointa"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"vyanzo vya jaribio la mahali kwa lengo la majaribio"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Unda vyanzo vya majaribio ya eneo vya kujaribia au usakinishe mtoaji huduma mpya wa eneo. Hii inaruhusu programu kufuta eneo na/au hali inayorudishwa na vyanzo vingine vya eneo kama vile GPS au watoaji huduma wa eneo."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"fikia amri za ziada za mtoa huduma ya mahali"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Huruhusu programu kufikia amri za ziada za mtoaji huduma wa eneo. Hii inaweza kuruhusu programu kuhitilafiana na uendeshaji wa GPS au vyanzo vingine vya eneo."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ruhusu programu kufikia amri za ziada za mtoa huduma za mahali. Hii huenda ikaruhusu programu ikatize matumizi ya GPS au vyanzo vingine vya eneo."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"kibali ili kusakinisha mtoa huduma ya mahali"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Unda vyanzo vya eneo la majaribio vya kujaribu au kusakinisha mtoaji huduma mpya wa eneo. Hii inaruhusu programu kufuta eneo na/au hali zilizorudishwa na vyanzo vingine vya eneo kama vile GPS au watoaji huduma wa eneo."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"eneo sahihi (GPS na mtandao)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Inaruhusu programu kudhibiti sera za mtandao na kufafanua sheria maalum za programu."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"badilisha uthibitishaji wa matumizi ya mtandao"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Huruhusu programu kurekebisha jinsi matumizi ya mtandao yana hesabika dhidi ya programu. Sio ya matumizi na programu za kawaida."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"rekebisha alama za soketi"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Inaruhusu programu kurekebisha alama za soketi za upelekaji"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"fikia arifa"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Huruhusu programu kurejesha, kuchunguza, na kuondoa arifa, ikiwa ni pamoja na zile zilizochapishwa na programu nyingine."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"unganisha kwenye huduma ya kisikilizi cha arifa"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Inaruhusu kishikilizi kuunganishwa kwenye kusano cha kiwango cha juu cha huduma ya kisikilizi cha arifa. Haipaswi kuhitajika tena kwa programu za kawaida."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bandika kwenye huduma ya mtoa masharti"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Humruhusu mmiliki kubandika kwenye kiolesura cha kiwango cha juu cha huduma ya mtoa masharti. Isihitajike kamwe kwa pogramu za kawaida."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"shurutisha kwa huduma murua"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Huruhusu mmiliki kushurutisha kwenye kiolesura cha kiwango cha juu cha huduma murua. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"omba programu ya usakinishaji inayotolewa na mtoa huduma."</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Huruhusu programu kubadilisha vigezo vya urekebishaji vya skrini ya kugusa. Havipaswi kuhitajika kamwe kwa programu za kawaida."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"fikia vyeti vya DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Huruhusu programu kwa utoaji na matumizi ya vyeti vya DRM. Havifahi kuhitajika kwa ajili ya programu za kawaida."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Pokea matangazo ya makabidhiano ya uhamisho."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Huruhusu upokeaji wa maelezo ya hali ya makabidhiano ya uhamisho."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Pokea hali ya uhamisho wa Boriti ya Android"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Huruhusu programu hii kupokea taarifa kuhusu uhamisho wa Boriti ya Android"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Kuweka kanuni za nenosiri"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kudhibiti urefu na herufi zinazoruhusiwa katika manenosiri ya kufungua skrini."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Inaruhusu programu kurekebisha historia ya Kivinjari au alamisho zilizohifadhiwa kwenye simu yako. Hii huenda ikaruhusu programu kufuta au kurekebisha data ya Kivinjari. Kumbuka: huenda idhini hii isitekelezwe na vivinjari vingine au programu nyingine zenye uwezo wa kuvinjari wavuti."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"weka kengele"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Inaruhusu programu kuweka kengele katika programu iliyosakinishwa ya kengele. Programu zingine za kengele zinawezakosa kutekeleza kipengee hiki."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"ondoa ujumbe wa sauti"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Huruhusu programu kuondoa ujumbe kwenye kikasha chako cha ujumbe wa sauti."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"simamia ujumbe wa sauti"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Huruhusu programu kubadili na kuondoa ujumbe kwenye kikasha chako cha ujumbe wa sauti."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"ongeza barua ya sauti"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Huruhusu programu kuongeza mawasiliano kwenye kikasha cha ujumbe wa sauti."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"soma ujumbe wote wa sauti"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"Washa"</string>
<string name="capital_off" msgid="6815870386972805832">"ZIMA"</string>
<string name="whichApplication" msgid="4533185947064773386">"Kamilisha kitendo ukitumia"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Chagua programu ya nyumbani"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Tumia kama chaguo-msingi la kitendo hiki."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Futa chaguo-msingi katika mipangilio ya Mfumo > Apps > iliyopakuliwa."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Ruhusu Kila mara"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Usiruhusu Kamwe"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM kadi imeondolewa"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na SIM kadi halali iliyoingizwa."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Nimemaliza"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM kadi imeongezwa"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Anzisha upya kifaa chako ili kufikia mtandao wa simu."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Anza upya"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Weka muda"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Weka tarehe"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> kimechaguliwa"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> kimefutwa"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Ya kazini <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Ungependa kutumia lazimisha kutumia programu?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lazimisha kutumia programu katika programu moja. \n\n Ili uondoke bonyeza na ushikilie kitufe cha programu za hivi majuzi $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"HAPANA"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Uko katika hali ya Kusalia katika Programu Moja."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Ungependa kutumia kipengele cha kusalia katika programu moja?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"ANZA"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Anzisha Lazimisha kutumia programu"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Ondoka kwenye Lazimisha kutumia programu"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 04790a7..0a371ba 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -51,7 +51,7 @@
<string name="serviceEnabledFor" msgid="6856228140453471041">"เปิดการใช้งานบริการสำหรับ:"</string>
<string name="serviceDisabled" msgid="1937553226592516411">"ปิดใช้งานบริการไว้"</string>
<string name="serviceRegistered" msgid="6275019082598102493">"การลงทะเบียนสำเร็จแล้ว"</string>
- <string name="serviceErased" msgid="1288584695297200972">"นำออกเรียบร้อยแล้ว"</string>
+ <string name="serviceErased" msgid="1288584695297200972">"ลบเรียบร้อยแล้ว"</string>
<string name="passwordIncorrect" msgid="7612208839450128715">"รหัสผ่านไม่ถูกต้อง"</string>
<string name="mmiComplete" msgid="8232527495411698359">"MMI เสร็จสมบูรณ์"</string>
<string name="badPin" msgid="9015277645546710014">"PIN เก่าที่คุณพิมพ์ไม่ถูกต้อง"</string>
@@ -145,9 +145,9 @@
<string name="contentServiceSync" msgid="8353523060269335667">"ซิงค์"</string>
<string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ซิงค์"</string>
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"มีการนำออก <xliff:g id="CONTENT_TYPE">%s</xliff:g> มากเกินไป"</string>
- <string name="low_memory" product="tablet" msgid="6494019234102154896">"ที่จัดเก็บข้อมูลของแท็บเล็ตเต็ม นำออกไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
- <string name="low_memory" product="watch" msgid="4415914910770005166">"ที่เก็บข้อมูลนาฬิกาเต็ม โปรดนำออกไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
- <string name="low_memory" product="default" msgid="3475999286680000541">"ที่เก็บข้อมูลโทรศัพท์เต็ม นำออกบางไฟล์เพื่อเพิ่มที่ว่าง"</string>
+ <string name="low_memory" product="tablet" msgid="6494019234102154896">"ที่จัดเก็บข้อมูลของแท็บเล็ตเต็ม ลบไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
+ <string name="low_memory" product="watch" msgid="4415914910770005166">"ที่เก็บข้อมูลนาฬิกาเต็ม โปรดลบไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
+ <string name="low_memory" product="default" msgid="3475999286680000541">"ที่เก็บข้อมูลโทรศัพท์เต็ม ลบบางไฟล์เพื่อเพิ่มที่ว่าง"</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"เครือข่ายอาจได้รับการตรวจสอบ"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"โดยบุคคลที่สามที่ไม่รู้จัก"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"โดย <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
@@ -271,13 +271,13 @@
<string name="permlab_install_shortcut" msgid="4279070216371564234">"ติดตั้งทางลัด"</string>
<string name="permdesc_install_shortcut" msgid="8341295916286736996">"อนุญาตให้แอปพลิเคชันเพิ่มทางลัดหน้าจอหลักโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
<string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"ถอนการติดตั้งทางลัด"</string>
- <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"อนุญาตให้แอปพลิเคชันนำออกทางลัดหน้าจอหลักโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
+ <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"อนุญาตให้แอปพลิเคชันลบทางลัดหน้าจอหลักโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
<string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"จัดเส้นทางการโทรออกใหม่"</string>
<string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"อนุญาตให้แอปดูหมายเลขที่โทรในระหว่างการโทรออกโดยสามารถเลือกเปลี่ยนเส้นทางการโทรไปยังหมายเลขอื่นหรือยกเลิกการโทรไปเลยได้"</string>
<string name="permlab_receiveSms" msgid="8673471768947895082">"รับข้อความ (SMS)"</string>
- <string name="permdesc_receiveSms" msgid="6424387754228766939">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ SMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือนำออกข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
+ <string name="permdesc_receiveSms" msgid="6424387754228766939">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ SMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
<string name="permlab_receiveMms" msgid="1821317344668257098">"รับข้อความ (MMS)"</string>
- <string name="permdesc_receiveMms" msgid="533019437263212260">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือนำออกข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
+ <string name="permdesc_receiveMms" msgid="533019437263212260">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
<string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"ได้รับการกระจายข้อความฉุกเฉิน"</string>
<string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความที่เผยแพร่กรณีฉุกเฉิน การอนุญาตนี้ใช้ได้เฉพาะกับแอปพลิเคชันระบบเท่านั้น"</string>
<string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"อ่านข้อความที่ได้รับจากสถานีมือถือ"</string>
@@ -290,14 +290,12 @@
<string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"อนุญาตให้แอปพลิเคชันอ่านข้อความ SMS ที่จัดเก็บไว้ในแท็บเล็ตหรือซิมการ์ด ซึ่งจะทำให้แอปพลิเคชันสามารถอ่านข้อความ SMS ทั้งหมดได้ไม่ว่าจะเป็นเนื้อหาใดหรือมีการรักษาข้อมูลที่เป็นความลับแบบใด"</string>
<string name="permdesc_readSms" product="default" msgid="3695967533457240550">"อนุญาตให้แอปพลิเคชันอ่านข้อความ SMS ที่จัดเก็บไว้ในโทรศัพท์หรือซิมการ์ด ซึ่งจะทำให้แอปพลิเคชันสามารถอ่านข้อความ SMS ทั้งหมดได้ไม่ว่าจะเป็นเนื้อหาใดหรือมีการรักษาข้อมูลที่เป็นความลับแบบใด"</string>
<string name="permlab_writeSms" msgid="3216950472636214774">"แก้ไขข้อความของคุณ (SMS หรือ MMS)"</string>
- <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"อนุญาตให้แอปพลิเคชันเขียนลงในข้อความ SMS ที่เก็บไว้ในแท็บเล็ตหรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจนำออกข้อความของคุณทิ้ง"</string>
- <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"อนุญาตให้แอปพลิเคชันเขียนลงในข้อความ SMS ที่เก็บไว้ในโทรศัพท์หรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจนำออกข้อความของคุณทิ้ง"</string>
+ <string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"อนุญาตให้แอปพลิเคชันเขียนลงในข้อความ SMS ที่เก็บไว้ในแท็บเล็ตหรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจลบข้อความของคุณทิ้ง"</string>
+ <string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"อนุญาตให้แอปพลิเคชันเขียนลงในข้อความ SMS ที่เก็บไว้ในโทรศัพท์หรือซิมการ์ดของคุณ แอปพลิเคชันที่เป็นอันตรายอาจลบข้อความของคุณทิ้ง"</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"รับข้อความ (WAP)"</string>
- <string name="permdesc_receiveWapPush" msgid="748232190220583385">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ WAP การอนุญาตนี้รวมถึงความสามารถในการตรวจสอบหรือนำออกข้อความที่ส่งมาให้คุณโดยไม่ต้องแสดงให้คุณเห็น"</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permdesc_receiveWapPush" msgid="748232190220583385">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ WAP การอนุญาตนี้รวมถึงความสามารถในการตรวจสอบหรือลบข้อความที่ส่งมาให้คุณโดยไม่ต้องแสดงให้คุณเห็น"</string>
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"รับข้อความบลูทูธ (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"อนุญาตให้แอปรับและประมวลผลข้อความ MAP สำหรับบลูทูธ ซึ่งหมายความว่าแอปจะสามารถตรวจสอบหรือลบข้อความที่ส่งไปยังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"เรียกแอปพลิเคชันที่ทำงานอยู่"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"อนุญาตให้แอปพลิเคชันเรียกดูข้อมูลเกี่ยวกับงานที่ดำเนินการอยู่ในขณะนี้และเมื่อเร็วๆ นี้ ซึ่งอาจทำให้แอปพลิเคชันสามารถค้นข้อมูลได้ว่าอุปกรณ์นี้ใช้แอปพลิเคชันใดบ้าง"</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"โต้ตอบระหว่างผู้ใช้"</string>
@@ -311,9 +309,9 @@
<string name="permlab_reorderTasks" msgid="2018575526934422779">"จัดลำดับแอปพลิเคชันที่ทำงานอยู่ใหม่"</string>
<string name="permdesc_reorderTasks" msgid="7734217754877439351">"อนุญาตให้แอปพลิเคชันย้ายงานไปยังส่วนหน้าและพื้นหลัง แอปพลิเคชันอาจดำเนินการโดยไม่รอคำสั่งจากคุณ"</string>
<string name="permlab_removeTasks" msgid="6821513401870377403">"หยุดแอปพลิเคชันที่ทำงานอยู่"</string>
- <string name="permdesc_removeTasks" msgid="1394714352062635493">"อนุญาตให้แอปพลิเคชันนำออกงานออกและยุติแอปพลิเคชันต่างๆ ของงานนั้น แอปพลิเคชันที่เป็นอันตรายอาจทำให้แอปพลิเคชันอื่นๆ ทำงานได้ไม่ถูกต้อง"</string>
+ <string name="permdesc_removeTasks" msgid="1394714352062635493">"อนุญาตให้แอปพลิเคชันลบงานออกและยุติแอปพลิเคชันต่างๆ ของงานนั้น แอปพลิเคชันที่เป็นอันตรายอาจทำให้แอปพลิเคชันอื่นๆ ทำงานได้ไม่ถูกต้อง"</string>
<string name="permlab_manageActivityStacks" msgid="7391191384027303065">"จัดการชุดรายการกิจกรรม"</string>
- <string name="permdesc_manageActivityStacks" msgid="1615881933034084440">"อนุญาตให้แอปเพิ่ม นำออก และแก้ไขชุดรายการกิจกรรมที่แอปอื่นใช้งาน แอปที่อันตรายอาจรบกวนการทำงานของแอปอื่น"</string>
+ <string name="permdesc_manageActivityStacks" msgid="1615881933034084440">"อนุญาตให้แอปเพิ่ม ลบ และแก้ไขชุดรายการกิจกรรมที่แอปอื่นใช้งาน แอปที่อันตรายอาจรบกวนการทำงานของแอปอื่น"</string>
<string name="permlab_startAnyActivity" msgid="2918768238045206456">"เริ่มต้นกิจกรรมใดๆ"</string>
<string name="permdesc_startAnyActivity" msgid="997823695343584001">"อนุญาตให้แอปพลิเคชันเริ่มกิจกรรม ไม่ว่าการอนุญาตหรือสถานะที่ส่งออกจะเป็นอย่างไรก็ตาม"</string>
<string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"ตั้งค่าความเข้ากันได้ของหน้าจอ"</string>
@@ -351,7 +349,7 @@
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ตรวจสอบและควบคุมแอปพลิเคชันทั้งหมดที่เปิดใช้งาน"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"อนุญาตให้แอปพลิเคชันตรวจสอบและควบคุมวิธีการที่ระบบเปิดกิจกรรมต่างๆ แอปพลิเคชันที่เป็นอันตรายอาจทำอันตรายแก่ระบบได้อย่างสิ้นเชิง การอนุญาตนี้จำเป็นสำหรับการพัฒนาเท่านั้น ไม่ใช้สำหรับแอปพลิเคชันทั่วไปโดยเด็ดขาด"</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ส่งการกระจายข้อมูลว่ามีการนำแพ็กเกจออก"</string>
- <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าแพ็กเกจของแอปพลิเคชันหนึ่งๆ ได้ถูกนำออกไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ยุติแอปพลิเคชันอื่นๆ ที่กำลังทำงานอยู่"</string>
+ <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าแพ็กเกจของแอปพลิเคชันหนึ่งๆ ได้ถูกลบไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ยุติแอปพลิเคชันอื่นๆ ที่กำลังทำงานอยู่"</string>
<string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"ส่งการกระจายข้อมูลว่าได้รับ SMS"</string>
<string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าได้รับข้อความ SMS แล้ว แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ปลอมข้อความ SMS ที่เข้ามา"</string>
<string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ส่งการกระจายข้อมูลว่าได้รับ WAP-PUSH"</string>
@@ -417,8 +415,8 @@
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"อนุญาตให้ผู้ใช้ส่งการติดต่อไปยังโปรแกรมควบคุมอุปกรณ์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"เชื่อมโยงกับอินพุตทีวี"</string>
<string name="permdesc_bindTvInput" msgid="2371008331852001924">"อนุญาตให้เจ้าของเชื่อมโยงกับส่วนติดต่อระดับสูงสุดของอินพุตทีวี ซึ่งแอปทั่วไปไม่จำเป็นต้องใช้"</string>
- <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"เพิ่มหรือนำออกผู้ดูแลระบบอุปกรณ์"</string>
- <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"อนุญาตให้เจ้าของเพิ่มหรือนำออกผู้ดูแลระบบอุปกรณ์ที่ใช้งาน ไม่ควรต้องใช้สำหรับแอปปกติ"</string>
+ <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"เพิ่มหรือลบผู้ดูแลระบบอุปกรณ์"</string>
+ <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"อนุญาตให้เจ้าของเพิ่มหรือลบผู้ดูแลระบบอุปกรณ์ที่ใช้งาน ไม่ควรต้องใช้สำหรับแอปปกติ"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"เปลี่ยนการวางแนวหน้าจอ"</string>
<string name="permdesc_setOrientation" msgid="3046126619316671476">"อนุญาตให้แอปพลิเคชันเปลี่ยนการหมุนของหน้าจอได้ตลอดเวลา ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_setPointerSpeed" msgid="9175371613322562934">"เปลี่ยนความเร็วของตัวชี้"</string>
@@ -430,19 +428,19 @@
<string name="permlab_persistentActivity" msgid="8841113627955563938">"ทำให้แอปพลิเคชันทำงานเสมอ"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"อนุญาตให้แอปพลิเคชันทำให้ส่วนหนึ่งของตัวเองคงอยู่ถาวรในหน่วยความจำ ซึ่งจะจำกัดพื้นที่หน่วยความจำที่ใช้งานได้ของแอปพลิเคชันอื่นๆ และทำให้แท็บเล็ตทำงานช้าลง"</string>
<string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"อนุญาตให้แอปพลิเคชันทำให้ส่วนหนึ่งของตัวเองคงอยู่ถาวรในหน่วยความจำ ซึ่งจะจำกัดพื้นที่หน่วยความจำที่ใช้งานได้ของแอปพลิเคชันอื่นๆ และทำให้โทรศัพท์ทำงานช้าลง"</string>
- <string name="permlab_deletePackages" msgid="184385129537705938">"นำออกแอปพลิเคชัน"</string>
- <string name="permdesc_deletePackages" msgid="7411480275167205081">"อนุญาตให้แอปพลิเคชันนำออกแพ็กเกจ Android แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้นำออกแอปพลิเคชันที่สำคัญ"</string>
- <string name="permlab_clearAppUserData" msgid="274109191845842756">"นำออกข้อมูลของแอปพลิเคชันอื่น"</string>
+ <string name="permlab_deletePackages" msgid="184385129537705938">"ลบแอปพลิเคชัน"</string>
+ <string name="permdesc_deletePackages" msgid="7411480275167205081">"อนุญาตให้แอปพลิเคชันลบแพ็กเกจ Android แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ลบแอปพลิเคชันที่สำคัญ"</string>
+ <string name="permlab_clearAppUserData" msgid="274109191845842756">"ลบข้อมูลของแอปพลิเคชันอื่น"</string>
<string name="permdesc_clearAppUserData" msgid="4625323684125459488">"อนุญาตให้แอปพลิเคชันล้างข้อมูลผู้ใช้"</string>
- <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"นำออกแคชของแอปพลิเคชันอื่น"</string>
- <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"อนุญาตให้แอปพลิเคชันนำออกไฟล์แคช"</string>
+ <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"ลบแคชของแอปพลิเคชันอื่น"</string>
+ <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"อนุญาตให้แอปพลิเคชันลบไฟล์แคช"</string>
<string name="permlab_getPackageSize" msgid="7472921768357981986">"วัดพื้นที่เก็บข้อมูลของแอปพลิเคชัน"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"อนุญาตให้แอปพลิเคชันเรียกดูรหัส ข้อมูล และขนาดแคชของตน"</string>
<string name="permlab_installPackages" msgid="2199128482820306924">"ติดตั้งแอปพลิเคชันโดยตรง"</string>
<string name="permdesc_installPackages" msgid="5628530972548071284">"อนุญาตให้แอปพลิเคชันติดตั้งแพ็กเกจ Android ใหม่หรือที่อัปเดต แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ในการเพิ่มแอปพลิเคชันใหม่ๆ ด้วยสิทธิ์ที่สูงนี้ได้ตามต้องการ"</string>
- <string name="permlab_clearAppCache" msgid="7487279391723526815">"นำออกข้อมูลแคชของแอปพลิเคชันทั้งหมด"</string>
- <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"อนุญาตให้แอปพลิเคชันสร้างพื้นที่ว่างในที่จัดเก็บข้อมูลของแท็บเล็ต โดยนำออกไฟล์ในไดเรกทอรีแคชของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นเริ่มทำงานช้ากว่าเดิมเนื่องจากต้องดึงข้อมูลของตนซ้ำ"</string>
- <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"อนุญาตให้แอปพลิเคชันสร้างพื้นที่ว่างในที่จัดเก็บข้อมูลของโทรศัพท์ โดยนำออกไฟล์ในไดเรกทอรีแคชของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นเริ่มทำงานช้ากว่าเดิมเนื่องจากต้องดึงข้อมูลของตนซ้ำ"</string>
+ <string name="permlab_clearAppCache" msgid="7487279391723526815">"ลบข้อมูลแคชของแอปพลิเคชันทั้งหมด"</string>
+ <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"อนุญาตให้แอปพลิเคชันสร้างพื้นที่ว่างในที่จัดเก็บข้อมูลของแท็บเล็ต โดยลบไฟล์ในไดเรกทอรีแคชของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นเริ่มทำงานช้ากว่าเดิมเนื่องจากต้องดึงข้อมูลของตนซ้ำ"</string>
+ <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"อนุญาตให้แอปพลิเคชันสร้างพื้นที่ว่างในที่จัดเก็บข้อมูลของโทรศัพท์ โดยลบไฟล์ในไดเรกทอรีแคชของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นเริ่มทำงานช้ากว่าเดิมเนื่องจากต้องดึงข้อมูลของตนซ้ำ"</string>
<string name="permlab_movePackage" msgid="3289890271645921411">"ย้ายแหล่งข้อมูลแอปพลิเคชัน"</string>
<string name="permdesc_movePackage" msgid="319562217778244524">"อนุญาตให้แอปพลิเคชันย้ายแหล่งข้อมูลแอปพลิเคชันจากภายในไปยังสื่อภายนอกและกลับกัน"</string>
<string name="permlab_readLogs" msgid="6615778543198967614">"อ่านข้อมูลบันทึกที่สำคัญ"</string>
@@ -479,14 +477,14 @@
<string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ต ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลผู้ติดต่อของคุณ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลผู้ติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
<string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลผู้ติดต่อของคุณ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลผู้ติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
<string name="permlab_writeContacts" msgid="5107492086416793544">"แก้ไขผู้ติดต่อของคุณ"</string>
- <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงข้อมูลผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ต ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถนำออกข้อมูลผู้ติดต่อได้"</string>
- <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงข้อมูลผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถนำออกข้อมูลผู้ติดต่อได้"</string>
+ <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงข้อมูลผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ต ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถลบข้อมูลผู้ติดต่อได้"</string>
+ <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงข้อมูลผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถลบข้อมูลผู้ติดต่อได้"</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"อ่านประวัติการโทร"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"อนุญาตให้แอปพลิเคชันอ่านบันทึกการโทรของแท็บเล็ต ซึ่งรวมถึงข้อมูลเกี่ยวกับการโทรเข้าและโทรออก การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลบันทึกการโทรของคุณได้ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลบันทึกการโทรนี้โดยไม่แจ้งให้คุณทราบ"</string>
<string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"อนุญาตให้แอปพลิเคชันอ่านบันทึกการโทรของโทรศัพท์ ซึ่งรวมถึงข้อมูลเกี่ยวกับการโทรเข้าและโทรออก การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลบันทึกการโทรของคุณได้ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลบันทึกการโทรนี้โดยไม่แจ้งให้คุณทราบ"</string>
<string name="permlab_writeCallLog" msgid="8552045664743499354">"เขียนประวัติการโทร"</string>
- <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"อนุญาตให้แอปแก้ไขประวัติการโทรจากแท็บเล็ตของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อนำออกหรือแก้ไขประวัติการโทรของคุณ"</string>
- <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"อนุญาตให้แอปแก้ไขประวัติการโทรจากโทรศัพท์ของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อนำออกหรือแก้ไขประวัติการโทรของคุณ"</string>
+ <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"อนุญาตให้แอปแก้ไขประวัติการโทรจากแท็บเล็ตของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อลบหรือแก้ไขประวัติการโทรของคุณ"</string>
+ <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"อนุญาตให้แอปแก้ไขประวัติการโทรจากโทรศัพท์ของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อลบหรือแก้ไขประวัติการโทรของคุณ"</string>
<string name="permlab_readProfile" msgid="4701889852612716678">"อ่านบัตรผู้ติดต่อของคุณเอง"</string>
<string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลส่วนตัวในโปรไฟล์ที่จัดเก็บไว้ในอุปกรณ์ของคุณ เช่น ชื่อและข้อมูลติดต่อของคุณ ซึ่งหมายความว่าแอปพลิเคชันสามารถระบุตัวคุณและอาจส่งข้อมูลโปรไฟล์ของคุณให้ผู้อื่น"</string>
<string name="permlab_writeProfile" msgid="907793628777397643">"แก้ไขบัตรผู้ติดต่อของคุณเอง"</string>
@@ -501,12 +499,12 @@
<string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บไว้ในแท็บเล็ตของคุณ ซึ่งรวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย ซึ่งอาจทำให้แอปพลิเคชันสามารถแชร์หรือบันทึกข้อมูลในปฏิทินของคุณได้ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับหรือหรือข้อมูลที่อ่อนไหวแบบใดก็ตาม"</string>
<string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บไว้ในโทรศัพท์ของคุณ ซึ่งรวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย ซึ่งอาจทำให้แอปพลิเคชันสามารถแชร์หรือบันทึกข้อมูลในปฏิทินของคุณได้ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับหรือหรือข้อมูลที่อ่อนไหวแบบใดก็ตาม"</string>
<string name="permlab_writeCalendar" msgid="8438874755193825647">"เพิ่มหรือแก้ไขกิจกรรมบนปฏิทินและส่งอีเมลให้ผู้เข้าร่วมโดยที่เจ้าของไม่ทราบ"</string>
- <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"อนุญาตให้แอปพลิเคชันเพิ่ม นำออก เปลี่ยนกิจกรรมที่คุณสามารถเปลี่ยนแปลงในแท็บเล็ตได้ รวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย การอนุญาตนี้อาจทำให้แอปพลิเคชันสามารถส่งข้อความที่มาจากเจ้าของปฏิทิน หรือเปลี่ยนแปลงกิจกรรมโดยที่เจ้าของไม่ทราบ"</string>
- <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"อนุญาตให้แอปพลิเคชันเพิ่ม นำออก เปลี่ยนกิจกรรมที่คุณสามารถเปลี่ยนแปลงในโทรศัพท์ได้ รวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย การอนุญาตนี้อาจทำให้แอปพลิเคชันสามารถส่งข้อความที่มาจากเจ้าของปฏิทิน หรือเปลี่ยนแปลงกิจกรรมโดยที่เจ้าของไม่ทราบ"</string>
+ <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"อนุญาตให้แอปพลิเคชันเพิ่ม ลบ เปลี่ยนกิจกรรมที่คุณสามารถเปลี่ยนแปลงในแท็บเล็ตได้ รวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย การอนุญาตนี้อาจทำให้แอปพลิเคชันสามารถส่งข้อความที่มาจากเจ้าของปฏิทิน หรือเปลี่ยนแปลงกิจกรรมโดยที่เจ้าของไม่ทราบ"</string>
+ <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"อนุญาตให้แอปพลิเคชันเพิ่ม ลบ เปลี่ยนกิจกรรมที่คุณสามารถเปลี่ยนแปลงในโทรศัพท์ได้ รวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย การอนุญาตนี้อาจทำให้แอปพลิเคชันสามารถส่งข้อความที่มาจากเจ้าของปฏิทิน หรือเปลี่ยนแปลงกิจกรรมโดยที่เจ้าของไม่ทราบ"</string>
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"จำลองที่มาของตำแหน่งเพื่อทดสอบ"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"สร้างต้นทางของตำแหน่งจำลองสำหรับการทดสอบหรือติดตั้งผู้ให้บริการตำแหน่งรายใหม่ ซึ่งจะทำให้แอปพลิเคชันสามารถแทนที่ตำแหน่งและ/หรือสถานะที่ส่งกลับมาจากต้นทางของตำแหน่งอื่นๆ เช่น GPS หรือผู้ให้บริการตำแหน่งได้"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"เข้าถึงคำสั่งของโปรแกรมแจ้งตำแหน่งพิเศษ"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"อนุญาตให้แอปเข้าถึงคำสั่งของผู้ให้บริการตำแหน่งเพิ่มเติม ซึ่งอาจทำให้แอปสามารถแทรกแซงการทำงานของ GPS หรือต้นทางของตำแหน่งอื่นๆ ได้"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"อนุญาตให้แอปเข้าถึงคำสั่งของผู้ให้บริการตำแหน่งเพิ่มเติม ซึ่งอาจทำให้แอปสามารถแทรกแซงการทำงานของ GPS หรือต้นทางของตำแหน่งอื่นๆ ได้"</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"การอนุญาตให้ติดตั้งโปรแกรมแจ้งตำแหน่ง"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"สร้างต้นทางของตำแหน่งจำลองสำหรับการทดสอบหรือติดตั้งผู้ให้บริการตำแหน่งรายใหม่ ซึ่งจะทำให้แอปพลิเคชันสามารถแทนที่ตำแหน่งและ/หรือสถานะที่ส่งกลับมาจากต้นทางของตำแหน่งอื่นๆ เช่น GPS หรือผู้ให้บริการตำแหน่งได้"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"ตำแหน่งที่แม่นยำ (อิงตาม GPS และเครือข่าย)"</string>
@@ -556,8 +554,8 @@
<string name="permlab_mount_unmount_filesystems" product="nosdcard" msgid="2927361537942591841">"เข้าถึงระบบไฟล์ของ USB"</string>
<string name="permlab_mount_unmount_filesystems" product="default" msgid="4402305049890953810">"เข้าถึงระบบไฟล์ของการ์ด SD"</string>
<string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"อนุญาตให้แอปพลิเคชันต่อเชื่อมและยกเลิกการต่อเชื่อมระบบไฟล์สำหรับที่เก็บข้อมูลแบบถอดได้"</string>
- <string name="permlab_mount_format_filesystems" product="nosdcard" msgid="6227819582624904972">"นำออกที่จัดเก็บข้อมูล USB"</string>
- <string name="permlab_mount_format_filesystems" product="default" msgid="262582698639274056">"นำออกการ์ด SD"</string>
+ <string name="permlab_mount_format_filesystems" product="nosdcard" msgid="6227819582624904972">"ลบที่จัดเก็บข้อมูล USB"</string>
+ <string name="permlab_mount_format_filesystems" product="default" msgid="262582698639274056">"ลบการ์ด SD"</string>
<string name="permdesc_mount_format_filesystems" msgid="8784268246779198627">"อนุญาตให้แอปพลิเคชันฟอร์แมตที่เก็บข้อมูลแบบถอดได้"</string>
<string name="permlab_asec_access" msgid="3411338632002193846">"รับข้อมูลบนที่เก็บข้อมูลภายใน"</string>
<string name="permdesc_asec_access" msgid="3094563844593878548">"อนุญาตให้แอปพลิเคชันดึงข้อมูลจากที่จัดเก็บข้อมูลภายใน"</string>
@@ -617,7 +615,7 @@
<string name="permlab_setWallpaperHints" msgid="3278608165977736538">"ปรับขนาดวอลเปเปอร์ของคุณ"</string>
<string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"อนุญาตให้แอปพลิเคชันตั้งค่าคำแนะนำขนาดวอลเปเปอร์ของระบบ"</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"รีเซ็ตระบบเป็นค่าเริ่มต้นจากโรงงาน"</string>
- <string name="permdesc_masterClear" msgid="3665380492633910226">"อนุญาตให้แอปพลิเคชันรีเซ็ตระบบทั้งหมดเป็นค่าเริ่มต้นจากโรงงาน นำออกข้อมูลทั้งหมด การกำหนดค่า และแอปพลิเคชันที่ติดตั้งไว้"</string>
+ <string name="permdesc_masterClear" msgid="3665380492633910226">"อนุญาตให้แอปพลิเคชันรีเซ็ตระบบทั้งหมดเป็นค่าเริ่มต้นจากโรงงาน ลบข้อมูลทั้งหมด การกำหนดค่า และแอปพลิเคชันที่ติดตั้งไว้"</string>
<string name="permlab_setTime" msgid="2021614829591775646">"ตั้งเวลา"</string>
<string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"อนุญาตให้แอปพลิเคชันเปลี่ยนเวลานาฬิกาของแท็บเล็ต"</string>
<string name="permdesc_setTime" product="default" msgid="1855702730738020">"อนุญาตให้แอปพลิเคชันเปลี่ยนเวลานาฬิกาของโทรศัพท์"</string>
@@ -693,11 +691,11 @@
<string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"อ่านเนื้อหาในการ์ด SD ของคุณ"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"อนุญาตให้แอปอ่านเนื้อหาในที่จัดเก็บข้อมูล USB"</string>
<string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"อนุญาตให้แอปอ่านเนื้อหาในการ์ด SD"</string>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"แก้ไขหรือนำออกเนื้อหาใน USB"</string>
- <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"แก้ไขหรือนำออกเนื้อหาในการ์ด SD ของคุณ"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"แก้ไขหรือลบเนื้อหาใน USB"</string>
+ <string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"แก้ไขหรือลบเนื้อหาในการ์ด SD ของคุณ"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"อนุญาตให้แอปฯ เขียนลงใน USB"</string>
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"อนุญาตให้แอปพลิเคชันเขียนลงบนการ์ด SD"</string>
- <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"แก้/นำออกเนื้อหาข้อมูลสื่อภายใน"</string>
+ <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"แก้/ลบเนื้อหาข้อมูลสื่อภายใน"</string>
<string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"อนุญาตให้แอปพลิเคชันแก้ไขเนื้อหาของที่เก็บข้อมูลสื่อภายใน"</string>
<string name="permlab_manageDocs" product="default" msgid="5778318598448849829">"จัดการที่เก็บเอกสาร"</string>
<string name="permdesc_manageDocs" product="default" msgid="8704323176914121484">"อนุญาตให้แอปจัดการที่เก็บเอกสาร"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"อนุญาตให้แอปพลิเคชันจัดการนโยบายเครือข่ายและกำหนดกฎเฉพาะแอปพลิเคชัน"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"แก้ไขการบันทึกบัญชีการใช้งานเครือข่าย"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"อนุญาตให้แอปพลิเคชันแก้ไขวิธีการบันทึกบัญชีการใช้งานเครือข่ายของแอปพลิเคชัน ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"แก้ไขเครื่องหมายซ็อกเก็ต"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"อนุญาตให้แอปแก้ไขเครื่องหมายซ็อกเก็ตสำหรับการกำหนดเส้นทาง"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"เข้าถึงการแจ้งเตือน"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"ทำให้แอปสามารถเรียกดู ตรวจสอบ และล้างการแจ้งเตือนได้ ซึ่งรวมถึงการแจ้งเตือนที่โพสต์โดยแอปอื่นๆ ด้วย"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"เชื่อมโยงกับบริการตัวฟังการแจ้งเตือน"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"อนุญาตให้เจ้าของเชื่อมโยงกับอินเตอร์เฟซระดับสูงสุดของบริการตัวฟังการแจ้งเตือน ซึ่งไม่มีความจำเป็นสำหรับแอปธรรมดา"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"เชื่อมโยงกับบริการของผู้เสนอเงื่อนไข"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"อนุญาตให้ผู้ใช้อุปกรณ์เชื่อมโยงกับอินเทอร์เฟซระดับบนสุดของบริการของผู้เสนอเงื่อนไข ไม่จำเป็นสำหรับแอปทั่วไป"</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"เชื่อมโยงกับบริการที่ต้องการ"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"อนุญาตให้แอปพลิเคชันเชื่อมโยงกับอินเทอร์เฟซระดับบนสุดของบริการที่ต้องการ ไม่จำเป็นสำหรับแอปทั่วไป"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"เรียกใช้แอปการกำหนดค่าของผู้ให้บริการ"</string>
@@ -733,20 +733,20 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"อนุญาตให้แอปสามารถปรับพารามิเตอร์การเทียบมาตรฐานของหน้าจอสัมผัส ไม่ควรใช้สำหรับแอปทั่วไป"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"เข้าถึงใบรับรอง DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"ช่วยให้แอปพลิเคชันสามารถจัดสรรและใช้ใบรับรอง DRM ได้ ไม่จำเป็นสำหรับแอปปกติทั่วไป"</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"รับการกระจายข้อมูลการโอนย้ายช่องสัญญาณ"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"อนุญาตให้รับข้อมูลสถานะการโอนย้ายช่องสัญญาณ"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"รับสถานะการโอน Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"อนุญาตให้แอปพลิเคชันนี้รับข้อมูลเกี่ยวกับการโอน Android Beam ปัจจุบัน"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"ตรวจสอบจำนวนของรหัสผ่านที่พิมพ์ไม่ถูกต้องขณะปลดล็อกหน้าจอ และล็อกแท็บเล็ตหรือนำออกข้อมูลทั้งหมดในแท็บเล็ตถ้ามีการพิมพ์รหัสผ่านที่ไม่ถูกต้องมากเกินไป"</string>
- <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"ตรวจสอบจำนวนการพิมพ์รหัสผ่านที่ไม่ถูกต้องขณะปลดล็อกหน้าจอ และล็อกโทรศัพท์หรือนำออกข้อมูลทั้งหมดในโทรศัพท์ถ้ามีการพิมพ์รหัสผ่านที่ไม่ถูกต้องมากเกินไป"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"ตรวจสอบจำนวนของรหัสผ่านที่พิมพ์ไม่ถูกต้องขณะปลดล็อกหน้าจอ และล็อกแท็บเล็ตหรือลบข้อมูลทั้งหมดในแท็บเล็ตถ้ามีการพิมพ์รหัสผ่านที่ไม่ถูกต้องมากเกินไป"</string>
+ <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"ตรวจสอบจำนวนการพิมพ์รหัสผ่านที่ไม่ถูกต้องขณะปลดล็อกหน้าจอ และล็อกโทรศัพท์หรือลบข้อมูลทั้งหมดในโทรศัพท์ถ้ามีการพิมพ์รหัสผ่านที่ไม่ถูกต้องมากเกินไป"</string>
<string name="policylab_resetPassword" msgid="2620077191242688955">"เปลี่ยนรหัสผ่านการปลดล็อกหน้าจอ"</string>
<string name="policydesc_resetPassword" msgid="605963962301904458">"เปลี่ยนรหัสผ่านการปลดล็อกหน้าจอ"</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"ล็อกหน้าจอ"</string>
<string name="policydesc_forceLock" msgid="1141797588403827138">"ควบคุมว่าหน้าจอจะล็อกอย่างไรและเมื่อใด"</string>
- <string name="policylab_wipeData" msgid="3910545446758639713">"นำออกข้อมูลทั้งหมด"</string>
- <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"นำออกข้อมูลของแท็บเล็ตโดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
- <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"นำออกข้อมูลของโทรศัพท์โดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
+ <string name="policylab_wipeData" msgid="3910545446758639713">"ลบข้อมูลทั้งหมด"</string>
+ <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"ลบข้อมูลของแท็บเล็ตโดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
+ <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"ลบข้อมูลของโทรศัพท์โดยไม่มีการเตือน ด้วยการดำเนินการรีเซ็ตข้อมูลเป็นค่าเริ่มต้น"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์"</string>
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"ตั้งค่าพร็อกซีส่วนกลางของอุปกรณ์ที่จะใช้ขณะเปิดการใช้งานนโยบาย เฉพาะผู้ดูแลอุปกรณ์คนแรกเท่านั้นที่ตั้งค่าพร็อกซีส่วนกลางที่มีผลบังคับ"</string>
<string name="policylab_expirePassword" msgid="885279151847254056">"ตั้งค่าวันหมดอายุของรหัสผ่านล็อกหน้าจอ"</string>
@@ -953,7 +953,7 @@
<string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"การควบคุมสื่อ"</string>
<string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"เริ่มเรียงลำดับวิดเจ็ตใหม่"</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"เรียงลำดับวิดเจ็ตใหม่เสร็จแล้ว"</string>
- <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"นำออกวิดเจ็ต <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> แล้ว"</string>
+ <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"ลบวิดเจ็ต <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> แล้ว"</string>
<string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"ขยายพื้นที่ปลดล็อก"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"การปลดล็อกด้วยการเลื่อน"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"การปลดล็อกด้วยรูปแบบ"</string>
@@ -1004,12 +1004,12 @@
<string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"อ่านบุ๊กมาร์กและประวัติเว็บของคุณ"</string>
<string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"อนุญาตให้แอปพลิเคชันอ่านประวัติของ URL ทั้งหมดที่เบราว์เซอร์เคยไป และบุ๊กมาร์กทั้งหมดของเบราว์เซอร์ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นๆ ที่มีความสามารถในการเรียกดูบนเว็บ"</string>
<string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"เขียนบุ๊กมาร์กและประวัติเว็บ"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บไว้ในแท็บเล็ต ซึ่งทำให้แอปพลิเคชันสามารถนำออกหรือเปลี่ยนข้อมูลเบราว์เซอร์ได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นๆ ที่มีความสามารถในการเรียกดูบนเว็บ"</string>
- <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บไว้ในโทรศัพท์ ซึ่งทำให้แอปพลิเคชันสามารถนำออกหรือเปลี่ยนข้อมูลเบราว์เซอร์ได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นๆ ที่มีความสามารถในการเรียกดูบนเว็บ"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บไว้ในแท็บเล็ต ซึ่งทำให้แอปพลิเคชันสามารถลบหรือเปลี่ยนข้อมูลเบราว์เซอร์ได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นๆ ที่มีความสามารถในการเรียกดูบนเว็บ"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บไว้ในโทรศัพท์ ซึ่งทำให้แอปพลิเคชันสามารถลบหรือเปลี่ยนข้อมูลเบราว์เซอร์ได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นๆ ที่มีความสามารถในการเรียกดูบนเว็บ"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"ตั้งปลุก"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"อนุญาตให้แอปพลิเคชันตั้งเวลาปลุกในแอปพลิเคชันนาฬิกาปลุกที่ติดตั้ง แอปพลิเคชันนาฬิกาปลุกบางรายการอาจไม่ใช้คุณลักษณะนี้"</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"นำข้อความเสียงออก"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"อนุญาตให้แอปนำข้อความออกจากกล่องข้อความเสียงของคุณ"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"จัดการข้อความเสียง"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"อนุญาตให้แอปแก้ไขและนำข้อความออกจากกล่องข้อความเสียงของคุณ"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"เพิ่มข้อวามเสียง"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"อนุญาตให้แอปพลิเคชันเพิ่มข้อความลงในกล่องข้อความเสียงของคุณ"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"อ่านข้อความเสียงทั้งหมด"</string>
@@ -1036,7 +1036,7 @@
<string name="prepend_shortcut_label" msgid="2572214461676015642">"เมนู+"</string>
<string name="menu_space_shortcut_label" msgid="2410328639272162537">"Space"</string>
<string name="menu_enter_shortcut_label" msgid="2743362785111309668">"Enter"</string>
- <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"นำออก"</string>
+ <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"ลบ"</string>
<string name="search_go" msgid="8298016669822141719">"ค้นหา"</string>
<string name="searchview_description_search" msgid="6749826639098512120">"ค้นหา"</string>
<string name="searchview_description_query" msgid="5911778593125355124">"คำค้นหา"</string>
@@ -1160,12 +1160,12 @@
<string name="copy" msgid="2681946229533511987">"คัดลอก"</string>
<string name="paste" msgid="5629880836805036433">"วาง"</string>
<string name="replace" msgid="5781686059063148930">"แทนที่..."</string>
- <string name="delete" msgid="6098684844021697789">"นำออก"</string>
+ <string name="delete" msgid="6098684844021697789">"ลบ"</string>
<string name="copyUrl" msgid="2538211579596067402">"คัดลอก URL"</string>
<string name="selectTextMode" msgid="1018691815143165326">"เลือกข้อความ"</string>
<string name="textSelectionCABTitle" msgid="5236850394370820357">"การเลือกข้อความ"</string>
<string name="addToDictionary" msgid="4352161534510057874">"เพิ่มในพจนานุกรม"</string>
- <string name="deleteText" msgid="6979668428458199034">"นำออก"</string>
+ <string name="deleteText" msgid="6979668428458199034">"ลบ"</string>
<string name="inputMethod" msgid="1653630062304567879">"วิธีป้อนข้อมูล"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"การทำงานของข้อความ"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"พื้นที่จัดเก็บเหลือน้อย"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"เปิด"</string>
<string name="capital_off" msgid="6815870386972805832">"ปิด"</string>
<string name="whichApplication" msgid="4533185947064773386">"ทำงานให้เสร็จโดยใช้"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"เลือกแอปหน้าแรก"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ใช้ค่าเริ่มต้นสำหรับการทำงานนี้"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"ล้างค่าเริ่มต้นในการตั้งค่าระบบ > แอปพลิเคชัน > ดาวน์โหลด"</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"อนุญาตทุกครั้ง"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"ไม่อนุญาตเลย"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"นำซิมการ์ดออกแล้ว"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"เครือข่ายมือถือจะไม่สามารถใช้งานได้จนกว่าคุณจะรีสตาร์ทโดยใส่ซิมการ์ดที่ถูกต้องแล้ว"</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"เสร็จสิ้น"</string>
<string name="sim_added_title" msgid="3719670512889674693">"เพิ่มซิมการ์ดแล้ว"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"รีสตาร์ทอุปกรณ์ของคุณเพื่อเข้าถึงเครือข่ายมือถือ"</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"รีสตาร์ท"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"ตั้งเวลา"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"ตั้งวันที่"</string>
@@ -1308,8 +1324,8 @@
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"ปิดที่เก็บข้อมูล USB"</string>
<string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"แตะเพื่อปิดที่จัดเก็บข้อมูล USB"</string>
<string name="usb_storage_stop_title" msgid="660129851708775853">"ใช้การจัดเก็บใน USB"</string>
- <string name="usb_storage_stop_message" product="nosdcard" msgid="4264025280777219521">"ก่อนปิดที่จัดเก็บข้อมูล USB ให้ยกเลิกการต่อเชื่อม (“นำออก”) ที่จัดเก็บข้อมูล USB ของ Android จากคอมพิวเตอร์แล้ว"</string>
- <string name="usb_storage_stop_message" product="default" msgid="8043969782460613114">"ก่อนปิดที่จัดเก็บข้อมูล USB ให้ยกเลิกการต่อเชื่อม (\"นำออก\") การ์ด SD ของ Android จากคอมพิวเตอร์"</string>
+ <string name="usb_storage_stop_message" product="nosdcard" msgid="4264025280777219521">"ก่อนปิดที่จัดเก็บข้อมูล USB ให้ยกเลิกการต่อเชื่อม (“ลบ”) ที่จัดเก็บข้อมูล USB ของ Android จากคอมพิวเตอร์แล้ว"</string>
+ <string name="usb_storage_stop_message" product="default" msgid="8043969782460613114">"ก่อนปิดที่จัดเก็บข้อมูล USB ให้ยกเลิกการต่อเชื่อม (\"ลบ\") การ์ด SD ของ Android จากคอมพิวเตอร์"</string>
<string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"ปิดที่เก็บข้อมูล USB"</string>
<string name="usb_storage_stop_error_message" msgid="1970374898263063836">"เกิดปัญหาในการปิดที่จัดเก็บข้อมูล USB ตรวจสอบให้แน่ใจว่าคุณได้ยกเลิกการต่อเชื่อมโฮสต์ USB แล้ว จากนั้นลองใหม่อีกครั้ง"</string>
<string name="dlg_confirm_kill_storage_users_title" msgid="963039033470478697">"เปิดที่เก็บข้อมูล USB"</string>
@@ -1323,7 +1339,7 @@
<string name="usb_notification_message" msgid="2290859399983720271">"แตะสำหรับตัวเลือก USB อื่นๆ"</string>
<string name="extmedia_format_title" product="nosdcard" msgid="9020092196061007262">"ฟอร์แมต USB หรือไม่"</string>
<string name="extmedia_format_title" product="default" msgid="3648415921526526069">"ฟอร์แมตการ์ด SD หรือไม่"</string>
- <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"ไฟล์ทั้งหมดที่เก็บไว้ในที่จัดเก็บข้อมูล USB ของคุณจะถูกนำออกทิ้ง การทำงานนี้ไม่สามารถย้อนกลับได้!"</string>
+ <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"ไฟล์ทั้งหมดที่เก็บไว้ในที่จัดเก็บข้อมูล USB ของคุณจะถูกลบทิ้ง การทำงานนี้ไม่สามารถย้อนกลับได้!"</string>
<string name="extmedia_format_message" product="default" msgid="14131895027543830">"ข้อมูลทั้งหมดในการ์ดของคุณจะหายไป"</string>
<string name="extmedia_format_button_format" msgid="4131064560127478695">"รูปแบบ"</string>
<string name="adb_active_notification_title" msgid="6729044778949189918">"เชื่อมต่อการแก้ไขข้อบกพร่อง USB แล้ว"</string>
@@ -1348,18 +1364,18 @@
<string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"การ์ด SD เสียหาย"</string>
<string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="1795917578395333280">"ที่จัดเก็บข้อมูล USB เสียหาย ลองฟอร์แมตอีกครั้ง"</string>
<string name="ext_media_unmountable_notification_message" product="default" msgid="1753898567525568253">"การ์ด SD เสียหาย ลองฟอร์แมตอีกครั้ง"</string>
- <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"ที่เก็บข้อมูล USB ถูกนำออกโดยไม่คาดคิด"</string>
- <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"การ์ด SD ถูกนำออกโดยไม่คาดหมาย"</string>
- <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"ยกเลิกการต่อเชื่อมที่เก็บข้อมูล USB ก่อนนำออกเพื่อป้องกันข้อมูลสูญหาย"</string>
- <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"ยกเลิกการต่อเชื่อมการ์ด SD ก่อนนำออกเพื่อหลีกเลี่ยงข้อมูลสูญหาย"</string>
+ <string name="ext_media_badremoval_notification_title" product="nosdcard" msgid="1661683031330951073">"ที่เก็บข้อมูล USB ถูกลบโดยไม่คาดคิด"</string>
+ <string name="ext_media_badremoval_notification_title" product="default" msgid="6872152882604407837">"การ์ด SD ถูกลบโดยไม่คาดหมาย"</string>
+ <string name="ext_media_badremoval_notification_message" product="nosdcard" msgid="4329848819865594241">"ยกเลิกการต่อเชื่อมที่เก็บข้อมูล USB ก่อนลบเพื่อป้องกันข้อมูลสูญหาย"</string>
+ <string name="ext_media_badremoval_notification_message" product="default" msgid="7260183293747448241">"ยกเลิกการต่อเชื่อมการ์ด SD ก่อนลบเพื่อหลีกเลี่ยงข้อมูลสูญหาย"</string>
<string name="ext_media_safe_unmount_notification_title" product="nosdcard" msgid="3967973893270360230">"นำที่เก็บข้อมูล USB ออกอย่างปลอดภัย"</string>
<string name="ext_media_safe_unmount_notification_title" product="default" msgid="6729801130790616200">"นำการ์ด SD ออกได้อย่างปลอดภัย"</string>
<string name="ext_media_safe_unmount_notification_message" product="nosdcard" msgid="6142195361606493530">"คุณสามารถนำที่เก็บข้อมูล USB ออกได้อย่างปลอดภัย"</string>
<string name="ext_media_safe_unmount_notification_message" product="default" msgid="568841278138377604">"คุณสามารถนำการ์ด SD ออกได้อย่างปลอดภัย"</string>
<string name="ext_media_nomedia_notification_title" product="nosdcard" msgid="4486377230140227651">"นำที่เก็บข้อมูล USB ออกแล้ว"</string>
<string name="ext_media_nomedia_notification_title" product="default" msgid="8902518030404381318">"นำการ์ด SD ออกแล้ว"</string>
- <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"ที่เก็บข้อมูล USB ถูกนำออกแล้ว ใส่สื่อใหม่"</string>
- <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"การ์ด SD ถูกนำออก ใส่การ์ดใหม่"</string>
+ <string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"ที่เก็บข้อมูล USB ถูกลบแล้ว ใส่สื่อใหม่"</string>
+ <string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"การ์ด SD ถูกลบ ใส่การ์ดใหม่"</string>
<string name="activity_list_empty" msgid="1675388330786841066">"ไม่พบกิจกรรมที่ตรงกัน"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"อัปเดตสถิติการใช้ส่วนประกอบ"</string>
<string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"อนุญาตให้แอปพลิเคชันแก้ไขสถิติการใช้งานของส่วนประกอบที่เก็บรวบรวมไว้ ไม่ใช้สำหรับแอปพลิเคชันทั่วไป"</string>
@@ -1438,14 +1454,14 @@
<string name="action_mode_done" msgid="7217581640461922289">"เสร็จสิ้น"</string>
<string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"กำลังยกเลิกการต่อเชื่อมที่จัดเก็บข้อมูล USB..."</string>
<string name="progress_unmounting" product="default" msgid="1327894998409537190">"กำลังยกเลิกการต่อเชื่อมการ์ด SD..."</string>
- <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"กำลังนำออกที่จัดเก็บข้อมูล USB..."</string>
- <string name="progress_erasing" product="default" msgid="6596988875507043042">"กำลังนำออกการ์ด SD..."</string>
- <string name="format_error" product="nosdcard" msgid="6299769563624776948">"ไม่สามารถนำออกที่เก็บข้อมูล USB"</string>
- <string name="format_error" product="default" msgid="7315248696644510935">"ไม่สามารถนำออกการ์ด SD"</string>
- <string name="media_bad_removal" msgid="7960864061016603281">"การ์ด SD ถูกนำออกก่อนที่จะยกเลิกการต่อเชื่อม"</string>
+ <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"กำลังลบที่จัดเก็บข้อมูล USB..."</string>
+ <string name="progress_erasing" product="default" msgid="6596988875507043042">"กำลังลบการ์ด SD..."</string>
+ <string name="format_error" product="nosdcard" msgid="6299769563624776948">"ไม่สามารถลบที่เก็บข้อมูล USB"</string>
+ <string name="format_error" product="default" msgid="7315248696644510935">"ไม่สามารถลบการ์ด SD"</string>
+ <string name="media_bad_removal" msgid="7960864061016603281">"การ์ด SD ถูกลบก่อนที่จะยกเลิกการต่อเชื่อม"</string>
<string name="media_checking" product="nosdcard" msgid="418188720009569693">"กำลังตรวจสอบที่เก็บข้อมูล USB อยู่ในขณะนี้"</string>
<string name="media_checking" product="default" msgid="7334762503904827481">"กำลังตรวจสอบการ์ด SD อยู่ในขณะนี้"</string>
- <string name="media_removed" msgid="7001526905057952097">"การ์ด SD ถูกนำออกแล้ว"</string>
+ <string name="media_removed" msgid="7001526905057952097">"การ์ด SD ถูกลบแล้ว"</string>
<string name="media_shared" product="nosdcard" msgid="5830814349250834225">"ขณะนี้ที่เก็บข้อมูล USB ถูกใช้งานอยู่โดยคอมพิวเตอร์"</string>
<string name="media_shared" product="default" msgid="5706130568133540435">"ขณะนี้การ์ด SD มีการใช้งานอยู่โดยคอมพิวเตอร์"</string>
<string name="media_unknown_state" msgid="729192782197290385">"สื่อภายนอกอยู่ในสถานะที่ไม่รู้จัก"</string>
@@ -1460,8 +1476,8 @@
<string name="gpsVerifYes" msgid="2346566072867213563">"ใช่"</string>
<string name="gpsVerifNo" msgid="1146564937346454865">"ไม่"</string>
<string name="sync_too_many_deletes" msgid="5296321850662746890">"เกินจำนวนการนำออกสูงสุด"</string>
- <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"มีรายการที่จะนำออก <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> รายการสำหรับ <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> ในบัญชี <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> คุณต้องการทำสิ่งใด"</string>
- <string name="sync_really_delete" msgid="2572600103122596243">"นำออกรายการ"</string>
+ <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"มีรายการที่จะลบ <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> รายการสำหรับ <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g> ในบัญชี <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> คุณต้องการทำสิ่งใด"</string>
+ <string name="sync_really_delete" msgid="2572600103122596243">"ลบรายการ"</string>
<string name="sync_undo_deletes" msgid="2941317360600338602">"เลิกทำการนำออก"</string>
<string name="sync_do_nothing" msgid="3743764740430821845">"ไม่ต้องทำอะไรในขณะนี้"</string>
<string name="choose_account_label" msgid="5655203089746423927">"เลือกบัญชี"</string>
@@ -1485,7 +1501,7 @@
<string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ลดปี"</string>
<string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
<string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ยกเลิก"</string>
- <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"นำออก"</string>
+ <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ลบ"</string>
<string name="keyboardview_keycode_done" msgid="1992571118466679775">"เสร็จสิ้น"</string>
<string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"เปลี่ยนโหมด"</string>
<string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
@@ -1610,7 +1626,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งใน <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้ับัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
- <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"นำออก"</string>
+ <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"ลบ"</string>
<string name="safe_media_volume_warning" product="default" msgid="7324161939475478066">"ในกรณีที่ต้องการเพิ่มระดับเสียงจนเกินระดับที่แนะนำ\nการฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string>
<string name="continue_to_enable_accessibility" msgid="1626427372316070258">"ใช้สองนิ้วแตะค้างไว้เพื่อเปิดใช้งานการเข้าถึง"</string>
<string name="accessibility_enabled" msgid="1381972048564547685">"เปิดใช้งานการเข้าถึงแล้ว"</string>
@@ -1735,12 +1751,27 @@
<string name="select_day" msgid="7774759604701773332">"เลือกเดือนและวัน"</string>
<string name="select_year" msgid="7952052866994196170">"เลือกปี"</string>
<string name="item_is_selected" msgid="949687401682476608">"เลือก <xliff:g id="ITEM">%1$s</xliff:g>"</string>
- <string name="deleted_key" msgid="7659477886625566590">"นำออก <xliff:g id="KEY">%1$s</xliff:g> แล้ว"</string>
+ <string name="deleted_key" msgid="7659477886625566590">"ลบ <xliff:g id="KEY">%1$s</xliff:g> แล้ว"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g>ที่ทำงาน"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"คุณกำลังใช้โหมดการล็อกแอป"</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"ใช้การล็อกแอปไหม"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"การล็อกแอปจะล็อกการแสดงไว้ในแอปเดียว\n\nหากต้องการออก ให้กดปุ่มแอปล่าสุด$ค้างไว้"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"ไม่"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"เริ่มต้น"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"เริ่มใช้การล็อกแอป"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"ออกจากการล็อกแอป"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 5326e5c..bc4ddcef 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Pinapayagan ang app na magsulat sa mga mensaheng SMS na nakaimbak sa iyong telepono o SIM card. Maaaring tanggalin ng nakakahamak na apps ang iyong mga mensahe."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"tumanggap ng mga text message (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng WAP. Kabilang sa pahintulot na ito ang kakayahang sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyo nang hindi ipinapakita ang mga ito sa iyo."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Tumanggap ng mga mensahe sa Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Pinapayagan ang app na makatanggap at makapagproseso ng mga mensahe ng Bluetooth MAP. Nangangahulugan ito na maaaring subaybayan o i-delete ng app ang mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"bawiin ang tumatakbong apps"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Pinapayagan ang app na kumuha ng impormasyon tungkol sa mga kasalukuyan at kamakailang gumaganang gawain. Maaari nitong payagan ang app na tumuklas ng impormasyon tungkol sa kung aling mga application ang ginagamit sa device."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"makipag-ugnayan sa kabuuan ng mga user"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"gayahin ang mga pinagmumulan ng lokasyon para sa pagsusuri"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Lumikha ng mga mock na pinagmulan ng lokasyon para sa pagsubok o mag-install ng bagong provider ng lokasyon. Pinapayagan nito ang app na i-override ang lokasyon at/o katayuan na ibinabalik ng iba pang mga pinagmulan ng lokasyon gaya ng GPS o mga provider ng lokasyon."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"i-access ang mga dagdag na command ng provider ng lokasyon"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Pinapayagan ang app na mag-access ng mga dagdag na command ng provider ng lokasyon. Maaari nitong payagan ang app na gambalain ang pagpapatakbo ng GPS o ng iba pang mga pinagmulan ng lokasyon."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Nagbibigay-daan sa app na mag-access ng mga karagdagang command ng provider ng lokasyon. Maaari nitong bigyang-daan ang app na gambalain ang pagpapatakbo ng GPS o ng iba pang mga pinagmulan ng lokasyon."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"pahintulot na mag-install ng provider ng lokasyon"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Lumikha ng mga mock na pinagmulan ng lokasyon o mag-install ng bagong provider ng lokasyon. Pinapayagan nito ang app na i-override ang lokasyon at/o katayuan na ibinabalik ng iba pang mga pinagmulan ng lokasyon gaya ng GPS o mga provider ng lokasyon."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"tumpak na lokasyon (batay sa GPS at network)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Pinapayagan ang app na pamahalaan ang mga patakaran ng network at ilarawan ang mga patakarang tukoy sa app."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"baguhin ang pagkukuwenta sa paggamit ng network"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Pinapayagan ang app na baguhin kung paano isinasaalang-alang ang paggamit ng network laban sa apps. Hindi para sa paggamit ng normal na apps."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"baguhin ang mga socket mark"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Nagbibigay-daan sa app na baguhin ang mga socket mark para sa pagruruta"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"i-access ang mga notification"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Pinapayagan ang app na kumuha, sumuri, at mag-clear ng mga notification, kabilang ang mga na-post ng iba pang apps."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"mapailalim sa isang serbisyo ng notification listener"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nagbibigay-daan sa may-ari na mapailalim sa interface sa tuktok na antas ng isang serbisyo ng notification listener. Hindi dapat kailanganin para sa karaniwang apps kahit kailan."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"i-bind sa isang serbisyo sa pagbibigay ng kundisyon"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Nagbibigay-daan sa naghahawak na i-bind ang top-level na interface ng isang serbisyo sa pagbibigay ng kundisyon. Hindi kailanman dapat kailanganin ng mga normal na app."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"sumailalim sa isang serbisyo ng dream"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Pinapayagan ang may-ari na sumailalim sa interface ng serbisyo ng dream na nasa nangungunang antas. Hindi kailanman dapat na kailanganin para sa mga normal na app."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"paganahin ang app ng configuration na ibinigay ng carrier"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Pinapayagan ang app na baguhin ang mga parameter sa pag-calibrate ng touch screen. Hindi dapat kailanganin sa normal na apps."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"access sa Mga DRM certificate"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Nagbibigay-daan sa isang application na makapagbigay at gumamit ng mga DRM certficate. Hindi dapat kailanman kailanganin para sa mga normal na app."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Makatanggap ng mga broadcast ng paglilipat ng handover."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Pinapayagan ang pagtanggap ng impormasyon sa status ng paglilipat ng handover."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Tanggapin ang status ng paglilipat ng Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Pinapayagan ang application na ito na tumanggap ng impormasyon tungkol sa mga kasalukuyang paglilipat ng Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Pinapayagan ang app na baguhin ang kasaysayan o mga bookmark ng Browser na naka-imbak sa iyong telepono. Maaari nitong payagan ang app na burahin o baguhin ang data ng Browser. Tandaan: hindi maaaring ipatupad ang pahintulot na ito ng mga third-party na browser o iba pang mga application na may mga kakayahan sa pagba-browse sa web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"magtakda ng alarm"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Pinapayagan ang app na magtakda ng alarm sa isang naka-install na app ng alarm clock. Maaaring hindi ipatupad ng ilang apps ng alarm clock ang tampok na ito."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"alisin ang mga voicemail"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Pinapayagan ang app na mag-alis ng mga mensahe mula sa iyong inbox ng voicemail."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"pamahalaan ang mga voicemail"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Pinapayagan ang app na magbago at mag-alis ng mga mensahe mula sa iyong inbox ng voicemail."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"magdagdag ng voicemail"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Pinapayagan ang app na magdagdag ng mga mensahe sa iyong inbox ng voicemail."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"basahin ang lahat ng voicemail"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"I-ON"</string>
<string name="capital_off" msgid="6815870386972805832">"I-OFF"</string>
<string name="whichApplication" msgid="4533185947064773386">"Kumpletuhin ang pagkilos gamit ang"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Pumili ng home app"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Gamitin bilang default para sa pagkilos na ito."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"I-clear ang default sa mga setting ng System > Apps > Na-download."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Palaging Payagan"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Huwag kailanman Payagan"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Naalis ang SIM card"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Hindi magiging available ang mobile network hanggang mag-restart ka gamit ang isang may-bisang SIM card"</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Tapos na"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Idinagdag ang SIM card"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"I-restart ang iyong device upang ma-access ang mobile network."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"I-restart"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Magtakda ng oras"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Itakda ang petsa"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Napili ang <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Tinanggal ang <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Ikaw ay nasa Lock-to-App mode."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Gagamitin ang lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Nila-lock ng Lock-to-app ang display sa iisang app.\n\nUpang lumabas pindutin nang matagal ang button ng mga kamakailang app $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"HINDI"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"SIMULAN"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Simulan ang Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Lumabas sa Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index a1adcc3..b9a8ca0 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Uygulamaya, telefonunuzdaki veya SIM kartınızdaki SMS mesajlarına yazma izni verir. Kötü amaçlı uygulamalar mesajlarınızı silebilir."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"kısa mesajları (WAP) al"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Uygulamaya WAP mesajlarını alma ve işleme izni verir. Buna, size gönderilen mesajları takip edip size göstermeden silebilme izni de dahildir."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"Bluetooth iletilerini al (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Uygulamanın Bluetooth MAP iletilerini alıp işlemesine izin verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri izleyebileceği veya size göstermeden silebileceği anlamına gelir."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"çalışan uygulamaları al"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Uygulamaya o anda ve son çalışan görevler hakkında bilgi alma izni verir. Bu izin, uygulamanın cihaz tarafından kullanılan uygulamalar hakkında bilgi elde etmesine olanak sağlayabilir."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"kullanıcılar arasında etkileşim kurma"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"test için sahte konum kaynakları"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Test amacıyla veya yeni bir konum sağlayıcı yüklemek için sahte konum kaynakları oluşturma. Bu izin, uygulamanın GPS veya konum sağlayıcıları gibi diğer konum kaynakları tarafından döndürülen konum ve/veya durum bilgisini geçersiz kılmasına olanak sağlar."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ek konum sağlayıcı komutlarına eriş"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Uygulamaya ekstra konum sağlayıcı komutlarına erişim izni verir. Bu izin, uygulamanın GPS veya diğer konum kaynaklarının çalışmasına müdahale etmesine olanak sağlayabilir."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Uygulamanın, ekstra konum sağlayıcı komutlarına erişmesine izin verir. Bu izin, uygulamanın GPS veya diğer konum kaynaklarının çalışmasını kesmesine olanak sağlayabilir."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"konum sağlayıcı yükleme izni"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Test amacıyla veya yeni bir konum sağlayıcı yüklemek için sahte konum kaynakları oluşturma. Bu izin, uygulamanın GPS veya konum sağlayıcıları gibi diğer konum kaynakları tarafından döndürülen konum ve/veya durum bilgisini geçersiz kılmasına olanak sağlar."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"hassas konum (GPS ve ağ tabanlı)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Uygulamaya, ağ politikalarını yönetme ve uygulamaya özgü kuralları tanımlama izni verir."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"ağ kullanım hesaplamasını değiştir"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Uygulamaya, ağın uygulamalara göre nasıl kullanılacağını değiştirme izni verir. Normal uygulamalar tarafından kullanılmak için değildir."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"yuva işaretlerini değiştir"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Uygulamaya, yönlendirme için yuva işaretlerini değiştirme izni verir"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"bildirimlere eriş"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Uygulamanın bildirimler almasına, bildirimleri incelemesine ve temizlemesine izin verir. Buna diğer uygulamalar tarafından yayınlanan bildirimler de dahildir."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bildirim dinleyici hizmetine bağlan"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"İzin sahibine bir bildirim dinleyici hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bir durum sağlayıcı hizmetine bağlanma"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"İzin sahibinin, bir durum sağlayıcı hizmete ait üst düzey arayüze bağlanmasına izin verir. Normal uygulamalar için hiçbir zaman gerekli değildir."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"bir dream hizmetine bağla"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"İzin sahibine bir dream hizmetinin üst seviye arayüzüne bağlanma olanağı sunar. Normal uygulamalarda hiçbir zaman ihtiyaç duyulmamalıdır."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"operatör tarafından sağlanan yapılandırma uygulamasını çalıştır"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Uygulamaya, dokunmatik ekranın kalibrasyon parametrelerini değiştirme izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM sertifikalarına eriş"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Bir uygulamanın DRM sertifikaları için temel hazırlık yapmasına ve bunları kullanmasına izin verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Devir aktarımı yayınlarını al."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Devir aktarımı durum bilgilerini almaya izin verir."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Android Beam aktarım durumunu al"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Bu uygulamanın mevcut Android Beam aktarımlarıyla ilgili bilgi almasına izin verir"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri denetleme."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Uygulamaya Tarayıcı geçmişini ve telefonunuzda depolanan yer işaretlerini değiştirme izni verir. Bu izin, uygulamanın Tarayıcı geçmişini silmesine ve değiştirmesine olanak sağlar. Not: Bu izin, üçüncü taraf cihazlar veya Web\'e göz atma işlevine sahip diğer uygulamalar tarafından kullanılmayabilir."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"alarm ayarla"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Uygulamaya, çalar saat uygulamasının alarmını ayarlama izni verir. Bazı çalar saat uygulamaları bu özelliği uygulayamayabilir."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"sesli mesajları kaldır"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Uygulamaya, sesli mesaj gelen kutunuzdaki mesajları kaldırma izni verir."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"sesli mesajları yönet"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Uygulamanın sesli mesaj gelen kutunuzdaki mesajları değiştirmesine ve kaldırmasına izin verir."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"sesli mesaj ekle"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Uygulamaya, sesli mesaj gelen kutunuza mesaj ekleme izni verir."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"tüm sesli mesajları oku"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"AÇIK"</string>
<string name="capital_off" msgid="6815870386972805832">"KAPALI"</string>
<string name="whichApplication" msgid="4533185947064773386">"İşlemi şunu kullanarak tamamla"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Ana ekran uygulaması seçin"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Varsayılan olarak bu işlem için kullan."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Sistem ayarları > Uygulamalar > İndirilen bölümünden varsayılanı temizleyin."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Her Zaman İzin Ver"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Asla İzin Verme"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM kart çıkarıldı"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Geçerli bir SIM kart yerleştirilmiş olarak yeniden başlatana kadar mobil ağ kullanılamayacak."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Tamamlandı"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM kart eklendi"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Mobil ağa erişmek için cihazınızı yeniden başlatın."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Yeniden başlat"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Saati ayarlayın"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarlayın"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seçildi"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> silindi"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (İş)"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Uygulamaya kilitleme özelliği kullanılsın mı?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Uygulamaya kilitleme özelliği, ekranı tek bir uygulamaya kilitler.\n\nÇıkmak için son uygulamalar düğmesine ($) uzun basın"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"HAYIR"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Uygulamaya Kilitleme modundasınız."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Uygulamaya Kilitleme özelliği kullanılsın mı?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"BAŞLAT"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Uygulamaya kilitleme özelliğini başlat"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Uygulamaya kilitleme özelliğinden çık"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 542a04d..9ac45ee 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Дозволяє програмі писати в SMS повідомлення, збережені в телефоні чи на SIM-карті. Шкідливі програми можуть видаляти ваші повідомлення."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"отримувати текстові повідомлення (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Дозволяє програмі отримувати й обробляти WAP-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"отримувати повідомлення Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Дозволяє додаткові отримувати й обробляти повідомлення Bluetooth MAP. Це означає, що додаток може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"отримувати запущені програми"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Дозволяє програмі отримувати інформацію про поточні й останні запущені завдання. Це може дозволити програмі виявляти інформацію про програми, які використовуються на пристрої."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"взаємодіяти між користувачами"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"фіктивні джер. місцезн. для тестув."</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Створювати фіктивні джерела місцезнаходження для тестування або встановлювати нового постачальника даних місцезнаходження. Це може дозволити програмі замінювати місцезнаходження та/чи статус, отриманий від інших джерел даних про місцезнаходження, як-от постачальників послуг GPS або постачальників даних місцезнаходження."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"отр. дост. до додат. команд пров. місцезн."</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Дозволяє програмі отримувати доступ до додаткових команд постачальника даних місцезнаходження. Це може дати програмі змогу втручатися в роботу GPS чи інших джерел даних про місцезнаходження."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Додаток отримуватиме доступ до додаткових команд постачальника геоданих. Можливе втручання додатка в роботу GPS чи інших джерел геоданих."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"дозвіл на встановлення провайдера місцезнах."</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Створювати фіктивні джерела місцезнаходження для тестування або встановлювати нового постачальника даних місцезнаходження. Це може дозволити програмі замінювати місцезнаходження та/чи статус, отриманий від інших джерел даних про місцезнаходження, як-от постачальників послуг GPS або постачальників даних місцезнаходження."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"точне місцезнаходження (на основі GPS і мережі)"</string>
@@ -599,7 +597,7 @@
<string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"читати точні статуси телефону"</string>
<string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Дозволяє додатку отримувати доступ до статусів телефону. Цей дозвіл дає додатку змогу визначати статус виклику (активний чи у фоновому режимі), помилки викликів, точний статус передавання даних і помилки передавання даних."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"не доп.перехід пристр.в реж.сну"</string>
- <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"недоп. перехід тел. в реж. сну"</string>
+ <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"Вимкнення режиму сну"</string>
<string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Дозволяє програмі не допускати перехід планшетного ПК у режим сну."</string>
<string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Дозволяє програмі не допускати перехід телефону в режим сну."</string>
<string name="permlab_transmitIr" msgid="7545858504238530105">"передавати в інфрачервоному діапазоні"</string>
@@ -679,7 +677,7 @@
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Дозволяє програмі читати налаштування синхронізації для облікового запису, наприклад, визначати, чи програма Люди синхронізується з обліковим записом."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"вмикати й вимикати синхронізацію"</string>
<string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Дозволяє програмі змінювати налаштування синхронізації для облікового запису, наприклад, вмикати синхронізацію програми Люди з обліковим записом."</string>
- <string name="permlab_readSyncStats" msgid="7396577451360202448">"читати стат-ку синхрон."</string>
+ <string name="permlab_readSyncStats" msgid="7396577451360202448">"Перегляд статистики синхронізації"</string>
<string name="permdesc_readSyncStats" msgid="1510143761757606156">"Дозволяє програмі читати статистику синхронізації облікового запису, зокрема історію синхронізацій і обсяг синхронізованих даних."</string>
<string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"читати підписані канали"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Дозволяє програмі отримувати відомості про поточно синхронізовані канали."</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Дозволяє програмі керувати політикою мережі та визначити спеціальні правила для програм."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"змінювати облік використання мережі"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Дозволяє програмі змінювати метод підрахунку того, як програми використовують мережу. Не для використання звичайними програмами."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"змінювати мітки сокетів"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Дозволяє програмі змінювати мітки сокетів для маршрутизації"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"отримувати доступ до сповіщень"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозволяє програмі отримувати, перевіряти й очищати сповіщення, зокрема опубліковані іншими програмами."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"прив’язуватися до служби читання сповіщень"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Дозволяє власнику прив’язуватися до інтерфейсу верхнього рівня служби читання сповіщень. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"підключитися до служби постачання умов"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Додаток зможе підключатися до інтерфейсу верхнього рівня служби постачання умов. Звичайні додатки ніколи не використовують цей дозвіл."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"підключатися до служби передавання медіафайлів"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Додаток зможе підключатися до інтерфейсу верхнього рівня служби передавання медіафайлів. Звичайні додатки ніколи не використовують цей дозвіл."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"підключення до служби заставок"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Додаток зможе підключатися до інтерфейсу верхнього рівня служби заставок. Звичайні додатки ніколи не використовують цей дозвіл."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"викликати надану оператором програму конфігурації"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Програма може змінювати параметри калібрування сенсорного екрана. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"отримувати доступ до сертифікатів DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Дозволяє додатку надавати та використовувати сертифікати DRM. Ніколи не застосовується для звичайних додатків."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Отримувати широкомовні повідомлення про передавання даних."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Отримання інформації про стан передавання даних."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Отримувати інформацію про стан функції Передавання даних Android."</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Додаток може отримувати інформацію про поточне передавання даних за допомогою функції Передавання даних Android"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролювати довжину паролів для розблокування екрана та дозволені в них символи."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
@@ -1008,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Дозволяє програмі змінювати історію чи закладки веб-переглядача, збережені у вашому телефоні. Це може дозволити програмі стирати чи змінювати дані веб-переглядача. Зауважте: цей дозвіл не може застосовуватися веб-переглядачами третіх сторін або іншими програмами з можливостями веб-перегляду."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"установлювати будильник"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Дозволяє програмі налаштовувати сигнал у встановленій програмі будильника. У деяких програмах будильника ця функція може не застосовуватися."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"видаляти голосові повідомлення"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Додаток може видаляти голосові повідомлення з папки \"Вхідні\"."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"керувати голосовою поштою"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Додаток може змінювати голосові повідомлення та видаляти їх із папки \"Вхідні\"."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"додавати голосову пошту"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Дозволяє програмі додавати повідомлення в папку \"Вхідні\" голосової пошти."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"читати всі голосові повідомлення"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"УВІМК"</string>
<string name="capital_off" msgid="6815870386972805832">"ВИМК"</string>
<string name="whichApplication" msgid="4533185947064773386">"Завершити дію за доп."</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"Завершити дію за допомогою %1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Відкрити за допомогою"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Відкрити за допомогою %1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Редагувати за допомогою"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Редагувати за допомогою %1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Надіслати через"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Надіслати через %1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Виберіть програму"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Використ. за умовч. для цієї дії."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Очистити налаштування за умовчанням у меню Налаштування системи > Програми > Завантажені."</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Завжди дозволяти"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ніколи не дозволяти"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM-карту вилучено"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Мобільна мережа буде недоступна, поки ви не здійсните перезапуск, вставивши дійсну SIM-карту."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"Мобільна мережа стане доступною, лише коли ви перезавантажите пристрій і вставите дійсну SIM-карту."</string>
<string name="sim_done_button" msgid="827949989369963775">"Готово"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM-карту додано"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Перезапустіть пристрій, щоб отримати доступ до мобільної мережі."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Щоб з’єднатися з мобільною мережею, перезавантажте пристрій."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Перезапуск"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Установити час"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Установити дату"</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Вибрано: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> видалено"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Робоча <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Увімкнено режим \"Блокування в додатку\"."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Використовувати блокування в додатку?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Блокування в додатку блокує дисплей у певному додатку.\n\nЩоб вимкнути, натисніть і втримуйте кнопку останніх додатків ($)"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"НІ"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"УВІМКНУТИ"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Увімкнути блокування в додатку"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Вимкнути блокування в додатку"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 0195af3..61fac36 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Cho phép ứng dụng ghi vào tin nhắn SMS được lưu trữ trên điện thoại hoặc thẻ SIM của bạn. Ứng dụng độc hại có thể xóa tin nhắn của bạn."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"nhận tin nhắn văn bản (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Cho phép ứng dụng nhận và xử lý tin nhắn WAP. Quyền này bao gồm khả năng giám sát hoặc xóa tin nhắn được gửi cho bạn mà không hiển thị chúng cho bạn."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"nhận tin nhắn qua Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Cho phép ứng dụng nhận và xử lý tin nhắn MAP qua Bluetooth. Điều này có nghĩa là ứng dụng có thể giám sát hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"truy xuất các ứng dụng đang chạy"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Cho phép ứng dụng truy xuất thông tin về các công việc đã và đang chạy gần đây. Việc này có thể cho phép ứng dụng phát hiện thông tin về những ứng dụng nào đã được sử dụng trên thiết bị."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"tương tác giữa người dùng"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"các nguồn vị trí mô phỏng cho thử nghiệm"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Tạo nguồn vị trí mô phỏng cho thử nghiệm hoặc cài đặt nhà cung cấp vị trí mới. Việc này cho phép ứng dụng ghi đè vị trí và/hoặc trạng thái được trả về bởi các nguồn vị trí khác như GPS hoặc nhà cung cấp vị trí."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"truy cập vào các lệnh của nhà cung cấp vị trí bổ sung"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Cho phép ứng dụng truy cập vào các lệnh của nhà cung cấp vị trí bổ sung. Việc này có thể cho phép ứng dụng can thiệp vào quá trình vận hành của GPS hoặc các nguồn vị trí khác."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Cho phép ứng dụng truy cập vào các lệnh của nhà cung cấp vị trí bổ sung. Điều này có thể cho phép ứng dụng can thiệp vào hoạt động của Hệ thống định vị toàn cầu (GPS) hoặc các nguồn vị trí khác."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"quyền cài đặt nhà cung cấp vị trí"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Tạo nguồn vị trí mô phỏng cho thử nghiệm hoặc cài đặt nhà cung cấp vị trí mới. Việc này cho phép ứng dụng ghi đè vị trí và/hoặc trạng thái được trả về bởi các nguồn vị trí khác như GPS hoặc nhà cung cấp vị trí."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"vị trí chính xác (dựa vào mạng và GPS)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Cho phép ứng dụng quản lý chính sách mạng và xác định quy tắc dành riêng cho ứng dụng."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"sửa đổi hạch toán sử dụng mạng"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Cho phép ứng dụng sửa đổi cách tính mức sử dụng mạng so với ứng dụng. Không dành cho các ứng dụng thông thường."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"sửa đổi nhãn ổ cắm"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Cho phép ứng dụng sửa đổi nhãn ổ cắm để định tuyến"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"truy cập thông báo"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Cho phép ứng dụng truy xuất, kiểm tra và xóa thông báo, bao gồm những thông báo được đăng bởi các ứng dụng khác."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"liên kết với dịch vụ trình xử lý thông báo"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ trình xử lý thông báo. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"liên kết với dịch vụ trình cung cấp điều kiện"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ trình cung cấp điều kiện. Không cần thiết cho các ứng dụng thông thường."</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"liên kết với dịch vụ dream"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ dream. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gọi ra ứng dụng cấu hình do nhà cung cấp dịch vụ cung cấp"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Cho phép ứng dụng sửa đổi các thông số hiệu chỉnh của màn hình cảm ứng. Không cần cho ứng dụng thông thường."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"truy cập chứng chỉ DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Cho phép ứng dụng cung cấp và sử dụng chứng chỉ DRM. Không cần thiết cho các ứng dụng thông thường."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Nhận truyền phát chuyển giao."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Cho phép nhận thông tin trạng thái chuyển giao."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Nhận trạng thái chuyển của Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Cho phép ứng dụng này nhận thông tin về các lần chuyển hiện tại của Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kiểm soát độ dài và ký tự được phép trong mật khẩu mở khóa màn hình."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -879,12 +879,12 @@
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Nhập mật khẩu để mở khóa"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Nhập mã PIN để mở khóa"</string>
<string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Mã PIN không chính xác."</string>
- <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khóa, hãy nhấn vào Trình đơn sau đó nhấn 0."</string>
+ <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khóa, hãy nhấn vào Menu sau đó nhấn 0."</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Số khẩn cấp"</string>
<string name="lockscreen_carrier_default" msgid="8963839242565653192">"Không có dịch vụ nào."</string>
<string name="lockscreen_screen_locked" msgid="7288443074806832904">"Màn hình đã khóa."</string>
- <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Nhấn vào Trình đơn để mở khóa hoặc thực hiện cuộc gọi khẩn cấp."</string>
- <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Nhấn vào Trình đơn để mở khóa."</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Nhấn vào Menu để mở khóa hoặc thực hiện cuộc gọi khẩn cấp."</string>
+ <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Nhấn vào Menu để mở khóa."</string>
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Vẽ hình để mở khóa"</string>
<string name="lockscreen_emergency_call" msgid="5347633784401285225">"Cuộc gọi khẩn cấp"</string>
<string name="lockscreen_return_to_call" msgid="5244259785500040021">"Quay lại cuộc gọi"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Cho phép ứng dụng sửa đổi lịch sử hoặc dấu trang của Trình duyệt được lưu trữ trên điện thoại của bạn. Việc này có thể cho phép ứng dụng xóa hoặc sửa đổi dữ liệu của Trình duyệt. Lưu ý: quyền này có thể không được thực thi bởi các trình duyệt của bên thứ ba hoặc các ứng dụng khác có khả năng duyệt web."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"đặt báo thức"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Cho phép ứng dụng đặt báo thức trong ứng dụng đồng hồ báo thức được cài đặt. Một số ứng dụng đồng hồ báo thức có thể không thực thi tính năng này."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"xóa thư thoại"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Cho phép ứng dụng xóa thông báo khỏi hộp thư thoại đến của bạn."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"quản lý thư thoại"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Cho phép ứng dụng sửa đổi và xóa thư khỏi hộp thư thoại đến của bạn."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"thêm thư thoại"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Cho phép ứng dụng thêm thông báo vào hộp thư thoại đến của bạn."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"đọc tất cả các thư thoại"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"BẬT"</string>
<string name="capital_off" msgid="6815870386972805832">"TẮT"</string>
<string name="whichApplication" msgid="4533185947064773386">"Hoàn tất tác vụ đang sử dụng"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"Chọn ứng dụng gia đình"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Sử dụng theo mặc định đối với tác vụ này."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Xóa mặc định trong Cài đặt hệ thống > Ứng dụng > Đã tải xuống."</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Luôn cho phép"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Không bao giờ cho phép"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Đã xóa thẻ SIM"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Mạng di động sẽ không khả dụng cho đến khi bạn khởi động lại với thẻ SIM hợp lệ được lắp."</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"Xong"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Đã thêm thẻ SIM"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Khởi động lại thiết bị của bạn để truy cập mạng di động."</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"Khởi động lại"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Đặt giờ"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Đặt ngày"</string>
@@ -1375,7 +1391,7 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"Cho phép ứng dụng quan sát các thay đổi ở trạng thái đáng tin cậy."</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Cung cấp tác nhân đáng tin cậy."</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Cho phép ứng dụng cung cấp tác nhân đáng tin cậy."</string>
- <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Khởi chạy trình đơn cài đặt của đại lý tin cậy."</string>
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Khởi chạy menu cài đặt của đại lý tin cậy."</string>
<string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"Cho phép ứng dụng khởi chạy hoạt động thay đổi hoạt động của đại lý tin cậy."</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Liên kết với một dịch vụ của đại lý đáng tin cậy"</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Cho phép ứng dụng liên kết với một dịch vụ của đại lý đáng tin cậy."</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"Đã chọn <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"Đã xóa <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> làm việc"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"Sử dụng lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app sẽ khóa màn hình trong một ứng dụng.\n\nĐể thoát, nhấn và giữ nút ứng dụng gần đây $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"KHÔNG"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Bạn đang ở chế độ Khóa trong ứng dụng."</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"Sử dụng Khóa trong ứng dụng?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"BẮT ĐẦU"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Bắt đầu Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Thoát Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 5d8e8c6..83da692 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -241,7 +241,7 @@
<string name="permgroupdesc_accounts" msgid="4948732641827091312">"访问可用的帐户。"</string>
<string name="permgrouplab_hardwareControls" msgid="7998214968791599326">"硬件控制"</string>
<string name="permgroupdesc_hardwareControls" msgid="4357057861225462702">"直接访问手机上的硬件。"</string>
- <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"手机通话"</string>
+ <string name="permgrouplab_phoneCalls" msgid="9067173988325865923">"电话"</string>
<string name="permgroupdesc_phoneCalls" msgid="7489701620446183770">"监管、记录和处理电话呼叫。"</string>
<string name="permgrouplab_systemTools" msgid="4652191644082714048">"系统工具"</string>
<string name="permgroupdesc_systemTools" msgid="8162102602190734305">"对系统进行低级访问和控制。"</string>
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"允许应用对手机或 SIM 卡上存储的短信执行写入操作。恶意应用可能会删除您的短信。"</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"接收讯息 (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"允许该应用接收和处理 WAP 消息。此权限包括监视发送给您的消息或删除发送给您的消息而不向您显示的功能。"</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"接收蓝牙信息(MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"允许此应用接收和处理蓝牙MAP信息。这意味着,该应用可能会监视发送或到您设备的信息,在您阅读发送到您设备的信息之前擅自删除信息。"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"检索正在运行的应用"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"允许该应用检索近期运行的和当前正在运行的任务的相关信息。此权限可让该应用了解设备上使用了哪些应用。"</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"用户间互动"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"使用模拟地点来源进行测试"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"创建用于测试的模拟位置源或安装新的位置提供程序。此权限可让该应用覆盖由其他位置源(如 GPS)或位置提供程序返回的位置和/或状态信息。"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"获取额外的位置信息提供程序命令"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"允许该应用访问额外的位置提供程序命令。此权限可让该应用干扰 GPS 或其他位置源的运行。"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"允许该应用使用其他的位置信息提供程序命令。此权限使该应用可以干扰GPS或其他位置信息源的运作。"</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"允许安装位置信息提供程序"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"创建用于测试的模拟位置源或安装新的位置提供程序。此权限可让该应用覆盖由其他位置源(如 GPS)或位置提供程序返回的位置和/或状态信息。"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"精确位置(基于 GPS 和网络)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"允许应用管理网络政策和定义专门针对应用的规则。"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"修改网络使用情况记录方式"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"允许该应用修改对于各应用的网络使用情况的统计方式。普通应用不应使用此权限。"</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"修改套接字标记"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"允许应用修改用于路由的套接字标记"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"访问通知"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"允许该应用检索、检查并清除通知,包括其他应用发布的通知。"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"绑定到通知侦听器服务"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允许应用绑定到通知侦听器服务的顶级接口(普通应用绝不需要此权限)。"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"绑定到条件提供程序服务"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允许应用绑定到条件提供程序服务的顶级接口。普通应用绝不需要此权限。"</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"绑定到互动屏保服务"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"允许应用绑定到互动屏保服务的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"调用运营商提供的配置应用"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"允许应用修改触摸屏的校准参数。普通应用绝不需要此权限。"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"访问DRM证书"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"允许应用配置和使用DRM证书。普通应用绝不需要此权限。"</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"接收交接传输广播"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"允许接收交接传输状态信息。"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"接收Android Beam的传输状态"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"允许此应用接收Android Beam当前传输内容的相关信息"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解锁密码所允许的长度和字符。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"允许该应用修改您手机上存储的浏览器历史记录或浏览器书签。此权限可让该应用清除或修改浏览器数据。请注意:此权限可能不适用于第三方浏览器或具备网页浏览功能的其他应用。"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"设置闹钟"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"允许应用在已安装的闹钟应用中设置闹钟。有些闹钟应用可能无法实现此功能。"</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"移除语音邮件"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"允许应用移除您语音信箱中的邮件。"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"管理语音信箱"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"允许应用修改和移除您语音信箱中的语音邮件。"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"添加语音邮件"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"允许应用向您的语音信箱收件箱添加邮件。"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"读取所有语音邮件"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"开启"</string>
<string name="capital_off" msgid="6815870386972805832">"关闭"</string>
<string name="whichApplication" msgid="4533185947064773386">"选择要使用的应用:"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"选择主屏幕应用"</string>
<string name="alwaysUse" msgid="4583018368000610438">"设为默认选项。"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"在“系统设置”>“应用”>“已下载”中清除默认设置。"</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"始终允许"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"永不允许"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"已移除 SIM 卡"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"移动网络不可用。请插入有效的 SIM 卡并重新启动。"</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"完成"</string>
<string name="sim_added_title" msgid="3719670512889674693">"已添加 SIM 卡"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"请重新启动您的设备,以便访问移动网络。"</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"重新启动"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"设置时间"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"设置日期"</string>
@@ -1375,10 +1391,8 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"允许应用检测信任状态的变化。"</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"提供信任的代理。"</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"允许应用提供信任的代理。"</string>
- <!-- no translation found for permlab_launch_trust_agent_settings (5859430082240410200) -->
- <skip />
- <!-- no translation found for permdesc_launch_trust_agent_settings (8185142708644913381) -->
- <skip />
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"启动信任的代理设置菜单。"</string>
+ <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"允许应用启动可变更信任的代理行为的活动。"</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"绑定至信任的代理服务"</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允许应用绑定至信任的代理服务。"</string>
<string name="permlab_recovery" msgid="3157024487744125846">"与更新和恢复系统互动"</string>
@@ -1739,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"已选择<xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"已删除<xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"工作<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"您目前处于单应用模式。"</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"要使用“单应用模式”吗?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"“单应用模式”功能会锁定屏幕,使其只显示一个应用。\n\n要退出,请按住“最近用过的应用”按钮 $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"算了"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"启动"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"启动单应用模式"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"退出单应用模式"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 762920c..ba9f22c 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -157,7 +157,7 @@
<string name="silent_mode" msgid="7167703389802618663">"靜音模式"</string>
<string name="turn_on_radio" msgid="3912793092339962371">"開啟無線網絡"</string>
<string name="turn_off_radio" msgid="8198784949987062346">"關閉無線網絡"</string>
- <string name="screen_lock" msgid="799094655496098153">"屏幕鎖定"</string>
+ <string name="screen_lock" msgid="799094655496098153">"螢幕鎖定"</string>
<string name="power_off" msgid="4266614107412865048">"關閉"</string>
<string name="silent_mode_silent" msgid="319298163018473078">"鈴聲關閉"</string>
<string name="silent_mode_vibrate" msgid="7072043388581551395">"鈴聲震動"</string>
@@ -173,7 +173,7 @@
<string name="no_recent_tasks" msgid="8794906658732193473">"沒有最近用過的應用程式。"</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"平板電腦選項"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"手機選項"</string>
- <string name="global_action_lock" msgid="2844945191792119712">"屏幕鎖定"</string>
+ <string name="global_action_lock" msgid="2844945191792119712">"螢幕鎖定"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"關閉"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"錯誤報告"</string>
<string name="bugreport_title" msgid="2667494803742548533">"取得錯誤報告"</string>
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"允許應用程式寫入手機或 SIM 卡中儲存的短訊。惡意應用程式可能會藉此刪除您的訊息。"</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"接收短訊 (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"允許應用程式接收和處理 WAP 訊息。這項權限也能讓應用程式監控訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"接收藍牙訊息 (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"允許應用程式接收和處理藍牙 MAP 訊息。這項設定可讓應用程式監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"擷取執行中的應用程式"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"允許應用程式擷取有關目前和最近執行的工作的資訊。如此一來,應用程式或可找出裝置上所使用應用程式的相關資訊。"</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"與其他用戶互動"</string>
@@ -316,8 +314,8 @@
<string name="permdesc_manageActivityStacks" msgid="1615881933034084440">"允許應用程式新增、移除及修改可供其他應用程式在其中執行的活動堆疊。惡意應用程式可能會干擾其他應用程式的行為。"</string>
<string name="permlab_startAnyActivity" msgid="2918768238045206456">"啟動任何活動"</string>
<string name="permdesc_startAnyActivity" msgid="997823695343584001">"允許應用程式不論權限保護或匯出狀態皆可啟動任何活動。"</string>
- <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"設定屏幕兼容性"</string>
- <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"允許應用程式控制其他應用程式的屏幕兼容模式。惡意應用程式可能藉此破壞其他應用程式的正常運作。"</string>
+ <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"設定螢幕兼容性"</string>
+ <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"允許應用程式控制其他應用程式的螢幕兼容模式。惡意應用程式可能藉此破壞其他應用程式的正常運作。"</string>
<string name="permlab_setDebugApp" msgid="3022107198686584052">"啟用應用程式偵錯"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"允許應用程式為其他程式開啟偵錯功能。惡意應用程式可能會藉此終止其他應用程式。"</string>
<string name="permlab_changeConfiguration" msgid="4162092185124234480">"更改系統顯示設定"</string>
@@ -347,7 +345,7 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"防止用戶切換至其他應用程式。"</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"取得目前的應用程式資訊"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"允許應用程式從目前屏幕前景的應用程式擷取私人資訊。"</string>
+ <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"允許應用程式從目前螢幕前景的應用程式擷取私人資訊。"</string>
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"監視及控制所有應用程式的啟動程序"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"允許應用程式監視和控制系統啟動活動的方式。惡意應用程式可能會藉此破壞整個系統。這個權限只有開發人員才需要,一般使用上不需使用這個權限。"</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"傳送套件已移除廣播"</string>
@@ -380,8 +378,8 @@
<string name="permdesc_setAnimationScale" msgid="7690063428924343571">"允許應用程式隨時更改全域的動畫速度 (更快或更慢)。"</string>
<string name="permlab_manageAppTokens" msgid="1286505717050121370">"管理應用程式憑證"</string>
<string name="permdesc_manageAppTokens" msgid="8043431713014395671">"允許應用程序略過一般程序,直接建立和管理本身的憑證 (不建議一般應用程式使用)。"</string>
- <string name="permlab_freezeScreen" msgid="4708181184441880175">"鎖定屏幕"</string>
- <string name="permdesc_freezeScreen" msgid="8558923789222670064">"允許應用程式暫時鎖定屏幕畫面,顯示全屏幕轉場效果。"</string>
+ <string name="permlab_freezeScreen" msgid="4708181184441880175">"鎖定螢幕"</string>
+ <string name="permdesc_freezeScreen" msgid="8558923789222670064">"允許應用程式暫時鎖定螢幕畫面,顯示全螢幕轉場效果。"</string>
<string name="permlab_injectEvents" msgid="1378746584023586600">"按鍵及控制按鈕"</string>
<string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"允許應用程式將本身的輸入操作 (按鍵等) 發送給其他應用程式。惡意應用程式可能會藉此操控平板電腦。"</string>
<string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"允許應用程式將本身的輸入操作 (按鍵等) 發送給其他應用程式。惡意應用程式可能會藉此操控手機。"</string>
@@ -419,8 +417,8 @@
<string name="permdesc_bindTvInput" msgid="2371008331852001924">"允許應用程式繫結至電視訊號輸入裝置的頂層介面,但一般應用程式並不需要使用。"</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"新增或移除裝置管理員"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允許應用程式新增或移除有效的裝置管理員 (不建議一般應用程式使用)。"</string>
- <string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕瀏覽方向"</string>
- <string name="permdesc_setOrientation" msgid="3046126619316671476">"允許應用程式隨時更改屏幕定向 (不建議一般應用程式使用)。"</string>
+ <string name="permlab_setOrientation" msgid="3365947717163866844">"更改螢幕瀏覽方向"</string>
+ <string name="permdesc_setOrientation" msgid="3046126619316671476">"允許應用程式隨時更改螢幕定向 (不建議一般應用程式使用)。"</string>
<string name="permlab_setPointerSpeed" msgid="9175371613322562934">"變更指標速度"</string>
<string name="permdesc_setPointerSpeed" msgid="6866563234274104233">"允許應用程式隨時更改滑鼠或觸控板游標的移動速度 (不建議一般應用程式使用)。"</string>
<string name="permlab_setKeyboardLayout" msgid="4778731703600909340">"更改鍵盤配置"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"用於測試的模擬位置源"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供程式。這項權限允許應用程式覆寫 GPS 或位置資訊提供程式等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"接收額外的位置提供者指令"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"允許應用程式存取額外位置資訊提供程式指令。如此一來,應用程式或可干擾 GPS 或其他位置資訊來源的運作。"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"允許應用程式存取額外的位置提供者指令。這項設定可能會使應用程式干擾 GPS 或其他位置來源的運作。"</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"允許安裝位置提供程式"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供程式。這項權限允許應用程式覆寫 GPS 或位置資訊提供程式等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"精確位置 (以 GPS 和網絡為基準)"</string>
@@ -643,7 +641,7 @@
<string name="permdesc_writeApnSettings" msgid="5333798886412714193">"允許應用程式更改網絡設定,並且攔截和檢查所有網絡流量,例如更改任何 APN 的 Proxy 及通訊埠。惡意應用程式可能會在您不知情的情況下,監視、重新導向或修改網絡封包。"</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"更改網絡連線"</string>
<string name="permdesc_changeNetworkState" msgid="6789123912476416214">"允許應用程式更改網絡連線狀態。"</string>
- <string name="permlab_changeTetherState" msgid="5952584964373017960">"更改網絡共用設定"</string>
+ <string name="permlab_changeTetherState" msgid="5952584964373017960">"變更網絡共享設定"</string>
<string name="permdesc_changeTetherState" msgid="1524441344412319780">"允許應用程式更改已共用網絡的連線狀態。"</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"更改背景資料使用設定"</string>
<string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"允許應用程式更改背景數據用量設定。"</string>
@@ -673,7 +671,7 @@
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"允許應用程式查看手機的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
<string name="permlab_nfc" msgid="4423351274757876953">"控制近距離無線通訊"</string>
<string name="permdesc_nfc" msgid="7120611819401789907">"允許應用程式使用近距離無線通訊 (NFC) 標記、卡片及讀取程式進行通訊。"</string>
- <string name="permlab_disableKeyguard" msgid="3598496301486439258">"停用屏幕上鎖"</string>
+ <string name="permlab_disableKeyguard" msgid="3598496301486439258">"停用螢幕上鎖"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全措施。例如:手機收到來電時停用按鍵鎖定,通話結束後重新啟用按鍵鎖定。"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允許應用程式讀取帳戶的同步設定,例如確定「通訊錄」應用程式是否和某個帳戶保持同步。"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"允許應用程式管理網絡政策並定義應用程式專用規則。"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"修改網絡使用量計算方式"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"允許應用程式修改應用程式網絡使用量的計算方式 (不建議一般應用程式使用)。"</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"修改通訊端標記"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"允許應用程式修改路由的通訊端標記"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"存取通知"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"允許應用程式擷取、檢查及清除通知 (包括由其他應用程式發佈的通知)。"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"繫結至通知接聽器服務"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允許應用程式繫結至通知接聽器服務的頂層介面 (不建議一般應用程式使用)。"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"繫結至條件供應商服務"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允許應用程式繫結至條件供應商服務的頂層介面,但一般應用程式並不需要使用。"</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"繫結至 Dream 服務"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"允許應用程式繫結至 Dream 服務的頂層介面 (不建議一般應用程式使用)。"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"調用流動網絡供應商提供的設定應用程式"</string>
@@ -733,24 +733,24 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"允許應用程式修改觸控式螢幕的校正參數,而一般應用程式並不需要作出類似修改。"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"存取 DRM 憑證"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"允許應用程式準備和使用 DRM 憑證,但一般應用程式並不需要使用。"</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"接收交遞傳輸廣播。"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"允許接收交遞傳輸狀態資訊。"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"接收 Android Beam 的傳送狀態"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"允許應用程式接收 Android Beam 目前傳送的資料"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
- <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解鎖密碼所允許的長度和字元。"</string>
- <string name="policylab_watchLogin" msgid="914130646942199503">"監控屏幕解鎖嘗試次數"</string>
- <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"監視為屏幕解鎖時輸入錯誤密碼的次數;如果輸入錯誤密碼的次數過多,則會鎖定平板電腦或清除平板電腦的所有資料。"</string>
- <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"監視為屏幕解鎖時輸入錯誤密碼的次數,如果輸入錯誤密碼的次數過多,則會鎖定手機或清除手機的所有資料。"</string>
- <string name="policylab_resetPassword" msgid="2620077191242688955">"更改屏幕解鎖密碼"</string>
- <string name="policydesc_resetPassword" msgid="605963962301904458">"更改屏幕解鎖密碼。"</string>
- <string name="policylab_forceLock" msgid="2274085384704248431">"鎖定屏幕"</string>
- <string name="policydesc_forceLock" msgid="1141797588403827138">"控制鎖定屏幕的方式和時間。"</string>
+ <string name="policydesc_limitPassword" msgid="3252114203919510394">"控制螢幕解鎖密碼所允許的長度和字元。"</string>
+ <string name="policylab_watchLogin" msgid="914130646942199503">"監控螢幕解鎖嘗試次數"</string>
+ <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"監視為螢幕解鎖時輸入錯誤密碼的次數;如果輸入錯誤密碼的次數過多,則會鎖定平板電腦或清除平板電腦的所有資料。"</string>
+ <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"監視為螢幕解鎖時輸入錯誤密碼的次數,如果輸入錯誤密碼的次數過多,則會鎖定手機或清除手機的所有資料。"</string>
+ <string name="policylab_resetPassword" msgid="2620077191242688955">"更改螢幕解鎖密碼"</string>
+ <string name="policydesc_resetPassword" msgid="605963962301904458">"更改螢幕解鎖密碼。"</string>
+ <string name="policylab_forceLock" msgid="2274085384704248431">"鎖定螢幕"</string>
+ <string name="policydesc_forceLock" msgid="1141797588403827138">"控制鎖定螢幕的方式和時間。"</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"清除所有資料"</string>
<string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"重設平板電腦為原廠設定,在不提出警告的情況下直接清除平板電腦的資料。"</string>
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"重設手機為原廠設定,在不提出警告的情況下直接清除手機的資料。"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"設定裝置的全域代理伺服器"</string>
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"設定政策啟用時所要使用的裝置全域代理伺服器,只有第一個裝置管理員所設定的全域代理伺服器具有效力。"</string>
<string name="policylab_expirePassword" msgid="885279151847254056">"設定螢幕上鎖密碼到期日"</string>
- <string name="policydesc_expirePassword" msgid="1729725226314691591">"控制屏幕上鎖密碼的更改頻率。"</string>
+ <string name="policydesc_expirePassword" msgid="1729725226314691591">"控制螢幕上鎖密碼的更改頻率。"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"設定儲存裝置加密"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"必須為儲存的應用程式資料加密。"</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"停用相機"</string>
@@ -882,10 +882,10 @@
<string name="keyguard_label_text" msgid="861796461028298424">"如要解鎖,請按選單鍵,然後按 0。"</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"緊急電話號碼"</string>
<string name="lockscreen_carrier_default" msgid="8963839242565653192">"沒有服務。"</string>
- <string name="lockscreen_screen_locked" msgid="7288443074806832904">"屏幕已鎖定。"</string>
+ <string name="lockscreen_screen_locked" msgid="7288443074806832904">"螢幕已鎖定。"</string>
<string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"按選單鍵解鎖或撥打緊急電話。"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"按選單鍵解鎖。"</string>
- <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"畫出解鎖圖形以解除鎖定屏幕"</string>
+ <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"畫出解鎖圖形以解除鎖定螢幕"</string>
<string name="lockscreen_emergency_call" msgid="5347633784401285225">"緊急電話"</string>
<string name="lockscreen_return_to_call" msgid="5244259785500040021">"返回通話"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"正確!"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"允許應用程式修改手機上儲存的瀏覽器記錄或書籤。如此一來,應用程式或可清除或修改瀏覽器資料。注意:這項權限可能不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"設定鬧鐘"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能沒有這項功能。"</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"移除留言訊息"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"允許應用程式移除留言信箱中的訊息。"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"管理留言信箱"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"允許應用程式修改和移除留言信箱中的訊息。"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"新增留言"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息加到您的留言信箱收件箱。"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"讀取所有語音留言"</string>
@@ -1044,8 +1044,8 @@
<string name="searchview_description_submit" msgid="2688450133297983542">"提交查詢"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"語音搜尋"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"啟用輕觸探索?"</string>
- <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> 需要啟用「輕觸探索」。開啟這項功能時,系統會在您的手指輕觸屏幕上的物件時顯示或朗讀說明,您也可以執行手勢來與平板電腦互動。"</string>
- <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> 需要啟用「輕觸探索」。開啟這項功能時,系統會在您的手指輕觸屏幕上的物件時顯示或朗讀說明,您也可以執行手勢來與手機互動。"</string>
+ <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> 需要啟用「輕觸探索」。開啟這項功能時,系統會在您的手指輕觸螢幕上的物件時顯示或朗讀說明,您也可以執行手勢來與平板電腦互動。"</string>
+ <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> 需要啟用「輕觸探索」。開啟這項功能時,系統會在您的手指輕觸螢幕上的物件時顯示或朗讀說明,您也可以執行手勢來與手機互動。"</string>
<string name="oneMonthDurationPast" msgid="7396384508953779925">"1 個月前"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 個月前"</string>
<plurals name="num_seconds_ago">
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"開啟"</string>
<string name="capital_off" msgid="6815870386972805832">"關"</string>
<string name="whichApplication" msgid="4533185947064773386">"完成操作需使用"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"選取主畫面應用程式"</string>
<string name="alwaysUse" msgid="4583018368000610438">"設定用於執行這項操作。"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"前往 [系統設定] > [應用程式] > [已下載] 清除預設值。"</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"一律允許"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"絕不允許"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM 卡已移除"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"您必須先以插入有效的 SIM 卡來重新啟動手機,才能使用流動網絡。"</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"完成"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM 卡已新增"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"重新啟動裝置,才能使用流動網絡。"</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"重新啟動"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"設定時間"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string>
@@ -1329,7 +1345,7 @@
<string name="adb_active_notification_title" msgid="6729044778949189918">"已連接 USB 偵錯工具"</string>
<string name="adb_active_notification_message" msgid="1016654627626476142">"輕觸即可停用 USB 偵錯。"</string>
<string name="select_input_method" msgid="4653387336791222978">"選擇輸入法"</string>
- <string name="configure_input_methods" msgid="9091652157722495116">"設定輸入方式"</string>
+ <string name="configure_input_methods" msgid="9091652157722495116">"設定輸入法"</string>
<string name="use_physical_keyboard" msgid="6203112478095117625">"實體鍵盤"</string>
<string name="hardware" msgid="7517821086888990278">"硬件"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"選取鍵盤配置"</string>
@@ -1375,8 +1391,8 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"允許應用程式聽取信任狀態的變更。"</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"提供信任的代理程式。"</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"允許應用程式提供信任的代理程式。"</string>
- <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"啟動信任的代理程式設定選單。"</string>
- <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"允許應用程式啟動可變更信任的代理程式行為的活動。"</string>
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"啟動信任代理的程式設定選單。"</string>
+ <string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"允許應用程式啟動可變更信任代理程式行為的活動。"</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"繫結至信任的代理程式服務"</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"允許應用程式繫結至信任的代理程式服務。"</string>
<string name="permlab_recovery" msgid="3157024487744125846">"與更新和復原系統互動"</string>
@@ -1420,7 +1436,7 @@
<string name="submit" msgid="1602335572089911941">"提交"</string>
<string name="car_mode_disable_notification_title" msgid="3164768212003864316">"已啟用車用模式"</string>
<string name="car_mode_disable_notification_message" msgid="8035230537563503262">"輕觸即可結束車用模式。"</string>
- <string name="tethered_notification_title" msgid="3146694234398202601">"網絡共用或無線基地台已啟用"</string>
+ <string name="tethered_notification_title" msgid="3146694234398202601">"已啟用網絡共享或熱點"</string>
<string name="tethered_notification_message" msgid="6857031760103062982">"輕觸即可設定。"</string>
<string name="back_button_label" msgid="2300470004503343439">"返回"</string>
<string name="next_button_label" msgid="1080555104677992408">"繼續"</string>
@@ -1558,13 +1574,13 @@
<string name="media_route_chooser_searching" msgid="4776236202610828706">"正在搜尋裝置…"</string>
<string name="media_route_chooser_extended_settings" msgid="87015534236701604">"設定"</string>
<string name="media_route_controller_disconnect" msgid="8966120286374158649">"停止連接"</string>
- <string name="media_route_status_scanning" msgid="7279908761758293783">"正在掃描…"</string>
+ <string name="media_route_status_scanning" msgid="7279908761758293783">"正在掃瞄…"</string>
<string name="media_route_status_connecting" msgid="6422571716007825440">"正在連線..."</string>
<string name="media_route_status_available" msgid="6983258067194649391">"可用"</string>
<string name="media_route_status_not_available" msgid="6739899962681886401">"無法使用"</string>
<string name="media_route_status_in_use" msgid="4533786031090198063">"使用中"</string>
<string name="display_manager_built_in_display_name" msgid="2583134294292563941">"內置畫面"</string>
- <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI 屏幕"</string>
+ <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI 螢幕"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"重疊效果 #<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>:<xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>,<xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">"(安全)"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"已選取<xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 已刪除"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"使用 Lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app 會鎖定螢幕,只顯示單一應用程式的畫面。\n\n如要結束,請按住最近使用的應用程式按鈕 $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"否"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"您目前正在使用應用程式鎖定模式。"</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"要使用「應用程式鎖定」嗎?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"啟動"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"啟動 Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"結束 Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 4184a97..8f62ca3 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"允許應用程式寫入手機或 SIM 卡中儲存的 SMS 簡訊。請注意,惡意應用程式可能利用此功能刪除您的簡訊。"</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"接收簡訊 (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"允許應用程式接收和處理 WAP 訊息。這項權限也能讓應用程式監控訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"接收藍牙訊息 (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"允許應用程式接收及處理藍牙 MAP 訊息。這項設定可讓應用程式監控傳送至您裝置的訊息,或在您閱讀訊息前主動刪除訊息。"</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"擷取執行中的應用程式"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"允許應用程式擷取最近執行工作的資訊。這項設定可讓應用程式找出裝置所用程式的相關資訊。"</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"對所有使用者執行各種動作"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"模擬位置來源以供測試"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供者。這項設定可讓應用程式覆寫 GPS 或位置資訊提供者等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"接收額外的位置提供者指令"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"允許應用程式存取額外位置資訊提供者指令。這項設定可能會造成應用程式干擾 GPS 或其他位置資訊來源的運作。"</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"允許應用程式存取額外位置資訊提供者指令。這項設定可能會造成應用程式干擾 GPS 或其他位置資訊來源的運作。"</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"准許安裝位置提供者"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"建立虛構的位置資訊來源以供測試,或安裝新的位置資訊提供者。這項設定可讓應用程式覆寫 GPS 或位置資訊提供者等其他位置資訊來源所傳回的位置資訊和/或狀態。"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"精確位置 (以 GPS 和網路為基準)"</string>
@@ -715,14 +713,16 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"允許應用程式管理網路政策並定義應用程式專用規則。"</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"修改網路使用量計算方式"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"允許應用程式修改應用程式網路使用量的計算方式 (不建議一般應用程式使用)。"</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"修改通訊端標記"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"允許應用程式修改路由的通訊端標記"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"存取通知"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"允許應用程式擷取、檢查及清除通知 (包括由其他應用程式發佈的通知)。"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"繫結至通知接聽器服務"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允許應用程式繫結至通知接聽器服務的頂層介面 (一般應用程式不需使用)。"</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"繫結至條件提供者服務"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允許應用程式繫結至條件提供者服務的頂層介面 (一般應用程式並不需要)。"</string>
+ <!-- no translation found for permlab_bindMediaRouteService (6637740382272686835) -->
+ <skip />
+ <!-- no translation found for permdesc_bindMediaRouteService (6436655024972496687) -->
+ <skip />
<string name="permlab_bindDreamService" msgid="4153646965978563462">"繫結至 Dream 服務"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"允許應用程式繫結至 Dream 服務的頂層介面 (一般應用程式不需使用)。"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"叫用行動通訊業者提供的設定應用程式"</string>
@@ -733,8 +733,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"允許應用程式修改觸控螢幕的校正參數 (一般應用程式並不需要)。"</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"存取 DRM 憑證"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"允許應用程式佈建及使用 DRM 憑證 (一般應用程式並不需要)。"</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"接收交遞傳輸廣播。"</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"允許接收交遞傳輸狀態資訊。"</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"接收 Android Beam 的傳輸狀態"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"允許應用程式接收 Android Beam 目前傳輸的資訊"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"控制螢幕解鎖密碼所允許的長度和字元。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
@@ -1008,8 +1008,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"允許應用程式修改手機上儲存的瀏覽紀錄或書籤。這項設定會讓應用程式具有清除或修改瀏覽資料的權限。注意:這項權限不適用於第三方瀏覽器或其他具備網頁瀏覽功能的應用程式。"</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"設定鬧鐘"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能無法執行這項功能。"</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"移除語音留言"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"允許應用程式移除語音留言收件匣中的訊息。"</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"管理語音信箱"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"允許應用程式修改及移除語音留言收件匣中的訊息。"</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"新增語音留言"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息新增至您的語音信箱收件匣。"</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"讀取所有語音留言"</string>
@@ -1181,6 +1181,20 @@
<string name="capital_on" msgid="1544682755514494298">"開啟"</string>
<string name="capital_off" msgid="6815870386972805832">"關閉"</string>
<string name="whichApplication" msgid="4533185947064773386">"選擇要使用的應用程式"</string>
+ <!-- no translation found for whichApplicationNamed (8260158865936942783) -->
+ <skip />
+ <!-- no translation found for whichViewApplication (3272778576700572102) -->
+ <skip />
+ <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
+ <skip />
+ <!-- no translation found for whichEditApplication (144727838241402655) -->
+ <skip />
+ <!-- no translation found for whichEditApplicationNamed (1775815530156447790) -->
+ <skip />
+ <!-- no translation found for whichSendApplication (6902512414057341668) -->
+ <skip />
+ <!-- no translation found for whichSendApplicationNamed (2799370240005424391) -->
+ <skip />
<string name="whichHomeApplication" msgid="4616420172727326782">"選取主螢幕應用程式"</string>
<string name="alwaysUse" msgid="4583018368000610438">"設為預設應用程式。"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"前往 [系統設定] > [應用程式] > [下載] 清除預設值。"</string>
@@ -1283,10 +1297,12 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"一律允許"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"一律不允許"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"SIM 卡已移除"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"您必須先插入有效的 SIM 卡再重新啟動手機,才能使用行動網路。"</string>
+ <!-- no translation found for sim_removed_message (5450336489923274918) -->
+ <skip />
<string name="sim_done_button" msgid="827949989369963775">"完成"</string>
<string name="sim_added_title" msgid="3719670512889674693">"SIM 卡已新增"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"請重新啟動裝置,才能使用行動網路。"</string>
+ <!-- no translation found for sim_added_message (7797975656153714319) -->
+ <skip />
<string name="sim_restart_button" msgid="4722407842815232347">"重新啟動"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"設定時間"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string>
@@ -1737,10 +1753,25 @@
<string name="item_is_selected" msgid="949687401682476608">"已選取 <xliff:g id="ITEM">%1$s</xliff:g>"</string>
<string name="deleted_key" msgid="7659477886625566590">"已刪除 <xliff:g id="KEY">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_title" msgid="5895142291937470019">"使用 Lock-to-app?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app 會鎖定螢幕,只顯示單一應用程式的畫面。\n\n如要結束,請按住最近使用的應用程式按鈕 $"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"否"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"您正在使用應用程式鎖定模式。"</string>
+ <string name="lock_to_app_title" msgid="5895142291937470019">"要使用「應用程式鎖定」功能嗎?"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"啟動"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"啟動 Lock-to-app"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"結束 Lock-to-app"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 93daaf1..4f456d3 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -294,10 +294,8 @@
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Ivumela uhlelo lokusebenza ukuthi ibhale imiylezo ye-SMS egcinwe ocingweni lwakh noma kwikhadi lakho le-SIM. Izuhlelo lokusebenza ezinobungozi zingayisusa imiyalezo yakho."</string>
<string name="permlab_receiveWapPush" msgid="5991398711936590410">"thola imiyalezo ebhaliwe (i-WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-WAP. Le mvume ifaka phakathi amandla okungamela noma okwesusa imilayezo ethunyelwe kuwe ngaphandle kokukubonisa."</string>
- <!-- no translation found for permlab_receiveBluetoothMap (7593811487142360528) -->
- <skip />
- <!-- no translation found for permdesc_receiveBluetoothMap (8656755936919466345) -->
- <skip />
+ <string name="permlab_receiveBluetoothMap" msgid="7593811487142360528">"thola imilayezo ye-Bluetooth (MAP)"</string>
+ <string name="permdesc_receiveBluetoothMap" msgid="8656755936919466345">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-Bluetooth MAP. Lokhu kusho ukuthi uhlelo lokusebenza lingakwazi ukugada noma ukususa imilayezo ethunyelwa kwidivayisi yakho ngaphandle kokukubonisa yona."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"thola izinhlelo zokusebenza ezisebenzayo"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Ivumela uhlelo lokusebenza ukubuyisa ulwazi mayelana nemisebenzi yamanje neyakamuva. Lokhu kungavumela uhlelo lokusebenza ukuthola ulwazi mayelana nokuthi iziphi izinhlelo zokusebenza ezisetshenziswa kudivayisi."</string>
<string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"ihlanganyela phakathi kwabasebenzisi"</string>
@@ -506,7 +504,7 @@
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"lungisela imithombo yendawo ukuhlolwa"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Dala imithombo yendawo ye-mock ngokuhlola noma ukufaka umnikeli wendawo omusha. Lokhu kuvumela uhlelo lokusebenza ukubhala ngaphezulu indawo kanye/noma isimo esibuyiswe eminye imithombo yendawo njenge-GPS noma abanikeli bendawo."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"finyelela kweminye imiyalo yokunikeza indawo"</string>
- <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Ivumela uhlelo lokusebenza ukufinyelela imiyalo yabanikeli bendawo engaphezulu. Lokhu kungavumela uhlelo lokusebenza ukuthi liphazamisane nomsebenzi we-GPS noma eminye imithombo yendawo."</string>
+ <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Ivumela uhlelo lokusebenza ukufinyelela imiyalo eyengeziwe yabahlinzeki bendawo. Lokhu kungase kuvumele uhlelo lokusebenza ukuthi liphazamisane nomsebenzi we-GPS noma eminye imithombo yendawo."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"imvume yokufaka umhlinzeki wendawo"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Dala imithombo yendawo ye-mock ngokuhlola noma ukufaka umnikeli wendawo omusha. Lokhu kuvumela uhlelo lokusebenza ukubhala ngaphezulu indawo kanye/noma isimo esibuyiswe eminye imithombo yendawo njenge-GPS noma abanikeli bendawo."</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"indawo eqondile (kususelwe ku-GPS nakunethiwekhi)"</string>
@@ -715,14 +713,14 @@
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Ivumela uhlelo lokusebenza ukuthi yengamele iigomo iphinde ichaze imithetho ehambisana ngqo nensiza."</string>
<string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"lungisa ukubala kokusebenza kohleloxhumano"</string>
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Ivumela uhlelo lokusebenza ukuthi iguqule ukuthii ukusetshenziswa kwenethiwekhi kumiswa kanjani ezinsizeni. Ayisetshenziswa izinhlelo zokusebenza ezijwayelekile."</string>
- <string name="permlab_markNetworkSocket" msgid="3658527214914959749">"shintsha izimpawu zesokhethi"</string>
- <string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Ivumela uhlelo lokusebenza ukuthi lilungise izimpawu zesokhethi zomzila"</string>
<string name="permlab_accessNotifications" msgid="7673416487873432268">"finyelela kuzaziso"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Ivumela uhlelo lokusebenza ukuthi lithole, lihlole, liphinde lisuse izaziso, ezifaka lezo ezithunyelwe ezinye izinhlelo zokusebenza."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bophezela kwisevisi yomlaleli wesaziso"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ivumela umbambi ukubophezela kwisixhumi esibonakalayo sezinga eliphezulu lesevisi yomlaleli wesaziso. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
<string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"hlanganisa kwisevisi yomhlinzeki wesimo"</string>
<string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo seleveli ephezulu sesevisi yomhlinzeki wesimo. Akufanele kudingekele izinhlelo zokusebenza ezivamile."</string>
+ <string name="permlab_bindMediaRouteService" msgid="6637740382272686835">"hlanganisela kusevisi yomzila yemidiya"</string>
+ <string name="permdesc_bindMediaRouteService" msgid="6436655024972496687">"Ivumela umbambi ukuhlanganisa kusibonisi esiphezulu sesevisi yomzila wemidiya. Akufanele kudingeke kuzinhlelo zokusebenza ezivamile."</string>
<string name="permlab_bindDreamService" msgid="4153646965978563462">"bophezela kusevisi yephupho"</string>
<string name="permdesc_bindDreamService" msgid="7325825272223347863">"Ivumela isiphathi ukuthi sibophezele ukusebenzisana kwezinga eliphezulu kwesevisi yephupho. Akumele kudingelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"buyisela uhlelo lokusebenza lokulungiselelwa okunikezwe yinkampani yenethiwekhi"</string>
@@ -733,8 +731,8 @@
<string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Ivumela uhlelo lokusebenza ukuthi lushintshe imingcele yokulinganisa yesikrini esithintwayo. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"finyelela izitifiketi ze-DRM"</string>
<string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Ivumela uhlelo lokusebenza ekunikezweni nokusetshenziswa kwezitifiketi ze-DRM. Akufanele kudingeke kuzinhlelo zokusebenza ezivamile."</string>
- <string name="permlab_handoverStatus" msgid="4558616203830448763">"Thola ukusakaza kokuthuthukisela kokunikeza."</string>
- <string name="permdesc_handoverStatus" msgid="5738446261941364055">"Ivumela ukuthola ulwazi lwesimo sokuthutha olunikezwayo."</string>
+ <string name="permlab_handoverStatus" msgid="1159132046126626731">"Thola isimo sokundlulisa se-Android Beam"</string>
+ <string name="permdesc_handoverStatus" msgid="4788144087245714948">"Ivumela lolu hlelo lokusebenza ukuthi luthole ulwazi mayelana nokundluliswa kwamanje kwe-Android Beam"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi okuvula isikrini"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
@@ -1008,8 +1006,8 @@
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Ivumela uhlelo lokusebenza ukushintsha umlando wamabhukhimakhi noma wesiphequluli alondolozwe efonini yakho. Lokhu kungavumela uhlelo lokusebenza ukususa noma ukushintsha idatha yesiphequluli. Qaphela: le mvume kungenzeka ingaphoqelelwa iziphequluli ezivela eceleni noma ezinye izinhlelo zokusebenza ezinamandla okuphequlula iwebhu."</string>
<string name="permlab_setAlarm" msgid="1379294556362091814">"setha i-alamu"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Ivumela uhlelo lokusebenza ukuthi isethe i-alamu ensizeni efkiwe ye-alamu. Ezinye izinhlelo zokusebenza ze-alamu kungenzeka zingakusebenzisi lokho."</string>
- <string name="permlab_removeVoicemail" msgid="6328485960478155867">"susa amavoyisimeyili"</string>
- <string name="permdesc_removeVoicemail" msgid="8113704917331103065">"Ivumela uhlelo lokusebenza ukususa imilayezo kusuka kubhokisi lokungenayo levoyisimeyili."</string>
+ <string name="permlab_manageVoicemail" msgid="7884874112753411405">"phatha amavoyisimeyili"</string>
+ <string name="permdesc_manageVoicemail" msgid="4134567328139761134">"Ivumela uhlelo lokusebenza ukuthi liguqule liphinde lisuse imilayezo esuka kubhokisi lakho lokungenayo lwe-voyisimeyili."</string>
<string name="permlab_addVoicemail" msgid="5525660026090959044">"engeza imeyili yezwi"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ivumela uhlelo lokusebenza ukwengeza imiyalezo kwibhokisi lakho lemeyili yezwi."</string>
<string name="permlab_readAllVoicemail" msgid="5834057671176753416">"funda wonke amavoyisimeyili"</string>
@@ -1181,6 +1179,13 @@
<string name="capital_on" msgid="1544682755514494298">"VULIWE"</string>
<string name="capital_off" msgid="6815870386972805832">"VALIWE"</string>
<string name="whichApplication" msgid="4533185947064773386">"Qedela isenzo usebenzisa"</string>
+ <string name="whichApplicationNamed" msgid="8260158865936942783">"Qedela isenzo usebenzisa i-%1$s"</string>
+ <string name="whichViewApplication" msgid="3272778576700572102">"Vula nge-"</string>
+ <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Vula nge-%1$s"</string>
+ <string name="whichEditApplication" msgid="144727838241402655">"Hlela nge-"</string>
+ <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Hlela nge-%1$s"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Yabelana no-"</string>
+ <string name="whichSendApplicationNamed" msgid="2799370240005424391">"Yabelana no-%1$s"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"Khetha uhlelo lokusebenza lwasekhaya"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Sebenzisa ngokuzenzakalelayo kulesenzo."</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"Susa izilungiselelo zesistimu; Izinhlelo zokusebenza & Okulandiwe"</string>
@@ -1283,10 +1288,10 @@
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Vumela njalo?"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Ungavumeli"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"Ikhadi le-SIM likhishiwe"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"Inethiwekhi yeselula ngeke itholakale kuwena kuze kube uqala kabusha ufake ikhadi le-SIM elifanele."</string>
+ <string name="sim_removed_message" msgid="5450336489923274918">"Inethiwekhi yeselula ngeke itholakale uze uqale kabusha ngekhadi le-SIM elivumelekile lifakiwe."</string>
<string name="sim_done_button" msgid="827949989369963775">"Kwenziwe"</string>
<string name="sim_added_title" msgid="3719670512889674693">"Ikhadi le-SIM lengeziwe"</string>
- <string name="sim_added_message" msgid="6599945301141050216">"Kufanele uqalise kabusha idivaysi yakho ukuze ungene kuhleloxhumano yeselula."</string>
+ <string name="sim_added_message" msgid="7797975656153714319">"Qala kabusha idivayisi yakho ukuze ufinyelele inethiwekhi yeselula."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Qala phansi"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Hlela isikhathi"</string>
<string name="date_picker_dialog_title" msgid="5879450659453782278">"Setha idethi"</string>
@@ -1375,7 +1380,7 @@
<string name="permdesc_trust_listener" msgid="8233895334214716864">"Ivumela uhlelo lokusebenza ukuthi lilalelele izinguquko kusimo sethemba."</string>
<string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Nikeza umsebenzeli owethembekile."</string>
<string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Ivumela uhlelo lokusebenza ukunikeza umsebenzeli owethembekile."</string>
- <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Ivula imenyu yamasethingi womsebenzeli."</string>
+ <string name="permlab_launch_trust_agent_settings" msgid="5859430082240410200">"Ivula imenyu yezilungiselelo zomsebenzeli."</string>
<string name="permdesc_launch_trust_agent_settings" msgid="8185142708644913381">"Ivumela uhlelo lokusebenza ukuqalisa umsebenzi oshintsha ukuziphatha komsebenzeli owethembekile."</string>
<string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Bophezela kusevisi yomenzeli wethemba"</string>
<string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Ivumela uhlelo lokusebenza ukuthi libophezeleke kusevisi yomenzeli wethemba."</string>
@@ -1737,10 +1742,25 @@
<string name="item_is_selected" msgid="949687401682476608">"I-<xliff:g id="ITEM">%1$s</xliff:g> ekhethiwe"</string>
<string name="deleted_key" msgid="7659477886625566590">"I-<xliff:g id="KEY">%1$s</xliff:g> isusiwe"</string>
<string name="managed_profile_label_badge" msgid="2355652472854327647">"Umsebenzi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+ <!-- no translation found for lock_to_app_toast (2126866321272822564) -->
+ <skip />
+ <string name="lock_to_app_toast_locked" msgid="4229650395479263497">"Ukwimodi yokukhiya kuhlelo lokusebenza."</string>
<string name="lock_to_app_title" msgid="5895142291937470019">"Sebenzisa isikhiya sohlelo lokusebenza?"</string>
- <string name="lock_to_app_description" msgid="8597199033462406175">"Isikhiya kuhlelo lokusebenza sikhiyela isibonisi kuhlelo lokusebenza olulodwa.\n\nUkuze uphume cindezela uphinde ubambe inkinobho yezinhlelo zokusebenza zakamuva engu-$"</string>
- <string name="lock_to_app_negative" msgid="8522854387366288195">"CHA"</string>
+ <!-- no translation found for lock_to_app_description (2800403592608529611) -->
+ <skip />
+ <!-- no translation found for lock_to_app_negative (2259143719362732728) -->
+ <skip />
<string name="lock_to_app_positive" msgid="7085139175671313864">"QALA"</string>
- <string name="lock_to_app_start" msgid="8889002974248178076">"Qala Isikhiya sohlelo lokusebenza"</string>
- <string name="lock_to_app_exit" msgid="7033017307788432861">"Phuma kusikhiya sohlelo lokusebenza"</string>
+ <!-- no translation found for lock_to_app_start (3074665051586318340) -->
+ <skip />
+ <!-- no translation found for lock_to_app_exit (8967089657201849300) -->
+ <skip />
+ <!-- no translation found for lock_to_app_use_screen_lock (1434584309048590886) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pin (7908385370846820001) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_pattern (7763071104790758405) -->
+ <skip />
+ <!-- no translation found for lock_to_app_unlock_password (795224196583495868) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5fdadb7..ab19ad4 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -676,21 +676,39 @@
<!-- The TimePicker style. -->
<attr name="timePickerStyle" format="reference" />
- <!-- The TimePicker Header background color . -->
- <attr name="timePickerHeaderBackgroundColor" format="reference" />
-
- <!-- The TimePicker Header time label text appearance -->
- <attr name="timePickerHeaderTimeLabelTextAppearance" format="reference" />
-
- <!-- TimePicker Header am pm label text appearance -->
- <attr name="timePickerHeaderAmPmLabelTextAppearance" format="reference" />
-
<!-- The TimePicker dialog theme. -->
<attr name="timePickerDialogTheme" format="reference" />
<!-- The DatePicker style. -->
<attr name="datePickerStyle" format="reference" />
+ <!-- The DatePicker Header day of week label background color . -->
+ <attr name="datePickerHeaderDayOfWeekLabelBackgroundColor" format="reference" />
+
+ <!-- The DatePicker Header day of week label text appearance -->
+ <attr name="datePickerHeaderDayOfWeekLabelTextAppearance" format="reference" />
+
+ <!-- The DatePicker Header selector background color . -->
+ <attr name="datePickerHeaderSelectorBackgroundColor" format="reference" />
+
+ <!-- The DatePicker Header selector month label text appearance -->
+ <attr name="datePickerHeaderSelectorMonthLabelTextAppearance" format="reference" />
+
+ <!-- The DatePicker Header selector day of month label text appearance -->
+ <attr name="datePickerHeaderSelectorDayOfMonthLabelTextAppearance" format="reference" />
+
+ <!-- The DatePicker Header selector year label text appearance -->
+ <attr name="datePickerHeaderSelectorYearLabelTextAppearance" format="reference" />
+
+ <!-- The DatePicker Header list year label text appearance -->
+ <attr name="datePickerHeaderListYearLabelTextAppearance" format="reference" />
+
+ <!-- DatePicker list year label circle background color -->
+ <attr name="datePickerHeaderListYearLabelCircleBackgroundColor" format="reference" />
+
+ <!-- The DatePicker dialog theme. -->
+ <attr name="datePickerDialogTheme" format="reference" />
+
<!-- Default ActivityChooserView style. -->
<attr name="activityChooserViewStyle" format="reference" />
@@ -1826,6 +1844,9 @@
Activity Transition. Corresponds to
{@link android.view.Window#setTransitionBackgroundFadeDuration(long)}. -->
<attr name="windowTransitionBackgroundFadeDuration" />
+
+ <!-- Elevation to use for the window. -->
+ <attr name="windowElevation" format="dimension" />
</declare-styleable>
<!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -1889,6 +1910,14 @@
<!-- When opening an activity in a new task, this is the animation that is
run on the activity of the old task (which is exiting the screen). -->
<attr name="taskOpenExitAnimation" format="reference" />
+ <!-- When opening an activity in a new task using Intent/FLAG_ACTIVITY_LAUNCH_BEHIND,
+ this is the animation that is run on the activity of the new task (which is
+ entering the screen and then leaving). -->
+ <attr name="launchTaskBehindBackgroundAnimation" format="reference" />
+ <!-- When opening an activity in a new task using Intent.FLAG_ACTIVITY_LAUNCH_BEHIND,
+ this is the animation that is run on the activity of the old task (which is
+ already on the screen and then stays on). -->
+ <attr name="launchTaskBehindSourceAnimation" format="reference" />
<!-- When closing the last activity of a task, this is the animation that is
run on the activity of the next task (which is entering the screen). -->
<attr name="taskCloseEnterAnimation" format="reference" />
@@ -4172,6 +4201,28 @@
<attr name="maxDate" format="string" />
<!-- @hide The layout of the date picker. -->
<attr name="internalLayout" format="reference" />
+ <!-- @hide The layout of the legacy DatePicker. -->
+ <attr name="legacyLayout" />
+ <!-- @hide Enables or disable the use of the legacy layout for the DatePicker. -->
+ <attr name="legacyMode" />
+ <!-- The background color for the date selector 's day of week of the non legacy DatePicker. -->
+ <attr name="dateSelectorDayOfWeekBackgroundColor" format="color|reference" />
+ <!-- The text color for the date selector's day of week of the non legacy DatePicker. -->
+ <attr name="dateSelectorDayOfWeekTextAppearance" format="reference" />
+ <!-- The background color for the date selector of the non legacy DatePicker. -->
+ <attr name="dateSelectorBackgroundColor" format="color|reference" />
+ <!-- The month's text appearance in the date selector of the non legacy DatePicker. -->
+ <attr name="dateSelectorMonthTextAppearance" format="reference" />
+ <!-- The day of month's text appearance in the date selector of the non legacy DatePicker. -->
+ <attr name="dateSelectorDayOfMonthTextAppearance" format="reference" />
+ <!-- The year's text appearance in the date selector of the non legacy DatePicker. -->
+ <attr name="dateSelectorYearTextAppearance" format="reference" />
+ <!-- The list year's text appearance in the list of the non legacy DatePicker. -->
+ <attr name="dateSelectorYearListItemTextAppearance" format="reference" />
+ <!-- The list year's selected circle color in the list of the non legacy DatePicker. -->
+ <attr name="dateSelectorYearListSelectedCircleColor" format="color|reference" />
+ <!-- The text color list of the calendar of the non legacy DatePicker. -->
+ <attr name="calendarTextColor" format="color|reference" />
</declare-styleable>
<declare-styleable name="TwoLineListItem">
@@ -4441,32 +4492,33 @@
</declare-styleable>
<declare-styleable name="TimePicker">
- <!-- @hide The layout of the time picker. -->
- <attr name="internalLayout" />
- <!-- @hide The layout of the legacy time picker. -->
- <attr name="legacyLayout" format="reference" />
<!-- @hide Enables or disable the use of the legacy layout for the TimePicker. -->
<attr name="legacyMode" format="boolean" />
- <!-- @hide The color when the non legacy TimePicker is disabled. -->
- <attr name="disabledColor" format="color|reference" />
- <!-- @hide The color for selected text of the non legacy TimePicker. -->
- <attr name="headerSelectedTextColor" format="color|reference" />
- <!-- @hide The color for unselected text of the non legacy TimePicker. -->
- <attr name="headerUnselectedTextColor" format="color|reference" />
- <!-- @hide The background color for the header of the non legacy TimePicker. -->
- <attr name="headerBackgroundColor" format="color|reference" />
- <!-- @hide The color for the hours/minutes numbers of the non legacy TimePicker. -->
- <attr name="numbersTextColor" format="color|reference" />
- <!-- @hide The background color for the hours/minutes numbers of the non legacy TimePicker. -->
- <attr name="numbersBackgroundColor" format="color|reference" />
- <!-- @hide The color for the AM/PM selectors of the non legacy TimePicker. -->
- <attr name="amPmTextColor" format="color|reference" />
- <!-- @hide The background color for the AM/PM selectors of the non legacy TimePicker when unselected. -->
- <attr name="amPmUnselectedBackgroundColor" format="color|reference" />
- <!-- @hide The background color for the AM/PM selectors of the non legacy TimePicker when selected. -->
- <attr name="amPmSelectedBackgroundColor" format="color|reference" />
- <!-- @hide The color for the hours/minutes selector of the non legacy TimePicker. -->
- <attr name="numbersSelectorColor" format="color|reference" />
+ <!-- @hide The layout of the legacy time picker. -->
+ <attr name="legacyLayout" format="reference" />
+ <!-- @hide The layout of the time picker. -->
+ <attr name="internalLayout" />
+ <!-- The text appearance for the AM/PM header of the TimePicker. -->
+ <attr name="headerAmPmTextAppearance" format="reference" />
+ <!-- The text appearance for the time header of the TimePicker. -->
+ <attr name="headerTimeTextAppearance" format="reference" />
+ <!-- The text color for selected time header of the TimePicker. This
+ will override the value from the text appearance. -->
+ <attr name="headerSelectedTextColor" format="color" />
+ <!-- The background color for the header of the TimePicker. -->
+ <attr name="headerBackgroundColor" format="color" />
+ <!-- The color for the hours/minutes numbers of the TimePicker. -->
+ <attr name="numbersTextColor" format="color" />
+ <!-- The background color for the hours/minutes numbers of the TimePicker. -->
+ <attr name="numbersBackgroundColor" format="color" />
+ <!-- The color for the AM/PM selectors of the TimePicker. -->
+ <attr name="amPmTextColor" format="color" />
+ <!-- The background color for the AM/PM selectors of the TimePicker when unselected. -->
+ <attr name="amPmUnselectedBackgroundColor" format="color" />
+ <!-- The background color for the AM/PM selectors of the TimePicker when selected. -->
+ <attr name="amPmSelectedBackgroundColor" format="color" />
+ <!-- The color for the hours/minutes selector of the TimePicker. -->
+ <attr name="numbersSelectorColor" format="color" />
</declare-styleable>
<!-- ========================= -->
@@ -6720,7 +6772,10 @@
its {@link android.service.voice.VoiceInteractionService#SERVICE_META_DATA} meta-data entry.
Described here are the attributes that can be included in that tag. -->
<declare-styleable name="VoiceInteractionService">
+ <!-- The service that hosts active voice interaction sessions. -->
<attr name="sessionService" format="string" />
+ <!-- The service that provides voice recognition. -->
+ <attr name="recognitionService" format="string" />
<attr name="settingsActivity" />
</declare-styleable>
@@ -6729,9 +6784,19 @@
by the enrollment application.
Described here are the attributes that can be included in that tag. -->
<declare-styleable name="VoiceEnrollmentApplication">
+ <!-- A globally unique ID for the keyphrase. -->
<attr name="searchKeyphraseId" format="integer" />
+ <!-- The actual keyphrase/hint text, or empty if not keyphrase dependent. -->
<attr name="searchKeyphrase" format="string" />
+ <!-- A comma separated list of java locales that are supported for this keyphrase,
+ or empty if not locale dependent. -->
<attr name="searchKeyphraseSupportedLocales" format="string" />
+ <!-- Flags for supported recognition modes. -->
+ <attr name="searchKeyphraseRecognitionFlags">
+ <flag name="none" value="0" />
+ <flag name="voiceTrigger" value="0x1" />
+ <flag name="userIdentification" value="0x2" />
+ </attr>
</declare-styleable>
<!-- Attributes used to style the Action Bar. -->
@@ -7158,4 +7223,21 @@
<attr name="ambientShadowAlpha" format="float" />
<attr name="spotShadowAlpha" format="float" />
</declare-styleable>
+
+ <declare-styleable name="RestrictionEntry">
+ <attr name="key" />
+ <attr name="restrictionType">
+ <enum name="hidden" value="0" />
+ <enum name="bool" value="1" />
+ <enum name="choice" value="2" />
+ <enum name="multi-select" value="4" />
+ <enum name="integer" value="5" />
+ <enum name="string" value="6" />
+ </attr>
+ <attr name="title" />
+ <attr name="description" />
+ <attr name="defaultValue" />
+ <attr name="entries" />
+ <attr name="entryValues" />
+ </declare-styleable>
</resources>
diff --git a/core/res/res/values/colors_holo.xml b/core/res/res/values/colors_holo.xml
index 97b4803..eab1e3f 100644
--- a/core/res/res/values/colors_holo.xml
+++ b/core/res/res/values/colors_holo.xml
@@ -112,12 +112,37 @@
<color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
<color name="timepicker_default_text_color_holo_dark">@color/white</color>
- <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
- <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
-
<color name="timepicker_default_ampm_selected_background_color_holo_light">@color/holo_blue_light</color>
<color name="timepicker_default_ampm_selected_background_color_holo_dark">@color/holo_blue_light</color>
<color name="timepicker_default_ampm_unselected_background_color_holo_light">@color/white</color>
<color name="timepicker_default_ampm_unselected_background_color_holo_dark">@color/transparent</color>
+
+ <!-- DatePicker colors -->
+ <eat-comment />
+
+ <color name="datepicker_default_header_selector_background_holo_light">@android:color/white</color>
+ <color name="datepicker_default_header_selector_background_holo_dark">#ff303030</color>
+
+ <color name="datepicker_default_header_dayofweek_background_color_holo_light">#999999</color>
+ <color name="datepicker_default_header_dayofweek_background_color_holo_dark">@android:color/white</color>
+
+ <color name="datepicker_default_normal_text_color_holo_light">#ff999999</color>
+ <color name="datepicker_default_normal_text_color_holo_dark">@android:color/white</color>
+
+ <color name="datepicker_default_disabled_text_color_holo_light">#80999999</color>
+ <color name="datepicker_default_disabled_text_color_holo_dark">#80999999</color>
+
+ <color name="datepicker_default_selected_text_color_holo_light">#33b5e5</color>
+ <color name="datepicker_default_selected_text_color_holo_dark">#33b5e5</color>
+
+ <color name="datepicker_default_pressed_text_color_holo_light">#0099cc</color>
+ <color name="datepicker_default_pressed_text_color_holo_dark">#0099cc</color>
+
+ <color name="datepicker_default_circle_background_color_holo_light">@android:color/holo_blue_light</color>
+ <color name="datepicker_default_circle_background_color_holo_dark">@android:color/holo_blue_light</color>
+
+ <color name="datepicker_default_view_animator_color_holo_light">#f2f2f2</color>
+ <color name="datepicker_default_view_animator_color_holo_dark">#ff303030</color>
+
</resources>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 7371d4e..6988881 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -161,9 +161,36 @@
<color name="timepicker_default_background_material">@color/primary_text_default_material_light</color>
<color name="timepicker_default_text_color_material">@color/black</color>
- <color name="timepicker_default_disabled_color_material">@color/bright_foreground_disabled_material_dark</color>
<color name="timepicker_default_ampm_selected_background_color_material">@color/material_light_blue_A200</color>
<color name="timepicker_default_ampm_unselected_background_color_material">@color/transparent</color>
<color name="timepicker_default_selector_color_material">@color/material_light_blue_A200</color>
<color name="timepicker_default_numbers_background_color_material">@color/transparent</color>
+
+ <!-- DatePicker colors -->
+ <eat-comment />
+
+ <color name="datepicker_default_header_selector_background_material_light">@android:color/white</color>
+ <color name="datepicker_default_header_selector_background_material_dark">#ff303030</color>
+
+ <color name="datepicker_default_header_dayofweek_background_color_material_light">#999999</color>
+ <color name="datepicker_default_header_dayofweek_background_color_material_dark">@android:color/white</color>
+
+ <color name="datepicker_default_normal_text_color_material_light">#ff999999</color>
+ <color name="datepicker_default_normal_text_color_material_dark">@android:color/white</color>
+
+ <color name="datepicker_default_disabled_text_color_material_light">#80999999</color>
+ <color name="datepicker_default_disabled_text_color_material_dark">#80999999</color>
+
+ <color name="datepicker_default_selected_text_color_material_light">#33b5e5</color>
+ <color name="datepicker_default_selected_text_color_material_dark">#33b5e5</color>
+
+ <color name="datepicker_default_pressed_text_color_material_light">#0099cc</color>
+ <color name="datepicker_default_pressed_text_color_material_dark">#0099cc</color>
+
+ <color name="datepicker_default_circle_background_color_material_light">@android:color/holo_blue_light</color>
+ <color name="datepicker_default_circle_background_color_material_dark">@android:color/holo_blue_light</color>
+
+ <color name="datepicker_default_view_animator_color_material_light">#f2f2f2</color>
+ <color name="datepicker_default_view_animator_color_material_dark">#ff303030</color>
+
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 53d9cee..0954ddf 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -564,6 +564,12 @@
<item>5</item>
</integer-array>
+ <!-- Vibrator pattern for feedback when selecting a day/month/year date of a Calendar -->
+ <integer-array name="config_calendarDateVibePattern">
+ <item>125</item>
+ <item>5</item>
+ </integer-array>
+
<!-- Vibrator pattern for feedback about booting with safe mode disabled -->
<integer-array name="config_safeModeDisabledVibePattern">
<item>0</item>
@@ -1513,6 +1519,7 @@
See {@link com.android.server.notification.NotificationSignalExtractor} -->
<string-array name="config_notificationSignalExtractors">
<item>com.android.server.notification.ValidateNotificationPeople</item>
+ <item>com.android.server.notification.PackagePriorityExtractor</item>
<item>com.android.server.notification.NotificationIntrusivenessExtractor</item>
</string-array>
@@ -1578,6 +1585,9 @@
<!-- Package name for default network scorer app; overridden by product overlays. -->
<string name="config_defaultNetworkScorerPackageName"></string>
+ <!-- default device has recents property -->
+ <bool name="config_hasRecents">true</bool>
+
<!-- Defines the default set of global actions. Actions may still be disabled or hidden based
on the current state of the device.
Each item must be one of the following strings:
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index ad6c6cd7..77b115b 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -362,6 +362,24 @@
<dimen name="timepicker_minimum_margin_top_bottom">24dip</dimen>
<dimen name="timepicker_radial_picker_dimen">270dip</dimen>
+ <dimen name="datepicker_done_label_size">14sp</dimen>
+ <dimen name="datepicker_day_number_size">16sp</dimen>
+ <dimen name="datepicker_month_label_size">16sp</dimen>
+ <dimen name="datepicker_month_day_label_text_size">10sp</dimen>
+ <dimen name="datepicker_day_number_select_circle_radius">16dp</dimen>
+ <dimen name="datepicker_month_list_item_header_height">50dp</dimen>
+ <dimen name="datepicker_view_animator_height">270dp</dimen>
+ <dimen name="datepicker_year_picker_padding_top">8dp</dimen>
+ <dimen name="datepicker_year_label_height">64dp</dimen>
+ <dimen name="datepicker_year_label_text_size">22dp</dimen>
+ <dimen name="datepicker_component_width">270dp</dimen>
+ <dimen name="datepicker_selected_calendar_layout_height">155dp</dimen>
+ <dimen name="datepicker_selected_date_day_size">75dp</dimen>
+ <dimen name="datepicker_selected_date_month_size">30dp</dimen>
+ <dimen name="datepicker_selected_date_year_size">30dp</dimen>
+ <dimen name="datepicker_header_height">30dp</dimen>
+ <dimen name="datepicker_header_text_size">14dp</dimen>
+
<!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
<dimen name="immersive_mode_cling_width">-1px</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a0ca06e..e4484ad 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2233,6 +2233,40 @@
<public type="attr" name="buttonBarNegativeButtonStyle" />
<public type="attr" name="popupElevation" />
<public type="attr" name="actionBarPopupTheme" />
+ <public type="attr" name="multiArch" />
+ <public type="attr" name="touchscreenBlocksFocus" />
+ <public type="attr" name="windowElevation" />
+ <public type="attr" name="launchTaskBehindBackgroundAnimation" />
+ <public type="attr" name="launchTaskBehindSourceAnimation" />
+ <!-- Attribute specified in a restriction entry to denote the type of restriction. -->
+ <public type="attr" name="restrictionType" />
+
+ <public type="attr" name="dateSelectorDayOfWeekBackgroundColor" />
+ <public type="attr" name="dateSelectorDayOfWeekTextAppearance" />
+ <public type="attr" name="dateSelectorBackgroundColor" />
+ <public type="attr" name="dateSelectorMonthTextAppearance" />
+ <public type="attr" name="dateSelectorDayOfMonthTextAppearance" />
+ <public type="attr" name="dateSelectorYearTextAppearance" />
+ <public type="attr" name="dateSelectorYearListItemTextAppearance" />
+ <public type="attr" name="dateSelectorYearListSelectedCircleColor" />
+ <public type="attr" name="calendarTextColor" />
+ <public type="attr" name="recognitionService" />
+
+ <!-- For the TimePicker -->
+ <public type="attr" name="timePickerStyle" />
+ <public type="attr" name="timePickerDialogTheme" />
+ <public type="attr" name="headerTimeTextAppearance" />
+ <public type="attr" name="headerAmPmTextAppearance" />
+ <public type="attr" name="headerSelectedTextColor" />
+ <public type="attr" name="headerBackgroundColor" />
+ <public type="attr" name="numbersTextColor" />
+ <public type="attr" name="numbersBackgroundColor" />
+ <public type="attr" name="numbersSelectorColor" />
+ <public type="attr" name="amPmTextColor" />
+ <public type="attr" name="amPmUnselectedBackgroundColor" />
+ <public type="attr" name="amPmSelectedBackgroundColor" />
+
+ <public type="attr" name="searchKeyphraseRecognitionFlags" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
@@ -2480,6 +2514,8 @@
<public-padding type="interpolator" name="l_resource_pad" end="0x010c0010" />
+ <public type="style" name="Theme.Leanback.FormWizard"/>
+
<!-- An interpolator which accelerates fast but decelerates slowly. -->
<public type="interpolator" name="fast_out_slow_in" />
<!-- An interpolator which starts with a peak non-zero velocity and decelerates slowly. -->
@@ -2509,6 +2545,4 @@
<!-- A transition that moves views in or out of the scene to or from the left edge when
a view visibility changes. -->
<public type="transition" name="slide_left"/>
- <public type="attr" name="multiArch" />
- <public type="attr" name="touchscreenBlocksFocus" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5d57262..2492689 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2124,6 +2124,11 @@
<string name="permdesc_bindConditionProviderService">Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_bindMediaRouteService">bind to a media route service</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_bindMediaRouteService">Allows the holder to bind to the top-level interface of a media route service. Should never be needed for normal apps.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_bindDreamService">bind to a dream service</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_bindDreamService">Allows the holder to bind to the top-level interface of a dream service. Should never be needed for normal apps.</string>
@@ -3622,13 +3627,13 @@
<!-- See SIM_REMOVED_DIALOG. This is the title of that dialog. -->
<string name="sim_removed_title">SIM card removed</string>
<!-- See SIM_REMOVED_DIALOG. This is the message of that dialog. -->
- <string name="sim_removed_message">The mobile network will be unavailable until you restart with a valid SIM card inserted.</string>
+ <string name="sim_removed_message">The cellular network will be unavailable until you restart with a valid SIM card inserted.</string>
<!-- See SIM_REMOVED_DIALOG. This is the button of that dialog. -->
<string name="sim_done_button">Done</string>
<!-- See SIM_ADDED_DIALOG. This is the title of that dialog. -->
<string name="sim_added_title">SIM card added</string>
<!-- See SIM_ADDED_DIALOG. This is the message of that dialog. -->
- <string name="sim_added_message">Restart your device to access the mobile network.</string>
+ <string name="sim_added_message">Restart your device to access the cellular network.</string>
<!-- See SIM_ADDED_DIALOG. This is the button of that dialog. -->
<string name="sim_restart_button">Restart</string>
@@ -3974,16 +3979,6 @@
<!-- Optional button to Skip a PreferenceActivity [CHAR LIMIT=20] -->
<string name="skip_button_label">Skip</string>
- <!-- Strings for throttling notification -->
- <!-- Shown when the user is in danger of being throttled -->
- <string name="throttle_warning_notification_title">High mobile data use</string>
- <string name="throttle_warning_notification_message">Touch to learn more about mobile data use.</string>
-
- <!-- Strings for throttling notification -->
- <!-- Shown when the users bandwidth is reduced because of excessive data use -->
- <string name="throttled_notification_title">Mobile data limit exceeded</string>
- <string name="throttled_notification_message">Touch to learn more about mobile data use.</string>
-
<!-- Displayed on the Find dialog when there are no matches [CHAR LIMIT=NONE]-->
<string name="no_matches">No matches</string>
@@ -4193,22 +4188,22 @@
<string name="data_usage_warning_body">Touch to view usage and settings.</string>
<!-- Notification title when 2G-3G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_3g_limit_title">2G-3G data disabled</string>
+ <string name="data_usage_3g_limit_title">2G-3G data is off</string>
<!-- Notification title when 4G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_4g_limit_title">4G data disabled</string>
+ <string name="data_usage_4g_limit_title">4G data is off</string>
<!-- Notification title when mobile data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_mobile_limit_title">Mobile data disabled</string>
+ <string name="data_usage_mobile_limit_title">Cellular data is off</string>
<!-- Notification title when Wi-Fi data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_wifi_limit_title">Wi-Fi data disabled</string>
+ <string name="data_usage_wifi_limit_title">Wi-Fi data is off</string>
<!-- Notification body when data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
- <string name="data_usage_limit_body">Touch to enable.</string>
+ <string name="data_usage_limit_body">Limit reached</string>
<!-- Notification title when 2G-3G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
<string name="data_usage_3g_limit_snoozed_title">2G-3G data limit exceeded</string>
<!-- Notification title when 4G data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
<string name="data_usage_4g_limit_snoozed_title">4G data limit exceeded</string>
<!-- Notification title when mobile data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
- <string name="data_usage_mobile_limit_snoozed_title">Mobile data limit exceeded</string>
+ <string name="data_usage_mobile_limit_snoozed_title">Cellular data limit exceeded</string>
<!-- Notification title when Wi-Fi data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
<string name="data_usage_wifi_limit_snoozed_title">Wi-Fi data limit exceeded</string>
<!-- Notification body when data usage has exceeded limit threshold. [CHAR LIMIT=32] -->
@@ -4787,21 +4782,31 @@
<!-- DO NOT TRANSLATE -->
<string name="day_of_week_label_typeface">sans-serif</string>
- <!-- Lock-to-app notification toast. The $ is not actually shown or translated, it is a marker of where the recents icon shows up. -->
- <string name="lock_to_app_toast">You are in Lock-to-App mode. Press and hold the recent apps button to exit $</string>
+ <!-- Notify use that they are in Lock-to-app -->
+ <string name="lock_to_app_toast">You are in lock-to-app mode. To exit, touch and hold the Recents button</string>
<!-- Notify user that they are locked in lock-to-app mode -->
<string name="lock_to_app_toast_locked">You are in Lock-to-App mode.</string>
<!-- Lock-to-app dialog title. -->
<string name="lock_to_app_title">Use lock-to-app?</string>
- <!-- Lock-to-app dialog description. The $ is not actually shown or translated, it is a marker of where the recents icon shows up. -->
- <string name="lock_to_app_description">Lock-to-app locks the display in a single app.\n\nTo exit press and hold the recent apps button $</string>
+ <!-- Lock-to-app dialog description. -->
+ <string name="lock_to_app_description">Lock-to-app locks the display in a single app.\n\nTo exit, touch and hold the Recents button.</string>
<!-- Lock-to-app negative response. -->
- <string name="lock_to_app_negative">NO</string>
+ <string name="lock_to_app_negative">NO, THANKS</string>
<!-- Lock-to-app positive response. -->
<string name="lock_to_app_positive">START</string>
<!-- Starting lock-to-app indication. -->
- <string name="lock_to_app_start">Start Lock-to-app</string>
+ <string name="lock_to_app_start">Locked to app</string>
<!-- Exting lock-to-app indication. -->
- <string name="lock_to_app_exit">Exit Lock-to-app</string>
+ <string name="lock_to_app_exit">No longer locked to app</string>
+
+ <!-- Lock-to-app checkbox for lock on exit -->
+ <string name="lock_to_app_use_screen_lock">Ask for %1$s before exiting</string>
+
+ <!-- Lock-to-app unlock pin string -->
+ <string name="lock_to_app_unlock_pin">PIN</string>
+ <!-- Lock-to-app unlock pattern string -->
+ <string name="lock_to_app_unlock_pattern">unlock pattern</string>
+ <!-- Lock-to-app unlock password string -->
+ <string name="lock_to_app_unlock_password">password</string>
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 0eceae6..b9cacd7 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -82,6 +82,8 @@
<item name="activityCloseExitAnimation">@anim/activity_close_exit</item>
<item name="taskOpenEnterAnimation">@anim/task_open_enter</item>
<item name="taskOpenExitAnimation">@anim/task_open_exit</item>
+ <item name="launchTaskBehindBackgroundAnimation">@anim/launch_task_behind_background</item>
+ <item name="launchTaskBehindSourceAnimation">@anim/launch_task_behind_source</item>
<item name="taskCloseEnterAnimation">@anim/task_close_enter</item>
<item name="taskCloseExitAnimation">@anim/task_close_exit</item>
<item name="taskToFrontEnterAnimation">@anim/task_open_enter</item>
@@ -566,11 +568,12 @@
</style>
<style name="Widget.TimePicker">
+ <item name="legacyMode">true</item>
<item name="legacyLayout">@layout/time_picker_legacy</item>
</style>
<style name="Widget.DatePicker">
- <item name="internalLayout">@layout/date_picker</item>
+ <item name="legacyLayout">@android:layout/date_picker_legacy</item>
<item name="calendarViewShown">false</item>
</style>
@@ -824,15 +827,9 @@
<item name="textColorLink">?textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Theme.Dialog" parent="TextAppearance.Theme">
- </style>
+ <style name="TextAppearance.Theme.Dialog" parent="TextAppearance.Theme" />
- <style name="TextAppearance.Theme.Dialog.AppError">
- <item name="textColor">#ffffc0c0</item>
- </style>
-
- <style name="TextAppearance.Widget">
- </style>
+ <style name="TextAppearance.Widget" />
<style name="TextAppearance.Widget.Button" parent="TextAppearance.Small.Inverse">
<item name="textColor">@color/primary_text_light_nodisable</item>
@@ -1206,7 +1203,6 @@
<item name="navigationButtonStyle">@style/Widget.Toolbar.Button.Navigation</item>
<item name="collapseIcon">?attr/homeAsUpIndicator</item>
<item name="contentInsetStart">16dp</item>
- <item name="touchscreenBlocksFocus">true</item>
</style>
<style name="Widget.Toolbar.Button.Navigation" parent="Widget">
@@ -1336,16 +1332,8 @@
<item name="orientation">vertical</item>
</style>
- <style name="TextAppearance.TimePicker.TimeLabel" parent="TextAppearance">
- </style>
-
- <style name="TextAppearance.TimePicker.AmPmLabel" parent="TextAppearance">
- </style>
-
- <style name="TextAppearance.Holo.TimePicker.TimeLabel" parent="TextAppearance.Holo">
- <item name="textSize">@dimen/timepicker_time_label_size</item>
- <item name="textColor">@color/timepicker_default_text_color_holo_dark</item>
- </style>
+ <style name="TextAppearance.TimePicker.TimeLabel" parent="TextAppearance" />
+ <style name="TextAppearance.TimePicker.AmPmLabel" parent="TextAppearance" />
<style name="Widget.FastScroll">
<item name="thumbDrawable">?attr/fastScrollThumbDrawable</item>
@@ -1366,8 +1354,26 @@
<item name="lightY">-200dp</item>
<item name="lightZ">800dp</item>
<item name="lightRadius">800dp</item>
- <item name="ambientShadowAlpha">0.125</item>
- <item name="spotShadowAlpha">0.25</item>
+ <item name="ambientShadowAlpha">0.0471</item>
+ <item name="spotShadowAlpha">0.1765</item>
+ </style>
+
+ <style name="TextAppearance.DatePicker.DayOfWeekLabel" parent="TextAppearance">
+ </style>
+
+ <style name="TextAppearance.DatePicker.Selector" parent="TextAppearance">
+ </style>
+
+ <style name="TextAppearance.DatePicker.Selector.MonthLabel" parent="TextAppearance.DatePicker.Selector">
+ </style>
+
+ <style name="TextAppearance.DatePicker.Selector.DayOfMonthLabel" parent="TextAppearance.DatePicker.Selector">
+ </style>
+
+ <style name="TextAppearance.DatePicker.Selector.YearLabel" parent="TextAppearance.DatePicker.Selector">
+ </style>
+
+ <style name="TextAppearance.DatePicker.List.YearLabel" parent="TextAppearance">
</style>
</resources>
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 84d38ce..fb8d9f5 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -212,8 +212,6 @@
<style name="TextAppearance.DeviceDefault.Small.Inverse" parent="TextAppearance.Material.Small.Inverse"/>
<style name="TextAppearance.DeviceDefault.SearchResult.Title" parent="TextAppearance.Material.SearchResult.Title"/>
<style name="TextAppearance.DeviceDefault.SearchResult.Subtitle" parent="TextAppearance.Material.SearchResult.Subtitle"/>
- <style name="TextAppearance.DeviceDefault.TimePicker.TimeLabel" parent="TextAppearance.Material.TimePicker.TimeLabel"/>
- <style name="TextAppearance.DeviceDefault.TimePicker.AmPmLabel" parent="TextAppearance.Material.TimePicker.AmPmLabel"/>
<style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Material.Widget"/>
<style name="TextAppearance.DeviceDefault.Widget.Button" parent="TextAppearance.Material.Widget.Button"/>
<style name="TextAppearance.DeviceDefault.Widget.IconMenu.Item" parent="TextAppearance.Material.Widget.IconMenu.Item"/>
@@ -280,4 +278,26 @@
<style name="DeviceDefault.Light.ButtonBar" parent="Widget.Material.Light.ButtonBar"/>
<style name="DeviceDefault.Light.ButtonBar.AlertDialog" parent="Widget.Material.Light.ButtonBar.AlertDialog"/>
<style name="DeviceDefault.Light.SegmentedButton" parent="Widget.Material.Light.SegmentedButton"/>
+
+ <style name="Theme.DeviceDefault.Dialog.TimePicker" parent="Theme.Material.Dialog.TimePicker"/>
+ <style name="Theme.DeviceDefault.Light.Dialog.TimePicker" parent="Theme.Material.Light.Dialog.TimePicker"/>
+
+ <style name="TextAppearance.DeviceDefault.DatePicker.DayOfWeekLabel" parent="TextAppearance.Material.DatePicker.DayOfWeekLabel"/>
+ <style name="TextAppearance.DeviceDefault.Light.DatePicker.DayOfWeekLabel" parent="TextAppearance.Material.Light.DatePicker.DayOfWeekLabel"/>
+
+ <style name="TextAppearance.DeviceDefault.DatePicker.Selector" parent="TextAppearance.Material.DatePicker.Selector"/>
+ <style name="TextAppearance.DeviceDefault.Light.DatePicker.Selector" parent="TextAppearance.Material.Light.DatePicker.Selector"/>
+
+ <style name="TextAppearance.DeviceDefault.DatePicker.Selector.MonthLabel" parent="TextAppearance.Material.DatePicker.Selector.MonthLabel"/>
+ <style name="TextAppearance.DeviceDefault.Light.DatePicker.Selector.MonthLabel" parent="TextAppearance.Material.Light.DatePicker.Selector.MonthLabel"/>
+
+ <style name="TextAppearance.DeviceDefault.DatePicker.Selector.DayOfMonthLabel" parent="TextAppearance.Material.DatePicker.Selector.DayOfMonthLabel"/>
+ <style name="TextAppearance.DeviceDefault.Light.DatePicker.Selector.DayOfMonthLabel" parent="TextAppearance.Material.Light.DatePicker.Selector.DayOfMonthLabel"/>
+
+ <style name="TextAppearance.DeviceDefault.DatePicker.Selector.YearLabel" parent="TextAppearance.Material.DatePicker.Selector.YearLabel"/>
+ <style name="TextAppearance.DeviceDefault.Light.DatePicker.Selector.YearLabel" parent="TextAppearance.Material.Light.DatePicker.Selector.YearLabel"/>
+
+ <style name="Theme.DeviceDefault.Dialog.DatePicker" parent="Theme.Material.Dialog.DatePicker"/>
+ <style name="Theme.DeviceDefault.Light.Dialog.DatePicker" parent="Theme.Material.Light.Dialog.DatePicker"/>
+
</resources>
diff --git a/core/res/res/values/styles_holo.xml b/core/res/res/values/styles_holo.xml
index 327d6b5..bf5fd29 100644
--- a/core/res/res/values/styles_holo.xml
+++ b/core/res/res/values/styles_holo.xml
@@ -462,12 +462,14 @@
</style>
<style name="Widget.Holo.TimePicker" parent="Widget.TimePicker">
+ <item name="legacyMode">true</item>
<item name="legacyLayout">@layout/time_picker_legacy_holo</item>
+ <!-- Attributes for new-style TimePicker. -->
<item name="internalLayout">@layout/time_picker_holo</item>
- <item name="disabledColor">@color/timepicker_default_disabled_color_holo_dark</item>
- <item name="headerSelectedTextColor">@color/holo_blue_light</item>
- <item name="headerUnselectedTextColor">@color/timepicker_default_text_color_holo_dark</item>
+ <item name="headerTimeTextAppearance">@style/TextAppearance.Holo.TimePicker.TimeLabel</item>
+ <item name="headerAmPmTextAppearance">@style/TextAppearance.Holo.TimePicker.AmPmLabel</item>
<item name="headerBackgroundColor">@color/timepicker_default_background_holo_dark</item>
+ <item name="headerSelectedTextColor">@color/holo_blue_light</item>
<item name="numbersTextColor">@color/timepicker_default_text_color_holo_dark</item>
<item name="numbersBackgroundColor">@color/timepicker_default_background_holo_dark</item>
<item name="amPmTextColor">@color/timepicker_default_text_color_holo_dark</item>
@@ -477,8 +479,18 @@
</style>
<style name="Widget.Holo.DatePicker" parent="Widget.DatePicker">
+ <item name="legacyLayout">@layout/date_picker_legacy_holo</item>
<item name="internalLayout">@layout/date_picker_holo</item>
<item name="calendarViewShown">true</item>
+ <item name="dateSelectorDayOfWeekBackgroundColor">?attr/datePickerHeaderDayOfWeekLabelBackgroundColor</item>
+ <item name="dateSelectorDayOfWeekTextAppearance">?attr/datePickerHeaderDayOfWeekLabelTextAppearance</item>
+ <item name="dateSelectorBackgroundColor">?attr/datePickerHeaderSelectorBackgroundColor</item>
+ <item name="dateSelectorMonthTextAppearance">?attr/datePickerHeaderSelectorMonthLabelTextAppearance</item>
+ <item name="dateSelectorDayOfMonthTextAppearance">?attr/datePickerHeaderSelectorDayOfMonthLabelTextAppearance</item>
+ <item name="dateSelectorYearTextAppearance">?attr/datePickerHeaderSelectorYearLabelTextAppearance</item>
+ <item name="dateSelectorYearListItemTextAppearance">?attr/datePickerHeaderListYearLabelTextAppearance</item>
+ <item name="dateSelectorYearListSelectedCircleColor">?attr/datePickerHeaderListYearLabelCircleBackgroundColor</item>
+ <item name="calendarTextColor">@color/date_picker_calendar_holo_dark</item>
</style>
<style name="Widget.Holo.ActivityChooserView" parent="Widget.ActivityChooserView" />
@@ -870,12 +882,14 @@
<style name="Widget.Holo.Light.NumberPicker" parent="Widget.Holo.NumberPicker" />
<style name="Widget.Holo.Light.TimePicker" parent="Widget.TimePicker">
+ <item name="legacyMode">true</item>
<item name="legacyLayout">@layout/time_picker_legacy_holo</item>
+ <!-- Non-legacy styling -->
<item name="internalLayout">@layout/time_picker_holo</item>
- <item name="disabledColor">@color/timepicker_default_disabled_color_holo_light</item>
- <item name="headerSelectedTextColor">@color/holo_blue_light</item>
- <item name="headerUnselectedTextColor">@color/timepicker_default_text_color_holo_light</item>
+ <item name="headerTimeTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.TimeLabel</item>
+ <item name="headerAmPmTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.AmPmLabel</item>
<item name="headerBackgroundColor">@color/timepicker_default_background_holo_light</item>
+ <item name="headerSelectedTextColor">@color/holo_blue_light</item>
<item name="numbersTextColor">@color/timepicker_default_text_color_holo_light</item>
<item name="numbersBackgroundColor">@color/timepicker_default_background_holo_light</item>
<item name="amPmTextColor">@color/timepicker_default_text_color_holo_light</item>
@@ -884,7 +898,20 @@
<item name="numbersSelectorColor">@color/holo_blue_light</item>
</style>
- <style name="Widget.Holo.Light.DatePicker" parent="Widget.Holo.DatePicker" />
+ <style name="Widget.Holo.Light.DatePicker" parent="Widget.DatePicker">
+ <item name="legacyLayout">@layout/date_picker_legacy_holo</item>
+ <item name="internalLayout">@layout/date_picker_holo</item>
+ <item name="calendarViewShown">true</item>
+ <item name="dateSelectorDayOfWeekBackgroundColor">?attr/datePickerHeaderDayOfWeekLabelBackgroundColor</item>
+ <item name="dateSelectorDayOfWeekTextAppearance">?attr/datePickerHeaderDayOfWeekLabelTextAppearance</item>
+ <item name="dateSelectorBackgroundColor">?attr/datePickerHeaderSelectorBackgroundColor</item>
+ <item name="dateSelectorMonthTextAppearance">?attr/datePickerHeaderSelectorMonthLabelTextAppearance</item>
+ <item name="dateSelectorDayOfMonthTextAppearance">?attr/datePickerHeaderSelectorDayOfMonthLabelTextAppearance</item>
+ <item name="dateSelectorYearTextAppearance">?attr/datePickerHeaderSelectorYearLabelTextAppearance</item>
+ <item name="dateSelectorYearListItemTextAppearance">?attr/datePickerHeaderListYearLabelTextAppearance</item>
+ <item name="dateSelectorYearListSelectedCircleColor">?attr/datePickerHeaderListYearLabelCircleBackgroundColor</item>
+ <item name="calendarTextColor">@color/date_picker_calendar_holo_light</item>
+ </style>
<style name="Widget.Holo.Light.ActivityChooserView" parent="Widget.Holo.ActivityChooserView">
<item name="background">@drawable/ab_share_pack_holo_light</item>
@@ -1183,6 +1210,11 @@
<item name="externalRouteEnabledDrawable">@drawable/ic_media_route_holo_light</item>
</style>
+ <style name="TextAppearance.Holo.TimePicker.TimeLabel" parent="TextAppearance.Holo">
+ <item name="textSize">@dimen/timepicker_time_label_size</item>
+ <item name="textColor">@color/timepicker_default_text_color_holo_dark</item>
+ </style>
+
<style name="TextAppearance.Holo.TimePicker.AmPmLabel" parent="TextAppearance.Holo">
<item name="textSize">@dimen/timepicker_ampm_label_size</item>
<item name="textAllCaps">true</item>
@@ -1202,6 +1234,62 @@
<item name="textStyle">bold</item>
</style>
+ <style name="TextAppearance.Holo.DatePicker.DayOfWeekLabel" parent="TextAppearance.Holo">
+ <item name="includeFontPadding">false</item>
+ <item name="textColor">@color/black</item>
+ <item name="textSize">@dimen/datepicker_header_text_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.DatePicker.Selector" parent="TextAppearance.Holo">
+ <item name="includeFontPadding">false</item>
+ <item name="textColor">@color/date_picker_selector_holo_dark</item>
+ </style>
+
+ <style name="TextAppearance.Holo.DatePicker.Selector.MonthLabel" parent="TextAppearance.Holo.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_month_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.DatePicker.Selector.DayOfMonthLabel" parent="TextAppearance.Holo.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_day_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.DatePicker.Selector.YearLabel" parent="TextAppearance.Holo.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_year_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.DatePicker.List.YearLabel" parent="TextAppearance.Holo">
+ <item name="textColor">@color/date_picker_year_selector_holo_dark</item>
+ <item name="textSize">@dimen/datepicker_year_label_text_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.DatePicker.DayOfWeekLabel" parent="TextAppearance.Holo">
+ <item name="includeFontPadding">false</item>
+ <item name="textColor">@color/white</item>
+ <item name="textSize">@dimen/datepicker_header_text_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.DatePicker.Selector" parent="TextAppearance.Holo">
+ <item name="includeFontPadding">false</item>
+ <item name="textColor">@color/date_picker_selector_holo_light</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.DatePicker.Selector.MonthLabel" parent="TextAppearance.Holo.Light.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_month_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.DatePicker.Selector.DayOfMonthLabel" parent="TextAppearance.Holo.Light.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_day_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.DatePicker.Selector.YearLabel" parent="TextAppearance.Holo.Light.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_year_size</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.DatePicker.List.YearLabel" parent="TextAppearance.Holo">
+ <item name="textColor">@color/date_picker_year_selector_holo_light</item>
+ <item name="textSize">@dimen/datepicker_year_label_text_size</item>
+ </style>
+
<style name="Widget.Holo.FastScroll" parent="Widget.FastScroll">
<item name="thumbMinWidth">0dp</item>
<item name="thumbMinHeight">0dp</item>
diff --git a/core/res/res/values/styles_leanback.xml b/core/res/res/values/styles_leanback.xml
index 6f9a88e..5531433 100644
--- a/core/res/res/values/styles_leanback.xml
+++ b/core/res/res/values/styles_leanback.xml
@@ -30,4 +30,30 @@
<item name="hideWheelUntilFocused">true</item>
</style>
+ <!-- Setup and form wizard themes -->
+ <style name="TextAppearance.Leanback.FormWizard" parent="@style/TextAppearance.Material">
+ <item name="textSize">18sp</item>
+ <item name="fontFamily">sans-serif-light</item>
+ </style>
+
+ <style name="TextAppearance.Leanback.FormWizard.Small" parent="@style/TextAppearance.Material.Small">
+ <item name="textSize">18sp</item>
+ <item name="fontFamily">sans-serif-light</item>
+ </style>
+
+ <style name="TextAppearance.Leanback.FormWizard.Medium" parent="@style/TextAppearance.Material.Medium">
+ <item name="textSize">36sp</item>
+ <item name="fontFamily">sans-serif-thin</item>
+ </style>
+
+ <style name="TextAppearance.Leanback.FormWizard.Large" parent="@style/TextAppearance.Material.Large">
+ <item name="textSize">56sp</item>
+ <item name="fontFamily">sans-serif-thin</item>
+ </style>
+
+ <style name="TextAppearance.Leanback.FormWizard.ListItem" parent="@style/TextAppearance.Material.Subhead">
+ <item name="textSize">18sp</item>
+ <item name="fontFamily">sans-serif-condensed</item>
+ </style>
+
</resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 4623258..6ae4f90 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -343,16 +343,72 @@
<style name="TextAppearance.Material.TimePicker.TimeLabel" parent="TextAppearance.Material">
<item name="textSize">@dimen/timepicker_time_label_size</item>
- <item name="textColor">?attr/textColorSecondary</item>
+ <item name="textColor">?attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Material.TimePicker.AmPmLabel" parent="TextAppearance.Material">
<item name="textSize">@dimen/timepicker_ampm_label_size</item>
<item name="textAllCaps">true</item>
- <item name="textColor">?attr/textColorSecondary</item>
+ <item name="textColor">?attr/textColorPrimary</item>
<item name="textStyle">bold</item>
</style>
+ <style name="TextAppearance.Material.DatePicker.DayOfWeekLabel" parent="TextAppearance.Material">
+ <item name="includeFontPadding">false</item>
+ <item name="textColor">@color/black</item>
+ <item name="textSize">@dimen/datepicker_header_text_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.DatePicker.Selector" parent="TextAppearance.Material">
+ <item name="includeFontPadding">false</item>
+ <item name="textColor">@color/date_picker_selector_material_dark</item>
+ </style>
+
+ <style name="TextAppearance.Material.DatePicker.Selector.MonthLabel" parent="TextAppearance.Material.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_month_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.DatePicker.Selector.DayOfMonthLabel" parent="TextAppearance.Material.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_day_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.DatePicker.Selector.YearLabel" parent="TextAppearance.Material.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_year_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.DatePicker.List.YearLabel" parent="TextAppearance.Material">
+ <item name="textColor">@color/date_picker_year_selector_material_dark</item>
+ <item name="textSize">@dimen/datepicker_year_label_text_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.Light.DatePicker.DayOfWeekLabel" parent="TextAppearance.Material">
+ <item name="includeFontPadding">false</item>
+ <item name="textColor">@color/white</item>
+ <item name="textSize">@dimen/datepicker_header_text_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.Light.DatePicker.Selector" parent="TextAppearance.Material">
+ <item name="includeFontPadding">false</item>
+ <item name="textColor">@color/date_picker_selector_material_light</item>
+ </style>
+
+ <style name="TextAppearance.Material.Light.DatePicker.Selector.MonthLabel" parent="TextAppearance.Material.Light.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_month_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.Light.DatePicker.Selector.DayOfMonthLabel" parent="TextAppearance.Material.Light.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_day_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.Light.DatePicker.Selector.YearLabel" parent="TextAppearance.Material.Light.DatePicker.Selector">
+ <item name="textSize">@dimen/datepicker_selected_date_year_size</item>
+ </style>
+
+ <style name="TextAppearance.Material.Light.DatePicker.List.YearLabel" parent="TextAppearance.Material">
+ <item name="textColor">@color/date_picker_year_selector_material_light</item>
+ <item name="textSize">@dimen/datepicker_year_label_text_size</item>
+ </style>
+
<style name="TextAppearance.StatusBar.Material" />
<style name="TextAppearance.StatusBar.Material.EventContent">
@@ -560,11 +616,11 @@
</style>
<style name="Widget.Material.TimePicker" parent="Widget.TimePicker">
- <item name="legacyLayout">@layout/time_picker_legacy_holo</item>
+ <item name="legacyMode">false</item>
<item name="internalLayout">@layout/time_picker_holo</item>
- <item name="disabledColor">@color/bright_foreground_disabled_material_dark</item>
+ <item name="headerTimeTextAppearance">@style/TextAppearance.Material.TimePicker.TimeLabel</item>
+ <item name="headerAmPmTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
<item name="headerSelectedTextColor">?attr/colorControlActivated</item>
- <item name="headerUnselectedTextColor">?attr/textColorPrimary</item>
<item name="headerBackgroundColor">@color/transparent</item>
<item name="numbersTextColor">?attr/textColorSecondary</item>
<item name="numbersBackgroundColor">@color/transparent</item>
@@ -575,8 +631,18 @@
</style>
<style name="Widget.Material.DatePicker" parent="Widget.DatePicker">
+ <item name="legacyLayout">@layout/date_picker_legacy_holo</item>
<item name="internalLayout">@layout/date_picker_holo</item>
<item name="calendarViewShown">true</item>
+ <item name="dateSelectorDayOfWeekBackgroundColor">?attr/datePickerHeaderDayOfWeekLabelBackgroundColor</item>
+ <item name="dateSelectorDayOfWeekTextAppearance">?attr/datePickerHeaderDayOfWeekLabelTextAppearance</item>
+ <item name="dateSelectorBackgroundColor">?attr/datePickerHeaderSelectorBackgroundColor</item>
+ <item name="dateSelectorMonthTextAppearance">?attr/datePickerHeaderSelectorMonthLabelTextAppearance</item>
+ <item name="dateSelectorDayOfMonthTextAppearance">?attr/datePickerHeaderSelectorDayOfMonthLabelTextAppearance</item>
+ <item name="dateSelectorYearTextAppearance">?attr/datePickerHeaderSelectorYearLabelTextAppearance</item>
+ <item name="dateSelectorYearListItemTextAppearance">?attr/datePickerHeaderListYearLabelTextAppearance</item>
+ <item name="dateSelectorYearListSelectedCircleColor">?attr/datePickerHeaderListYearLabelCircleBackgroundColor</item>
+ <item name="calendarTextColor">@color/date_picker_calendar_holo_dark</item>
</style>
<style name="Widget.Material.ActivityChooserView" parent="Widget.ActivityChooserView">
@@ -890,14 +956,23 @@
</style>
<style name="Widget.Material.Light.NumberPicker" parent="Widget.Material.NumberPicker"/>
+ <style name="Widget.Material.Light.TimePicker" parent="Widget.Material.TimePicker" />
- <style name="Widget.Material.Light.TimePicker" parent="Widget.Material.TimePicker">
- <item name="legacyLayout">@layout/time_picker_legacy_holo</item>
- <item name="internalLayout">@layout/time_picker_holo</item>
- <item name="disabledColor">@color/bright_foreground_disabled_material_light</item>
+ <style name="Widget.Material.Light.DatePicker" parent="Widget.DatePicker">
+ <item name="legacyLayout">@layout/date_picker_legacy_holo</item>
+ <item name="internalLayout">@layout/date_picker_holo</item>
+ <item name="calendarViewShown">true</item>
+ <item name="dateSelectorDayOfWeekBackgroundColor">?attr/datePickerHeaderDayOfWeekLabelBackgroundColor</item>
+ <item name="dateSelectorDayOfWeekTextAppearance">?attr/datePickerHeaderDayOfWeekLabelTextAppearance</item>
+ <item name="dateSelectorBackgroundColor">?attr/datePickerHeaderSelectorBackgroundColor</item>
+ <item name="dateSelectorMonthTextAppearance">?attr/datePickerHeaderSelectorMonthLabelTextAppearance</item>
+ <item name="dateSelectorDayOfMonthTextAppearance">?attr/datePickerHeaderSelectorDayOfMonthLabelTextAppearance</item>
+ <item name="dateSelectorYearTextAppearance">?attr/datePickerHeaderSelectorYearLabelTextAppearance</item>
+ <item name="dateSelectorYearListItemTextAppearance">?attr/datePickerHeaderListYearLabelTextAppearance</item>
+ <item name="dateSelectorYearListSelectedCircleColor">?attr/datePickerHeaderListYearLabelCircleBackgroundColor</item>
+ <item name="calendarTextColor">@color/date_picker_calendar_holo_light</item>
</style>
- <style name="Widget.Material.Light.DatePicker" parent="Widget.Material.DatePicker"/>
<style name="Widget.Material.Light.ActivityChooserView" parent="Widget.Material.ActivityChooserView" />
<style name="Widget.Material.Light.ImageWell" parent="Widget.Material.ImageWell"/>
<style name="Widget.Material.Light.ListView" parent="Widget.Material.ListView"/>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b22155c..08d354c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -289,6 +289,7 @@
<java-symbol type="bool" name="config_enableMultiUserUI"/>
<java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
<java-symbol type="bool" name="config_windowIsRound" />
+ <java-symbol type="bool" name="config_hasRecents" />
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
@@ -610,10 +611,14 @@
<java-symbol type="string" name="lock_to_app_description" />
<java-symbol type="string" name="lock_to_app_negative" />
<java-symbol type="string" name="lock_to_app_positive" />
- <java-symbol type="drawable" name="ic_recent" />
- <java-symbol type="layout" name="lock_to_app_enter" />
- <java-symbol type="layout" name="lock_to_app_exit" />
- <java-symbol type="drawable" name="lock_task_notify_bg" />
+ <java-symbol type="layout" name="lock_to_app_checkbox" />
+ <java-symbol type="id" name="lock_to_app_checkbox" />
+ <java-symbol type="string" name="lock_to_app_start" />
+ <java-symbol type="string" name="lock_to_app_exit" />
+ <java-symbol type="string" name="lock_to_app_use_screen_lock" />
+ <java-symbol type="string" name="lock_to_app_unlock_pin" />
+ <java-symbol type="string" name="lock_to_app_unlock_pattern" />
+ <java-symbol type="string" name="lock_to_app_unlock_password" />
<java-symbol type="string" name="lockscreen_access_pattern_cell_added" />
<java-symbol type="string" name="lockscreen_access_pattern_cleared" />
<java-symbol type="string" name="lockscreen_access_pattern_detected" />
@@ -1181,7 +1186,7 @@
<java-symbol type="layout" name="calendar_view" />
<java-symbol type="layout" name="character_picker" />
<java-symbol type="layout" name="character_picker_button" />
- <java-symbol type="layout" name="date_picker" />
+ <java-symbol type="layout" name="date_picker_legacy" />
<java-symbol type="layout" name="date_picker_dialog" />
<java-symbol type="layout" name="expanded_menu_layout" />
<java-symbol type="layout" name="fragment_bread_crumb_item" />
@@ -1497,7 +1502,7 @@
<java-symbol type="drawable" name="ic_menu_refresh" />
<java-symbol type="drawable" name="ic_settings" />
<java-symbol type="drawable" name="stat_notify_car_mode" />
- <java-symbol type="drawable" name="stat_notify_disabled" />
+ <java-symbol type="drawable" name="stat_notify_disabled_data" />
<java-symbol type="drawable" name="stat_notify_disk_full" />
<java-symbol type="drawable" name="stat_sys_adb" />
<java-symbol type="drawable" name="stat_sys_battery" />
@@ -1839,22 +1844,28 @@
<java-symbol type="dimen" name="subtitle_shadow_offset" />
<java-symbol type="dimen" name="subtitle_outline_width" />
- <!-- From the new TimePicker -->
- <java-symbol type="attr" name="timePickerHeaderBackgroundColor" />
+ <!-- From the new TimePicker and DatePicker -->
<java-symbol type="attr" name="timePickerDialogTheme" />
<java-symbol type="attr" name="headerSelectedTextColor" />
- <java-symbol type="attr" name="headerUnselectedTextColor" />
<java-symbol type="attr" name="numbersTextColor" />
<java-symbol type="attr" name="numbersBackgroundColor" />
<java-symbol type="attr" name="amPmTextColor" />
<java-symbol type="attr" name="amPmUnselectedBackgroundColor" />
<java-symbol type="attr" name="amPmSelectedBackgroundColor" />
<java-symbol type="attr" name="numbersSelectorColor" />
- <java-symbol type="attr" name="timePickerHeaderTimeLabelTextAppearance" />
<java-symbol type="attr" name="nestedScrollingEnabled" />
+ <java-symbol type="attr" name="datePickerDialogTheme" />
+ <java-symbol type="attr" name="datePickerHeaderSelectorBackgroundColor" />
+ <java-symbol type="attr" name="datePickerHeaderListYearLabelCircleBackgroundColor" />
+ <java-symbol type="attr" name="calendarTextColor" />
+
<java-symbol type="style" name="TextAppearance.Holo.TimePicker.TimeLabel" />
+
<java-symbol type="layout" name="time_picker_holo" />
<java-symbol type="layout" name="time_header_label" />
+ <java-symbol type="layout" name="year_label_text_view" />
+ <java-symbol type="layout" name="date_picker_holo" />
+
<java-symbol type="id" name="time_header" />
<java-symbol type="id" name="hours" />
<java-symbol type="id" name="minutes" />
@@ -1863,6 +1874,15 @@
<java-symbol type="id" name="separator" />
<java-symbol type="id" name="layout_buttons" />
<java-symbol type="id" name="done_button" />
+ <java-symbol type="id" name="date_picker_header" />
+ <java-symbol type="id" name="date_picker_month_and_day_layout" />
+ <java-symbol type="id" name="day_picker_selector_layout" />
+ <java-symbol type="id" name="date_picker_month" />
+ <java-symbol type="id" name="date_picker_day" />
+ <java-symbol type="id" name="date_picker_year" />
+ <java-symbol type="id" name="animator" />
+ <java-symbol type="id" name="done" />
+
<java-symbol type="string" name="done_label" />
<java-symbol type="string" name="hour_picker_description" />
<java-symbol type="string" name="minute_picker_description" />
@@ -1884,7 +1904,41 @@
<java-symbol type="string" name="timepicker_numbers_radius_multiplier_normal" />
<java-symbol type="string" name="timepicker_transition_mid_radius_multiplier" />
<java-symbol type="string" name="timepicker_transition_end_radius_multiplier" />
+
+ <java-symbol type="string" name="item_is_selected" />
+ <java-symbol type="string" name="day_of_week_label_typeface" />
+ <java-symbol type="string" name="select_day" />
+ <java-symbol type="string" name="day_picker_description" />
+ <java-symbol type="string" name="select_year" />
+ <java-symbol type="string" name="year_picker_description" />
+
+ <java-symbol type="dimen" name="datepicker_day_number_size" />
+ <java-symbol type="dimen" name="datepicker_month_label_size" />
+ <java-symbol type="dimen" name="datepicker_month_day_label_text_size" />
+ <java-symbol type="dimen" name="datepicker_month_list_item_header_height" />
+ <java-symbol type="dimen" name="datepicker_day_number_select_circle_radius" />
+ <java-symbol type="dimen" name="datepicker_view_animator_height" />
+ <java-symbol type="dimen" name="datepicker_year_label_height" />
+ <java-symbol type="dimen" name="datepicker_year_picker_padding_top" />
+
+ <java-symbol type="color" name="timepicker_default_text_color_holo_light" />
+ <java-symbol type="color" name="timepicker_default_ampm_unselected_background_color_holo_light" />
+ <java-symbol type="color" name="timepicker_default_ampm_selected_background_color_holo_light" />
+
+ <java-symbol type="color" name="datepicker_default_normal_text_color_holo_light" />
+ <java-symbol type="color" name="datepicker_default_disabled_text_color_holo_light" />
+ <java-symbol type="color" name="datepicker_default_circle_background_color_holo_light" />
+ <java-symbol type="color" name="datepicker_default_header_dayofweek_background_color_holo_light" />
+ <java-symbol type="color" name="datepicker_default_header_selector_background_holo_light" />
+
+ <java-symbol type="color" name="datepicker_default_normal_text_color_material_light" />
+ <java-symbol type="color" name="datepicker_default_disabled_text_color_material_light" />
+ <java-symbol type="color" name="datepicker_default_circle_background_color_material_light" />
+ <java-symbol type="color" name="datepicker_default_header_dayofweek_background_color_material_light" />
+ <java-symbol type="color" name="datepicker_default_header_selector_background_material_light" />
+
<java-symbol type="array" name="config_clockTickVibePattern" />
+ <java-symbol type="array" name="config_calendarDateVibePattern" />
<!-- From various Material changes -->
<java-symbol type="attr" name="toolbarStyle" />
@@ -1896,7 +1950,6 @@
<java-symbol type="style" name="Animation.VolumePanel" />
<java-symbol type="transition" name="no_transition" />
<java-symbol type="color" name="timepicker_default_text_color_material" />
- <java-symbol type="color" name="timepicker_default_disabled_color_material" />
<java-symbol type="color" name="timepicker_default_ampm_unselected_background_color_material" />
<java-symbol type="color" name="timepicker_default_ampm_selected_background_color_material" />
<java-symbol type="color" name="timepicker_default_selector_color_material" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 6ada975..0d4a2bf 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -394,22 +394,40 @@
<!-- TimePicker style -->
<item name="timePickerStyle">@style/Widget.TimePicker</item>
- <!-- TimePicker background color -->
- <item name="timePickerHeaderBackgroundColor">@color/darker_gray</item>
-
- <!-- TimePicker Header time label text appearance -->
- <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.TimePicker.TimeLabel</item>
-
- <!-- TimePicker Header am pm label text appearance -->
- <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.TimePicker.AmPmLabel</item>
-
<!-- TimePicker dialog theme -->
<item name="timePickerDialogTheme">@style/Theme.Dialog.TimePicker</item>
<!-- DatePicker style -->
<item name="datePickerStyle">@style/Widget.DatePicker</item>
- <item name="fastScrollThumbDrawable">@drawable/scrollbar_handle_accelerated_anim2</item>
+ <!-- DatePicker Header day of week label background color -->
+ <item name="datePickerHeaderDayOfWeekLabelBackgroundColor">@android:color/darker_gray</item>
+
+ <!-- DatePicker Header day of week label text appearance -->
+ <item name="datePickerHeaderDayOfWeekLabelTextAppearance">@style/TextAppearance.DatePicker.DayOfWeekLabel</item>
+
+ <!-- DatePicker Header selector background color -->
+ <item name="datePickerHeaderSelectorBackgroundColor">@android:color/darker_gray</item>
+
+ <!-- DatePicker Header selector month label text appearance -->
+ <item name="datePickerHeaderSelectorMonthLabelTextAppearance">@style/TextAppearance.DatePicker.Selector.MonthLabel</item>
+
+ <!-- DatePicker Header selector day of month label text appearance -->
+ <item name="datePickerHeaderSelectorDayOfMonthLabelTextAppearance">@style/TextAppearance.DatePicker.Selector.DayOfMonthLabel</item>
+
+ <!-- DatePicker Header selector year label text appearance -->
+ <item name="datePickerHeaderSelectorYearLabelTextAppearance">@style/TextAppearance.DatePicker.Selector.YearLabel</item>
+
+ <!-- DatePicker list year label text appearance -->
+ <item name="datePickerHeaderListYearLabelTextAppearance">@style/TextAppearance.DatePicker.List.YearLabel</item>
+
+ <!-- DatePicker list year label circle background color -->
+ <item name="datePickerHeaderListYearLabelCircleBackgroundColor">@android:color/darker_gray</item>
+
+ <!-- DatePicker dialog theme -->
+ <item name="datePickerDialogTheme">@android:style/Theme.Dialog.DatePicker</item>
+
+ <item name="fastScrollThumbDrawable">@android:drawable/scrollbar_handle_accelerated_anim2</item>
<item name="fastScrollTrackDrawable">@null</item>
<item name="fastScrollPreviewBackgroundRight">@drawable/menu_submenu_background</item>
<item name="fastScrollPreviewBackgroundLeft">@drawable/menu_submenu_background</item>
@@ -731,6 +749,14 @@
<item name="windowContentOverlay">@null</item>
</style>
+ <!-- Default heme for the DatePicker dialog windows, which is used by the
+ {@link android.app.DatePickerDialog} class. -->
+ <style name="Theme.Dialog.DatePicker">
+ <item name="windowBackground">@android:color/transparent</item>
+ <item name="windowTitleStyle">@android:style/DialogWindowTitle</item>
+ <item name="windowContentOverlay">@null</item>
+ </style>
+
<!-- Default dark theme for panel windows (on API level 10 and lower). This removes all
extraneous window decorations, so you basically have an empty rectangle in which
to place your content. It makes the window floating, with a transparent
@@ -820,21 +846,14 @@
<eat-comment />
<!-- Theme for the dialog shown when an app crashes or ANRs. -->
- <style name="Theme.Dialog.AppError" parent="Theme.DeviceDefault.Light.Dialog">
- <item name="windowFrame">@null</item>
- <item name="windowTitleStyle">@style/DialogWindowTitle</item>
- <item name="windowBackground">@color/transparent</item>
- <item name="windowIsFloating">true</item>
- <item name="windowContentOverlay">@null</item>
+ <style name="Theme.Dialog.AppError" parent="Theme.DeviceDefault.Light.Dialog.Alert">
<item name="windowContentTransitions">false</item>
- <item name="textAppearance">@style/TextAppearance.Theme.Dialog.AppError</item>
<item name="windowCloseOnTouchOutside">false</item>
</style>
<!-- Special theme for the recent apps dialog, to allow customization
with overlays. -->
<style name="Theme.Dialog.RecentApplications" parent="Theme.DeviceDefault.Light.Dialog">
- <item name="windowFrame">@null</item>
<item name="windowBackground">@color/transparent</item>
<item name="windowAnimationStyle">@style/Animation.RecentApplications</item>
<item name="textColor">@color/secondary_text_nofocus</item>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index ee2c7df..43381d6 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -195,19 +195,29 @@
<!-- TimePicker style -->
<item name="timePickerStyle">@style/Widget.DeviceDefault.TimePicker</item>
- <!-- TimePicker Header time label text appearance -->
- <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.DeviceDefault.TimePicker.TimeLabel</item>
-
- <!-- TimePicker Header am pm label text appearance -->
- <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.DeviceDefault.TimePicker.AmPmLabel</item>
-
<!-- TimePicker dialog theme -->
<item name="timePickerDialogTheme">@style/Theme.DeviceDefault.Dialog.TimePicker</item>
<!-- DatePicker style -->
<item name="datePickerStyle">@style/Widget.DeviceDefault.DatePicker</item>
+ <!-- The DatePicker Header day of week label text appearance -->
+ <item name="datePickerHeaderDayOfWeekLabelTextAppearance">@style/TextAppearance.DeviceDefault.DatePicker.DayOfWeekLabel</item>
+
+ <!-- The DatePicker Header selector month label text appearance -->
+ <item name="datePickerHeaderSelectorMonthLabelTextAppearance">@style/TextAppearance.DeviceDefault.DatePicker.Selector.MonthLabel</item>
+
+ <!-- The DatePicker Header selector day of month label text appearance -->
+ <item name="datePickerHeaderSelectorDayOfMonthLabelTextAppearance">@style/TextAppearance.DeviceDefault.DatePicker.Selector.DayOfMonthLabel</item>
+
+ <!-- The DatePicker Header selector year label text appearance -->
+ <item name="datePickerHeaderSelectorYearLabelTextAppearance">@style/TextAppearance.DeviceDefault.DatePicker.Selector.YearLabel</item>
+
+ <!-- DatePicker dialog theme -->
+ <item name="datePickerDialogTheme">@android:style/Theme.DeviceDefault.Dialog.DatePicker</item>
+
<item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.MediaRouteButton</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with no action bar -->
@@ -454,19 +464,29 @@
<!-- TimePicker style -->
<item name="timePickerStyle">@style/Widget.DeviceDefault.Light.TimePicker</item>
- <!-- TimePicker Header time label text appearance -->
- <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.DeviceDefault.TimePicker.TimeLabel</item>
-
- <!-- TimePicker Header am pm label text appearance -->
- <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.DeviceDefault.TimePicker.AmPmLabel</item>
-
<!-- TimePicker dialog theme -->
<item name="timePickerDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.TimePicker</item>
<!-- DatePicker style -->
<item name="datePickerStyle">@style/Widget.DeviceDefault.Light.DatePicker</item>
+ <!-- The DatePicker Header day of week label text appearance -->
+ <item name="datePickerHeaderDayOfWeekLabelTextAppearance">@style/TextAppearance.DeviceDefault.Light.DatePicker.DayOfWeekLabel</item>
+
+ <!-- The DatePicker Header selector month label text appearance -->
+ <item name="datePickerHeaderSelectorMonthLabelTextAppearance">@style/TextAppearance.DeviceDefault.Light.DatePicker.Selector.MonthLabel</item>
+
+ <!-- The DatePicker Header selector day of month label text appearance -->
+ <item name="datePickerHeaderSelectorDayOfMonthLabelTextAppearance">@style/TextAppearance.DeviceDefault.Light.DatePicker.Selector.DayOfMonthLabel</item>
+
+ <!-- The DatePicker Header selector year label text appearance -->
+ <item name="datePickerHeaderSelectorYearLabelTextAppearance">@style/TextAppearance.DeviceDefault.Light.DatePicker.Selector.YearLabel</item>
+
+ <!-- DatePicker dialog theme -->
+ <item name="datePickerDialogTheme">@android:style/Theme.DeviceDefault.Light.Dialog.DatePicker</item>
+
<item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.Light.MediaRouteButton</item>
+
</style>
<!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
diff --git a/core/res/res/values/themes_holo.xml b/core/res/res/values/themes_holo.xml
index 76bfc4b..f6c6b4c 100644
--- a/core/res/res/values/themes_holo.xml
+++ b/core/res/res/values/themes_holo.xml
@@ -374,21 +374,39 @@
<!-- TimePicker style -->
<item name="timePickerStyle">@style/Widget.Holo.TimePicker</item>
- <!-- TimePicker background color -->
- <item name="timePickerHeaderBackgroundColor">@color/timepicker_default_background_holo_dark</item>
-
- <!-- TimePicker Header time label text appearance -->
- <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Holo.TimePicker.TimeLabel</item>
-
- <!-- TimePicker Header am pm label text appearance -->
- <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.Holo.TimePicker.AmPmLabel</item>
-
<!-- TimePicker dialog theme -->
<item name="timePickerDialogTheme">@style/Theme.Holo.Dialog.TimePicker</item>
<!-- DatePicker style -->
<item name="datePickerStyle">@style/Widget.Holo.DatePicker</item>
+ <!-- DatePicker Header day of week label background color -->
+ <item name="datePickerHeaderDayOfWeekLabelBackgroundColor">@android:color/datepicker_default_header_dayofweek_background_color_holo_dark</item>
+
+ <!-- DatePicker Header day of week label text appearance -->
+ <item name="datePickerHeaderDayOfWeekLabelTextAppearance">@style/TextAppearance.Holo.DatePicker.DayOfWeekLabel</item>
+
+ <!-- DatePicker Header selector background color -->
+ <item name="datePickerHeaderSelectorBackgroundColor">@android:color/datepicker_default_header_selector_background_holo_dark</item>
+
+ <!-- DatePicker Header selector month label text appearance -->
+ <item name="datePickerHeaderSelectorMonthLabelTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.MonthLabel</item>
+
+ <!-- DatePicker Header selector day of month label text appearance -->
+ <item name="datePickerHeaderSelectorDayOfMonthLabelTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.DayOfMonthLabel</item>
+
+ <!-- DatePicker Header selector year label text appearance -->
+ <item name="datePickerHeaderSelectorYearLabelTextAppearance">@style/TextAppearance.Holo.DatePicker.Selector.YearLabel</item>
+
+ <!-- DatePicker list year label text appearance -->
+ <item name="datePickerHeaderListYearLabelTextAppearance">@style/TextAppearance.Holo.DatePicker.List.YearLabel</item>
+
+ <!-- DatePicker list year label circle background color -->
+ <item name="datePickerHeaderListYearLabelCircleBackgroundColor">@android:color/datepicker_default_circle_background_color_holo_dark</item>
+
+ <!-- DatePicker dialog theme -->
+ <item name="datePickerDialogTheme">@android:style/Theme.Holo.Dialog.DatePicker</item>
+
<item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_holo</item>
<item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_dark</item>
<item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_dark</item>
@@ -713,21 +731,39 @@
<!-- TimePicker style -->
<item name="timePickerStyle">@style/Widget.Holo.Light.TimePicker</item>
- <!-- TimePicker Header background color -->
- <item name="timePickerHeaderBackgroundColor">@color/timepicker_default_background_holo_light</item>
-
- <!-- TimePicker Header time label text appearance -->
- <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.TimeLabel</item>
-
- <!-- TimePicker Header am pm label text appearance -->
- <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.Holo.Light.TimePicker.AmPmLabel</item>
-
<!-- TimePicker dialog theme -->
<item name="timePickerDialogTheme">@style/Theme.Holo.Light.Dialog.TimePicker</item>
<!-- DatePicker style -->
<item name="datePickerStyle">@style/Widget.Holo.Light.DatePicker</item>
+ <!-- DatePicker Header day of week label background color -->
+ <item name="datePickerHeaderDayOfWeekLabelBackgroundColor">@android:color/datepicker_default_header_dayofweek_background_color_holo_light</item>
+
+ <!-- DatePicker Header day of week label text appearance -->
+ <item name="datePickerHeaderDayOfWeekLabelTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.DayOfWeekLabel</item>
+
+ <!-- DatePicker Header selector background color -->
+ <item name="datePickerHeaderSelectorBackgroundColor">@android:color/datepicker_default_header_selector_background_holo_light</item>
+
+ <!-- DatePicker Header selector month label text appearance -->
+ <item name="datePickerHeaderSelectorMonthLabelTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.MonthLabel</item>
+
+ <!-- DatePicker Header selector day of month label text appearance -->
+ <item name="datePickerHeaderSelectorDayOfMonthLabelTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.DayOfMonthLabel</item>
+
+ <!-- DatePicker Header selector year label text appearance -->
+ <item name="datePickerHeaderSelectorYearLabelTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.Selector.YearLabel</item>
+
+ <!-- DatePicker list year label text appearance -->
+ <item name="datePickerHeaderListYearLabelTextAppearance">@style/TextAppearance.Holo.Light.DatePicker.List.YearLabel</item>
+
+ <!-- DatePicker list year label circle background color -->
+ <item name="datePickerHeaderListYearLabelCircleBackgroundColor">@android:color/datepicker_default_circle_background_color_holo_light</item>
+
+ <!-- DatePicker dialog theme -->
+ <item name="datePickerDialogTheme">@android:style/Theme.Holo.Light.Dialog.DatePicker</item>
+
<item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_holo</item>
<item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_light</item>
<item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_light</item>
@@ -944,6 +980,14 @@
{@link android.app.TimePickerDialog} class. -->
<style name="Theme.Holo.Dialog.TimePicker" parent="Theme.Holo.Dialog.Alert" />
+ <!-- Holo theme for the DatePicker dialog windows, which is used by the
+ {@link android.app.DatePickerDialog} class. -->
+ <style name="Theme.Holo.Dialog.DatePicker">
+ <item name="windowBackground">@color/transparent</item>
+ <item name="windowTitleStyle">@style/DialogWindowTitle.Holo</item>
+ <item name="windowContentOverlay">@null</item>
+ </style>
+
<!-- Theme for a window that will be displayed either full-screen on
smaller screens (small, normal) or as a dialog on larger screens
(large, xlarge). -->
@@ -1059,6 +1103,14 @@
{@link android.app.TimePickerDialog} class. -->
<style name="Theme.Holo.Light.Dialog.TimePicker" parent="Theme.Holo.Light.Dialog.Alert" />
+ <!-- Holo Light theme for the DatePicker dialog windows, which is used by the
+ {@link android.app.DatePickerDialog} class. -->
+ <style name="Theme.Holo.Light.Dialog.DatePicker">
+ <item name="windowBackground">@android:color/transparent</item>
+ <item name="windowTitleStyle">@android:style/DialogWindowTitle.Holo.Light</item>
+ <item name="windowContentOverlay">@null</item>
+ </style>
+
<!-- Theme for a presentation window on a secondary display. -->
<style name="Theme.Holo.Light.Dialog.Presentation" parent="Theme.Holo.Light.NoActionBar.Fullscreen" />
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index 6f6385b..636216d 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -31,6 +31,7 @@
</style>
<style name="Theme.Leanback.Dialog.TimePicker" parent="Theme.Material.Dialog.BaseTimePicker">
+ <item name="legacyMode">true</item>
<item name="colorBackground">@color/background_leanback_dark</item>
<item name="textColorPrimary">@color/primary_text_leanback_dark</item>
<item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
@@ -40,6 +41,7 @@
</style>
<style name="Theme.Leanback.Light.Dialog.TimePicker" parent="Theme.Material.Light.Dialog.BaseTimePicker">
+ <item name="legacyMode">true</item>
<item name="colorBackground">@color/background_leanback_light</item>
<item name="textColorPrimary">@color/primary_text_leanback_light</item>
<item name="textColorSecondary">@color/secondary_text_leanback_light</item>
@@ -62,4 +64,16 @@
<item name="windowCloseOnTouchOutside">false</item>
<item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
</style>
+
+ <!-- Setup and form wizard themes @hide @SystemApi-->
+ <style name="Theme.Leanback.FormWizard" parent="Theme.Material.NoActionBar">
+ <item name="windowBackground">@drawable/background_leanback_setup</item>
+ <item name="colorBackgroundCacheHint">@null</item>
+ <item name="windowShowWallpaper">false</item>
+ <item name="textAppearanceSmall">@style/TextAppearance.Leanback.FormWizard.Small</item>
+ <item name="textAppearanceMedium">@style/TextAppearance.Leanback.FormWizard.Medium</item>
+ <item name="textAppearanceLarge">@style/TextAppearance.Leanback.FormWizard.Large</item>
+ <item name="textAppearanceListItem">@style/TextAppearance.Leanback.FormWizard.ListItem</item>
+ <item name="textAppearance">@style/TextAppearance.Leanback.FormWizard</item>
+ </style>
</resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 47f3778..741ffe6 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -352,21 +352,39 @@
<!-- TimePicker style -->
<item name="timePickerStyle">@style/Widget.Material.TimePicker</item>
- <!-- TimePicker background color -->
- <item name="timePickerHeaderBackgroundColor">?colorBackground</item>
-
- <!-- TimePicker Header time label text appearance -->
- <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Material.TimePicker.TimeLabel</item>
-
- <!-- TimePicker Header am pm label text appearance -->
- <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
-
<!-- TimePicker dialog theme -->
<item name="timePickerDialogTheme">@style/Theme.Material.Dialog.TimePicker</item>
<!-- DatePicker style -->
<item name="datePickerStyle">@style/Widget.Material.DatePicker</item>
+ <!-- DatePicker Header day of week label background color -->
+ <item name="datePickerHeaderDayOfWeekLabelBackgroundColor">@android:color/datepicker_default_header_dayofweek_background_color_material_dark</item>
+
+ <!-- DatePicker Header day of week label text appearance -->
+ <item name="datePickerHeaderDayOfWeekLabelTextAppearance">@style/TextAppearance.Material.DatePicker.DayOfWeekLabel</item>
+
+ <!-- DatePicker Header selector background color -->
+ <item name="datePickerHeaderSelectorBackgroundColor">@android:color/datepicker_default_header_selector_background_material_dark</item>
+
+ <!-- DatePicker Header selector month label text appearance -->
+ <item name="datePickerHeaderSelectorMonthLabelTextAppearance">@style/TextAppearance.Material.DatePicker.Selector.MonthLabel</item>
+
+ <!-- DatePicker Header selector day of month label text appearance -->
+ <item name="datePickerHeaderSelectorDayOfMonthLabelTextAppearance">@style/TextAppearance.Material.DatePicker.Selector.DayOfMonthLabel</item>
+
+ <!-- DatePicker Header selector year label text appearance -->
+ <item name="datePickerHeaderSelectorYearLabelTextAppearance">@style/TextAppearance.Material.DatePicker.Selector.YearLabel</item>
+
+ <!-- DatePicker list year label text appearance -->
+ <item name="datePickerHeaderListYearLabelTextAppearance">@style/TextAppearance.Material.DatePicker.List.YearLabel</item>
+
+ <!-- DatePicker list year label circle background color -->
+ <item name="datePickerHeaderListYearLabelCircleBackgroundColor">@android:color/datepicker_default_circle_background_color_material_dark</item>
+
+ <!-- DatePicker dialog theme -->
+ <item name="datePickerDialogTheme">@android:style/Theme.Material.Dialog.DatePicker</item>
+
<!-- TODO: This belongs in a FastScroll style -->
<item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_material</item>
<item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_dark</item>
@@ -700,21 +718,39 @@
<!-- TimePicker style -->
<item name="timePickerStyle">@style/Widget.Material.Light.TimePicker</item>
- <!-- TimePicker Header background color -->
- <item name="timePickerHeaderBackgroundColor">?attr/colorBackground</item>
-
- <!-- TimePicker Header time label text appearance -->
- <item name="timePickerHeaderTimeLabelTextAppearance">@style/TextAppearance.Material.TimePicker.TimeLabel</item>
-
- <!-- TimePicker Header am pm label text appearance -->
- <item name="timePickerHeaderAmPmLabelTextAppearance">@style/TextAppearance.Material.TimePicker.AmPmLabel</item>
-
<!-- TimePicker dialog theme -->
<item name="timePickerDialogTheme">@style/Theme.Material.Light.Dialog.TimePicker</item>
<!-- DatePicker style -->
<item name="datePickerStyle">@style/Widget.Material.Light.DatePicker</item>
+ <!-- DatePicker Header day of week label background color -->
+ <item name="datePickerHeaderDayOfWeekLabelBackgroundColor">@android:color/datepicker_default_header_dayofweek_background_color_material_light</item>
+
+ <!-- DatePicker Header day of week label text appearance -->
+ <item name="datePickerHeaderDayOfWeekLabelTextAppearance">@style/TextAppearance.Material.Light.DatePicker.DayOfWeekLabel</item>
+
+ <!-- DatePicker Header selector background color -->
+ <item name="datePickerHeaderSelectorBackgroundColor">@android:color/datepicker_default_header_selector_background_material_light</item>
+
+ <!-- DatePicker Header selector month label text appearance -->
+ <item name="datePickerHeaderSelectorMonthLabelTextAppearance">@style/TextAppearance.Material.Light.DatePicker.Selector.MonthLabel</item>
+
+ <!-- DatePicker Header selector day of month label text appearance -->
+ <item name="datePickerHeaderSelectorDayOfMonthLabelTextAppearance">@style/TextAppearance.Material.Light.DatePicker.Selector.DayOfMonthLabel</item>
+
+ <!-- DatePicker Header selector year label text appearance -->
+ <item name="datePickerHeaderSelectorYearLabelTextAppearance">@style/TextAppearance.Material.Light.DatePicker.Selector.YearLabel</item>
+
+ <!-- DatePicker list year label text appearance -->
+ <item name="datePickerHeaderListYearLabelTextAppearance">@style/TextAppearance.Material.Light.DatePicker.List.YearLabel</item>
+
+ <!-- DatePicker list year label circle background color -->
+ <item name="datePickerHeaderListYearLabelCircleBackgroundColor">@android:color/datepicker_default_circle_background_color_material_light</item>
+
+ <!-- DatePicker dialog theme -->
+ <item name="datePickerDialogTheme">@android:style/Theme.Material.Light.Dialog.DatePicker</item>
+
<item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_material</item>
<item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_light</item>
<item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_light</item>
@@ -1011,7 +1047,8 @@
<style name="Theme.Material.Dialog">
<item name="windowFrame">@null</item>
<item name="windowTitleStyle">@style/DialogWindowTitle.Material</item>
- <item name="windowBackground">@drawable/dialog_background_shadow_material</item>
+ <item name="windowBackground">@drawable/dialog_background_material</item>
+ <item name="windowElevation">@dimen/floating_window_z</item>
<item name="windowIsFloating">true</item>
<item name="windowContentOverlay">@null</item>
<item name="windowAnimationStyle">@style/Animation.Material.Dialog</item>
@@ -1077,6 +1114,7 @@
its pixels. -->
<style name="Theme.Material.Dialog.NoFrame">
<item name="windowBackground">@color/transparent</item>
+ <item name="windowElevation">0dp</item>
<item name="windowAnimationStyle">@null</item>
<item name="backgroundDimEnabled">false</item>
<item name="windowIsTranslucent">true</item>
@@ -1085,7 +1123,6 @@
</style>
<style name="Theme.Material.Dialog.BaseAlert">
- <item name="windowBackground">@color/transparent</item>
<item name="windowTitleStyle">@style/DialogWindowTitle.Material</item>
<item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
<item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
@@ -1098,15 +1135,22 @@
AlertDialog theme. -->
<style name="Theme.Material.Dialog.Alert" parent="Theme.Material.Dialog.BaseAlert"/>
- <style name="Theme.Material.Dialog.BaseTimePicker">
+ <!-- Base theme used to prevent circular references in Leanback overrides. -->
+ <style name="Theme.Material.Dialog.BaseTimePicker" />
+
+ <!-- Material theme for the TimePicker dialog windows, which is used by the
+ {@link android.app.TimePickerDialog} class. -->
+ <style name="Theme.Material.Dialog.TimePicker" parent="Theme.Material.Dialog.BaseTimePicker"/>
+
+ <style name="Theme.Material.Dialog.BaseDatePicker">
<item name="windowBackground">@color/transparent</item>
<item name="windowTitleStyle">@style/DialogWindowTitle.Material</item>
<item name="windowContentOverlay">@null</item>
</style>
- <!-- Material theme for the TimePicker dialog windows, which is used by the
- {@link android.app.TimePickerDialog} class. -->
- <style name="Theme.Material.Dialog.TimePicker" parent="Theme.Material.Dialog.BaseTimePicker"/>
+ <!-- Material theme for the DatePicker dialog windows, which is used by the
+ {@link android.app.DatePickerDialog} class. -->
+ <style name="Theme.Material.Dialog.DatePicker" parent="Theme.Material.Dialog.BaseDatePicker"/>
<!-- Theme for a window that will be displayed either full-screen on
smaller screens (small, normal) or as a dialog on larger screens
@@ -1131,7 +1175,8 @@
<style name="Theme.Material.Light.Dialog">
<item name="windowFrame">@null</item>
<item name="windowTitleStyle">@style/DialogWindowTitle.Material.Light</item>
- <item name="windowBackground">@drawable/dialog_background_shadow_material</item>
+ <item name="windowBackground">@drawable/dialog_background_material</item>
+ <item name="windowElevation">@dimen/floating_window_z</item>
<item name="windowIsFloating">true</item>
<item name="windowContentOverlay">@null</item>
<item name="windowAnimationStyle">@style/Animation.Material.Dialog</item>
@@ -1203,7 +1248,6 @@
<style name="Theme.Material.Light.DialogWhenLarge.NoActionBar" parent="@style/Theme.Material.Light.NoActionBar" />
<style name="Theme.Material.Light.Dialog.BaseAlert">
- <item name="windowBackground">@color/transparent</item>
<item name="windowTitleStyle">@style/DialogWindowTitle.Material.Light</item>
<item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
<item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
@@ -1216,14 +1260,22 @@
AlertDialog theme. -->
<style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.BaseAlert"/>
- <style name="Theme.Material.Light.Dialog.BaseTimePicker">
- <item name="windowBackground">@color/transparent</item>
- <item name="windowTitleStyle">@style/DialogWindowTitle.Material.Light</item>
- </style>
+ <!-- Base theme used to prevent circular references in Leanback overrides. -->
+ <style name="Theme.Material.Light.Dialog.BaseTimePicker" />
<!-- Material Light theme for the TimePicker dialog windows, which is used by the
{@link android.app.TimePickerDialog} class. -->
- <style name="Theme.Material.Light.Dialog.TimePicker" parent="Theme.Material.Light.Dialog.BaseTimePicker"/>
+ <style name="Theme.Material.Light.Dialog.TimePicker" parent="Theme.Material.Light.Dialog.BaseTimePicker" />
+
+ <style name="Theme.Material.Light.Dialog.BaseDatePicker">
+ <item name="windowBackground">@color/transparent</item>
+ <item name="windowTitleStyle">@style/DialogWindowTitle.Material.Light</item>
+ <item name="windowContentOverlay">@null</item>
+ </style>
+
+ <!-- Material Light theme for the DatePicker dialog windows, which is used by the
+ {@link android.app.DatePickerDialog} class. -->
+ <style name="Theme.Material.Light.Dialog.DatePicker" parent="Theme.Material.Light.Dialog.BaseDatePicker"/>
<!-- Theme for a presentation window on a secondary display. -->
<style name="Theme.Material.Light.Dialog.Presentation" parent="@style/Theme.Material.Light.NoActionBar.Fullscreen" />
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index a2cc40c..b524177 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1257,4 +1257,11 @@
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.android.frameworks.coretests"
android:label="Frameworks Core Tests" />
+ <key-sets>
+ <key-set android:name="A" >
+ <public-key android:name="keyA"
+ android:value="MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJoN1Nsgqf0V4C/bbN8wo8O2X/S5D76+5Mb9mlIsHkUTUTbHCNk+LxHIUYLm89YbP9zImrV0bUHLUAZUyoMUCiMCAwEAAQ=="/>
+ </key-set>
+ <upgrade-key-set android:name="A"/>
+ </key-sets>
</manifest>
diff --git a/core/tests/coretests/apks/keyset/Android.mk b/core/tests/coretests/apks/keyset/Android.mk
index e44ac6c..306dc90 100644
--- a/core/tests/coretests/apks/keyset/Android.mk
+++ b/core/tests/coretests/apks/keyset/Android.mk
@@ -88,4 +88,21 @@
LOCAL_CERTIFICATE := $(LOCAL_PATH)/../../certs/keyset_A
LOCAL_ADDITIONAL_CERTIFICATES := $(LOCAL_PATH)/../../certs/keyset_B
LOCAL_MANIFEST_FILE := uB/AndroidManifest.xml
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+#apks signed by platform only
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := keyset_splat_api
+LOCAL_CERTIFICATE := platform
+LOCAL_MANIFEST_FILE := api_test/AndroidManifest.xml
+include $(FrameworkCoreTests_BUILD_PACKAGE)
+
+#apks signed by platform and keyset_A
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_PACKAGE_NAME := keyset_splata_api
+LOCAL_CERTIFICATE := platform
+LOCAL_ADDITIONAL_CERTIFICATES := $(LOCAL_PATH)/../../certs/keyset_A
+LOCAL_MANIFEST_FILE := api_test/AndroidManifest.xml
include $(FrameworkCoreTests_BUILD_PACKAGE)
\ No newline at end of file
diff --git a/core/res/res/drawable/lock_task_notify_bg.xml b/core/tests/coretests/apks/keyset/api_test/AndroidManifest.xml
similarity index 69%
copy from core/res/res/drawable/lock_task_notify_bg.xml
copy to core/tests/coretests/apks/keyset/api_test/AndroidManifest.xml
index 3a8fab5..4c7e968 100644
--- a/core/res/res/drawable/lock_task_notify_bg.xml
+++ b/core/tests/coretests/apks/keyset/api_test/AndroidManifest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2010 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,10 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle" >
-
- <solid android:color="@android:color/black" />
- <corners
- android:radius="8dip" />
-</shape>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.coretests.keysets_api">
+ <application android:hasCode="false">
+ </application>
+</manifest>
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 0244425..3a80309 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.KeySet;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -33,6 +34,7 @@
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
@@ -3328,6 +3330,174 @@
}
/**
+ * The following tests are related to testing KeySets-based API
+ */
+
+ /*
+ * testGetSigningKeySetNull - ensure getSigningKeySet() returns null on null
+ * input and when calling a package other than that which made the call.
+ */
+ public void testGetSigningKeySet() throws Exception {
+ PackageManager pm = getPm();
+ String mPkgName = mContext.getPackageName();
+ String otherPkgName = "com.android.frameworks.coretests.keysets_api";
+ KeySet ks;
+ try {
+ ks = pm.getSigningKeySet(null);
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ ks = pm.getSigningKeySet("keysets.test.bogus.package");
+ assertTrue(false); // should have thrown
+ } catch (IllegalArgumentException e) {
+ }
+ installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
+ 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ try {
+ ks = pm.getSigningKeySet(otherPkgName);
+ assertTrue(false); // should have thrown
+ } catch (SecurityException e) {
+ }
+ cleanUpInstall(otherPkgName);
+ ks = pm.getSigningKeySet(mContext.getPackageName());
+ assertNotNull(ks);
+ }
+
+ /*
+ * testGetKeySetByAlias - same as getSigningKeySet, but for keysets defined
+ * by this package.
+ */
+ public void testGetKeySetByAlias() throws Exception {
+ PackageManager pm = getPm();
+ String mPkgName = mContext.getPackageName();
+ String otherPkgName = "com.android.frameworks.coretests.keysets_api";
+ KeySet ks;
+ try {
+ ks = pm.getKeySetByAlias(null, null);
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ ks = pm.getKeySetByAlias(null, "keysetBogus");
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ ks = pm.getKeySetByAlias("keysets.test.bogus.package", null);
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ ks = pm.getKeySetByAlias("keysets.test.bogus.package", "A");
+ assertTrue(false); // should have thrown
+ } catch(IllegalArgumentException e) {
+ }
+ try {
+ ks = pm.getKeySetByAlias(mPkgName, "keysetBogus");
+ assertTrue(false); // should have thrown
+ } catch(IllegalArgumentException e) {
+ }
+ installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
+ 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ try {
+ ks = pm.getKeySetByAlias(otherPkgName, "A");
+ assertTrue(false); // should have thrown
+ } catch (SecurityException e) {
+ }
+ cleanUpInstall(otherPkgName);
+ ks = pm.getKeySetByAlias(mPkgName, "A");
+ assertNotNull(ks);
+ }
+
+ public void testIsSignedBy() throws Exception {
+ PackageManager pm = getPm();
+ String mPkgName = mContext.getPackageName();
+ String otherPkgName = "com.android.frameworks.coretests.keysets_api";
+ KeySet mSigningKS = pm.getSigningKeySet(mPkgName);
+ KeySet mDefinedKS = pm.getKeySetByAlias(mPkgName, "A");
+
+ try {
+ assertFalse(pm.isSignedBy(null, null));
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ assertFalse(pm.isSignedBy(null, mSigningKS));
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ assertFalse(pm.isSignedBy(mPkgName, null));
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ assertFalse(pm.isSignedBy("keysets.test.bogus.package", mDefinedKS));
+ } catch(IllegalArgumentException e) {
+ }
+ assertFalse(pm.isSignedBy(mPkgName, mDefinedKS));
+ assertFalse(pm.isSignedBy(mPkgName, new KeySet(new Binder())));
+ assertTrue(pm.isSignedBy(mPkgName, mSigningKS));
+
+ installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
+ 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ assertFalse(pm.isSignedBy(otherPkgName, mDefinedKS));
+ assertTrue(pm.isSignedBy(otherPkgName, mSigningKS));
+ cleanUpInstall(otherPkgName);
+
+ installFromRawResource("keysetApi.apk", R.raw.keyset_splata_api,
+ 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ assertTrue(pm.isSignedBy(otherPkgName, mDefinedKS));
+ assertTrue(pm.isSignedBy(otherPkgName, mSigningKS));
+ cleanUpInstall(otherPkgName);
+ }
+
+ public void testIsSignedByExactly() throws Exception {
+ PackageManager pm = getPm();
+ String mPkgName = mContext.getPackageName();
+ String otherPkgName = "com.android.frameworks.coretests.keysets_api";
+ KeySet mSigningKS = pm.getSigningKeySet(mPkgName);
+ KeySet mDefinedKS = pm.getKeySetByAlias(mPkgName, "A");
+ try {
+ assertFalse(pm.isSignedBy(null, null));
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ assertFalse(pm.isSignedBy(null, mSigningKS));
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ assertFalse(pm.isSignedBy(mPkgName, null));
+ assertTrue(false); // should have thrown
+ } catch (NullPointerException e) {
+ }
+ try {
+ assertFalse(pm.isSignedByExactly("keysets.test.bogus.package", mDefinedKS));
+ } catch(IllegalArgumentException e) {
+ }
+ assertFalse(pm.isSignedByExactly(mPkgName, mDefinedKS));
+ assertFalse(pm.isSignedByExactly(mPkgName, new KeySet(new Binder())));
+ assertTrue(pm.isSignedByExactly(mPkgName, mSigningKS));
+
+ installFromRawResource("keysetApi.apk", R.raw.keyset_splat_api,
+ 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ assertFalse(pm.isSignedByExactly(otherPkgName, mDefinedKS));
+ assertTrue(pm.isSignedByExactly(otherPkgName, mSigningKS));
+ cleanUpInstall(otherPkgName);
+
+ installFromRawResource("keysetApi.apk", R.raw.keyset_splata_api,
+ 0, false, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
+ assertFalse(pm.isSignedByExactly(otherPkgName, mDefinedKS));
+ assertFalse(pm.isSignedByExactly(otherPkgName, mSigningKS));
+ cleanUpInstall(otherPkgName);
+ }
+
+
+
+ /**
* The following tests are related to testing the checkSignatures api.
*/
private void checkSignatures(int apk1, int apk2, int expMatchResult) throws Exception {
diff --git a/docs/html/distribute/googleplay/edu/about.jd b/docs/html/distribute/googleplay/edu/about.jd
index 60d9402..469b899 100644
--- a/docs/html/distribute/googleplay/edu/about.jd
+++ b/docs/html/distribute/googleplay/edu/about.jd
@@ -21,16 +21,6 @@
directly to classrooms and schools.
</p>
-
-<div class="resource-widget resource-flow-layout col-13" style="height:323px"
- data-query="collection:distribute/googleplay/gpfe/highlight"
- data-sortOrder="-timestamp"
- data-cardSizes="18x6,"
- data-maxResults="1"></div>
-
-
-<!-- <div class="center-img"><img src="{@docRoot}images/gp-edu-hero14.jpg" class="" /></div> -->
-
<p>
If you have an educational app, include it in Google Play for Education.
Google Play for Education can help your innovative educational apps gain
diff --git a/docs/html/distribute/googleplay/edu/start.jd b/docs/html/distribute/googleplay/edu/start.jd
index 136611c..067a15f 100644
--- a/docs/html/distribute/googleplay/edu/start.jd
+++ b/docs/html/distribute/googleplay/edu/start.jd
@@ -1,4 +1,4 @@
-page.title=Publish Android Apps for Education
+page.title=Publish Apps
page.image=/distribute/images/play-education.jpg
meta.tags="education", "guidelines", "quality"
page.tags="education", "addendum"
diff --git a/docs/html/distribute/googleplay/edu/videos.jd b/docs/html/distribute/googleplay/edu/videos.jd
new file mode 100644
index 0000000..ca4da7a
--- /dev/null
+++ b/docs/html/distribute/googleplay/edu/videos.jd
@@ -0,0 +1,30 @@
+page.title=Video Resources
+page.image=http://i1.ytimg.com/vi/vzvpcEffvaE/maxresdefault.jpg
+meta.tags="education"
+page.tags="education"
+page.metaDescription=Watch video resources from Google and successful educational developers.
+
+@jd:body
+
+<p>
+With Google Play for Education, bringing your app to the classroom has never been easier. However,
+you may want to familiarize yourself with some best practices before diving in.
+To help you visualize what a great education app might look like, what Google Play for Education is all
+about, and how to achieve success with the platform, here is a selection of recent videos from
+Google and successful educational developers.
+</p>
+
+<h2>Developer Stories</h2>
+<div style="margin-top:20px" class="resource-widget resource-flow-layout wrap col-13
+ no-section" data-query="collection:distribute/edu/videos/stories" data-resourcestyle="card"
+ data-maxresults="6" data-cardsizes="18x12x2"></div>
+
+<h2>Best Practices</h2>
+<div style="margin-top:20px" class="resource-widget resource-flow-layout wrap col-13
+ no-section" data-query="collection:distribute/edu/videos/bestpractices" data-resourcestyle="card"
+ data-maxresults="6" data-cardsizes="18x6, 6x6, 6x6, 6x6"></div>
+
+<h2>Teacher/Classroom Experience</h2>
+<div style="margin-top:20px" class="resource-widget resource-flow-layout wrap col-13
+ no-section" data-query="collection:distribute/edu/videos/experience" data-resourcestyle="card"
+ data-maxresults="6" data-cardsizes="18x12x2"></div>
\ No newline at end of file
diff --git a/docs/html/distribute/googleplay/googleplay_toc.cs b/docs/html/distribute/googleplay/googleplay_toc.cs
index 36e424a..45464c7 100644
--- a/docs/html/distribute/googleplay/googleplay_toc.cs
+++ b/docs/html/distribute/googleplay/googleplay_toc.cs
@@ -18,24 +18,24 @@
</div>
</li>
<li class="nav-section">
- <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/googleplay/edu/about.html">
+ <div class="nav-section-header" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/googleplay/edu/about.html">
<span class="en">Google Play for Education</span>
</a>
</div>
- </li>
- <li class="nav-section">
- <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/googleplay/edu/start.html">
- <span class="en">Publish Android Apps for Education</span>
- </a>
- </div>
+ <ul>
+ <li><a href="<?cs var:toroot?>distribute/googleplay/edu/start.html">
+ <span class="en">Publish Apps</span>
+ </a></li>
+ <li><a href="<?cs var:toroot?>distribute/googleplay/edu/videos.html">
+ <span class="en">Video Resources</span>
+ </a></li>
+ </ul>
</li>
</ul>
-
<script type="text/javascript">
<!--
buildToggleLists();
changeNavLang(getLangPref());
//-->
-</script>
-
+</script>
\ No newline at end of file
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index 4389e3d..90d8d4c 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -535,6 +535,8 @@
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener;
+import org.jivesoftware.smack.SmackException;
+import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketTypeFilter;
@@ -544,352 +546,378 @@
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.provider.ProviderManager;
+import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.util.StringUtils;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
import org.xmlpull.v1.XmlPullParser;
+import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
-import java.util.Random;
+import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.SSLSocketFactory;
+
/**
- * Sample Smack implementation of a client for GCM Cloud Connection Server.
+ * Sample Smack implementation of a client for GCM Cloud Connection Server. This
+ * code can be run as a standalone CCS client.
*
* <p>For illustration purposes only.
*/
public class SmackCcsClient {
- Logger logger = Logger.getLogger("SmackCcsClient");
+ private static final Logger logger = Logger.getLogger("SmackCcsClient");
- public static final String GCM_SERVER = "gcm.googleapis.com";
- public static final int GCM_PORT = 5235;
+ private static final String GCM_SERVER = "gcm.googleapis.com";
+ private static final int GCM_PORT = 5235;
- public static final String GCM_ELEMENT_NAME = "gcm";
- public static final String GCM_NAMESPACE = "google:mobile:data";
+ private static final String GCM_ELEMENT_NAME = "gcm";
+ private static final String GCM_NAMESPACE = "google:mobile:data";
- static Random random = new Random();
- XMPPConnection connection;
- ConnectionConfiguration config;
+ static {
- /**
- * XMPP Packet Extension for GCM Cloud Connection Server.
- */
- class GcmPacketExtension extends DefaultPacketExtension {
- String json;
-
- public GcmPacketExtension(String json) {
- super(GCM_ELEMENT_NAME, GCM_NAMESPACE);
- this.json = json;
+ ProviderManager.addExtensionProvider(GCM_ELEMENT_NAME, GCM_NAMESPACE,
+ new PacketExtensionProvider() {
+ @Override
+ public PacketExtension parseExtension(XmlPullParser parser) throws
+ Exception {
+ String json = parser.nextText();
+ return new GcmPacketExtension(json);
+ }
+ });
}
- public String getJson() {
- return json;
+ private XMPPConnection connection;
+
+ /**
+ * Indicates whether the connection is in draining state, which means that it
+ * will not accept any new downstream messages.
+ */
+ protected volatile boolean connectionDraining = false;
+
+ /**
+ * Sends a downstream message to GCM.
+ *
+ * @return true if the message has been successfully sent.
+ */
+ public boolean sendDownstreamMessage(String jsonRequest) throws
+ NotConnectedException {
+ if (!connectionDraining) {
+ send(jsonRequest);
+ return true;
+ }
+ logger.info("Dropping downstream message since the connection is draining");
+ return false;
}
- @Override
- public String toXML() {
- return String.format("<%s xmlns=\"%s\">%s</%s>", GCM_ELEMENT_NAME,
- GCM_NAMESPACE, json, GCM_ELEMENT_NAME);
+ /**
+ * Returns a random message id to uniquely identify a message.
+ *
+ * <p>Note: This is generated by a pseudo random number generator for
+ * illustration purpose, and is not guaranteed to be unique.
+ */
+ public String nextMessageId() {
+ return "m-" + UUID.randomUUID().toString();
}
- @SuppressWarnings("unused")
- public Packet toPacket() {
- return new Message() {
- // Must override toXML() because it includes a <body>
+ /**
+ * Sends a packet with contents provided.
+ */
+ protected void send(String jsonRequest) throws NotConnectedException {
+ Packet request = new GcmPacketExtension(jsonRequest).toPacket();
+ connection.sendPacket(request);
+ }
+
+ /**
+ * Handles an upstream data message from a device application.
+ *
+ * <p>This sample echo server sends an echo message back to the device.
+ * Subclasses should override this method to properly process upstream messages.
+ */
+ protected void handleUpstreamMessage(Map<String, Object> jsonObject) {
+ // PackageName of the application that sent this message.
+ String category = (String) jsonObject.get("category");
+ String from = (String) jsonObject.get("from");
+ @SuppressWarnings("unchecked")
+ Map<String, String> payload = (Map<String, String>) jsonObject.get("data");
+ payload.put("ECHO", "Application: " + category);
+
+ // Send an ECHO response back
+ String echo = createJsonMessage(from, nextMessageId(), payload,
+ "echo:CollapseKey", null, false);
+
+ try {
+ sendDownstreamMessage(echo);
+ } catch (NotConnectedException e) {
+ logger.log(Level.WARNING, "Not connected anymore, echo message is
+ not sent", e);
+ }
+ }
+
+ /**
+ * Handles an ACK.
+ *
+ * <p>Logs a {@code INFO} message, but subclasses could override it to
+ * properly handle ACKs.
+ */
+ protected void handleAckReceipt(Map<String, Object> jsonObject) {
+ String messageId = (String) jsonObject.get("message_id");
+ String from = (String) jsonObject.get("from");
+ logger.log(Level.INFO, "handleAckReceipt() from: " + from + ",
+ messageId: " + messageId);
+ }
+
+ /**
+ * Handles a NACK.
+ *
+ * <p>Logs a {@code INFO} message, but subclasses could override it to
+ * properly handle NACKs.
+ */
+ protected void handleNackReceipt(Map<String, Object> jsonObject) {
+ String messageId = (String) jsonObject.get("message_id");
+ String from = (String) jsonObject.get("from");
+ logger.log(Level.INFO, "handleNackReceipt() from: " + from + ",
+ messageId: " + messageId);
+ }
+
+ protected void handleControlMessage(Map<String, Object> jsonObject) {
+ logger.log(Level.INFO, "handleControlMessage(): " + jsonObject);
+ String controlType = (String) jsonObject.get("control_type");
+ if ("CONNECTION_DRAINING".equals(controlType)) {
+ connectionDraining = true;
+ } else {
+ logger.log(Level.INFO, "Unrecognized control type: %s. This could
+ happen if new features are " + "added to the CCS protocol.",
+ controlType);
+ }
+ }
+
+ /**
+ * Creates a JSON encoded GCM message.
+ *
+ * @param to RegistrationId of the target device (Required).
+ * @param messageId Unique messageId for which CCS will send an
+ * "ack/nack" (Required).
+ * @param payload Message content intended for the application. (Optional).
+ * @param collapseKey GCM collapse_key parameter (Optional).
+ * @param timeToLive GCM time_to_live parameter (Optional).
+ * @param delayWhileIdle GCM delay_while_idle parameter (Optional).
+ * @return JSON encoded GCM message.
+ */
+ public static String createJsonMessage(String to, String messageId,
+ Map<String, String> payload, String collapseKey, Long timeToLive,
+ Boolean delayWhileIdle) {
+ Map<String, Object> message = new HashMap<String, Object>();
+ message.put("to", to);
+ if (collapseKey != null) {
+ message.put("collapse_key", collapseKey);
+ }
+ if (timeToLive != null) {
+ message.put("time_to_live", timeToLive);
+ }
+ if (delayWhileIdle != null && delayWhileIdle) {
+ message.put("delay_while_idle", true);
+ }
+ message.put("message_id", messageId);
+ message.put("data", payload);
+ return JSONValue.toJSONString(message);
+ }
+
+ /**
+ * Creates a JSON encoded ACK message for an upstream message received
+ * from an application.
+ *
+ * @param to RegistrationId of the device who sent the upstream message.
+ * @param messageId messageId of the upstream message to be acknowledged to CCS.
+ * @return JSON encoded ack.
+ */
+ protected static String createJsonAck(String to, String messageId) {
+ Map<String, Object> message = new HashMap<String, Object>();
+ message.put("message_type", "ack");
+ message.put("to", to);
+ message.put("message_id", messageId);
+ return JSONValue.toJSONString(message);
+ }
+
+ /**
+ * Connects to GCM Cloud Connection Server using the supplied credentials.
+ *
+ * @param senderId Your GCM project number
+ * @param apiKey API Key of your project
+ */
+ public void connect(long senderId, String apiKey)
+ throws XMPPException, IOException, SmackException {
+ ConnectionConfiguration config =
+ new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
+ config.setSecurityMode(SecurityMode.enabled);
+ config.setReconnectionAllowed(true);
+ config.setRosterLoadedAtLogin(false);
+ config.setSendPresence(false);
+ config.setSocketFactory(SSLSocketFactory.getDefault());
+
+ connection = new XMPPTCPConnection(config);
+ connection.connect();
+
+ connection.addConnectionListener(new LoggingConnectionListener());
+
+ // Handle incoming packets
+ connection.addPacketListener(new PacketListener() {
+
+ @Override
+ public void processPacket(Packet packet) {
+ logger.log(Level.INFO, "Received: " + packet.toXML());
+ Message incomingMessage = (Message) packet;
+ GcmPacketExtension gcmPacket =
+ (GcmPacketExtension) incomingMessage.
+ getExtension(GCM_NAMESPACE);
+ String json = gcmPacket.getJson();
+ try {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> jsonObject =
+ (Map<String, Object>) JSONValue.
+ parseWithException(json);
+
+ // present for "ack"/"nack", null otherwise
+ Object messageType = jsonObject.get("message_type");
+
+ if (messageType == null) {
+ // Normal upstream data message
+ handleUpstreamMessage(jsonObject);
+
+ // Send ACK to CCS
+ String messageId = (String) jsonObject.get("message_id");
+ String from = (String) jsonObject.get("from");
+ String ack = createJsonAck(from, messageId);
+ send(ack);
+ } else if ("ack".equals(messageType.toString())) {
+ // Process Ack
+ handleAckReceipt(jsonObject);
+ } else if ("nack".equals(messageType.toString())) {
+ // Process Nack
+ handleNackReceipt(jsonObject);
+ } else if ("control".equals(messageType.toString())) {
+ // Process control message
+ handleControlMessage(jsonObject);
+ } else {
+ logger.log(Level.WARNING,
+ "Unrecognized message type (%s)",
+ messageType.toString());
+ }
+ } catch (ParseException e) {
+ logger.log(Level.SEVERE, "Error parsing JSON " + json, e);
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "Failed to process packet", e);
+ }
+ }
+ }, new PacketTypeFilter(Message.class));
+
+ // Log all outgoing packets
+ connection.addPacketInterceptor(new PacketInterceptor() {
+ @Override
+ public void interceptPacket(Packet packet) {
+ logger.log(Level.INFO, "Sent: {0}", packet.toXML());
+ }
+ }, new PacketTypeFilter(Message.class));
+
+ connection.login(senderId + "@gcm.googleapis.com", apiKey);
+ }
+
+ public static void main(String[] args) throws Exception {
+ final long senderId = 1234567890L; // your GCM sender id
+ final String password = "Your API key";
+
+ SmackCcsClient ccsClient = new SmackCcsClient();
+
+ ccsClient.connect(senderId, password);
+
+ // Send a sample hello downstream message to a device.
+ String toRegId = "RegistrationIdOfTheTargetDevice";
+ String messageId = ccsClient.nextMessageId();
+ Map<String, String> payload = new HashMap<String, String>();
+ payload.put("Hello", "World");
+ payload.put("CCS", "Dummy Message");
+ payload.put("EmbeddedMessageId", messageId);
+ String collapseKey = "sample";
+ Long timeToLive = 10000L;
+ String message = createJsonMessage(toRegId, messageId, payload,
+ collapseKey, timeToLive, true);
+
+ ccsClient.sendDownstreamMessage(message);
+ }
+
+ /**
+ * XMPP Packet Extension for GCM Cloud Connection Server.
+ */
+ private static final class GcmPacketExtension extends DefaultPacketExtension {
+
+ private final String json;
+
+ public GcmPacketExtension(String json) {
+ super(GCM_ELEMENT_NAME, GCM_NAMESPACE);
+ this.json = json;
+ }
+
+ public String getJson() {
+ return json;
+ }
+
@Override
public String toXML() {
-
- StringBuilder buf = new StringBuilder();
- buf.append("<message");
- if (getXmlns() != null) {
- buf.append(" xmlns=\"").append(getXmlns()).append("\"");
- }
- if (getLanguage() != null) {
- buf.append(" xml:lang=\"").append(getLanguage()).append("\"");
- }
- if (getPacketID() != null) {
- buf.append(" id=\"").append(getPacketID()).append("\"");
- }
- if (getTo() != null) {
- buf.append(" to=\"").append(StringUtils.escapeForXML(getTo())).append("\"");
- }
- if (getFrom() != null) {
- buf.append(" from=\"").append(StringUtils.escapeForXML(getFrom())).append("\"");
- }
- buf.append(">");
- buf.append(GcmPacketExtension.this.toXML());
- buf.append("</message>");
- return buf.toString();
+ return String.format("<%s xmlns=\"%s\">%s</%s>",
+ GCM_ELEMENT_NAME, GCM_NAMESPACE,
+ StringUtils.escapeForXML(json), GCM_ELEMENT_NAME);
}
- };
- }
- }
- public SmackCcsClient() {
- // Add GcmPacketExtension
- ProviderManager.getInstance().addExtensionProvider(GCM_ELEMENT_NAME,
- GCM_NAMESPACE, new PacketExtensionProvider() {
-
- @Override
- public PacketExtension parseExtension(XmlPullParser parser)
- throws Exception {
- String json = parser.nextText();
- GcmPacketExtension packet = new GcmPacketExtension(json);
- return packet;
- }
- });
- }
-
- /**
- * Returns a random message id to uniquely identify a message.
- *
- * <p>Note:
- * This is generated by a pseudo random number generator for illustration purpose,
- * and is not guaranteed to be unique.
- *
- */
- public String getRandomMessageId() {
- return "m-" + Long.toString(random.nextLong());
- }
-
- /**
- * Sends a downstream GCM message.
- */
- public void send(String jsonRequest) {
- Packet request = new GcmPacketExtension(jsonRequest).toPacket();
- connection.sendPacket(request);
- }
-
- /**
- * Handles an upstream data message from a device application.
- *
- * <p>This sample echo server sends an echo message back to the device.
- * Subclasses should override this method to process an upstream message.
- */
- public void handleIncomingDataMessage(Map<String, Object> jsonObject) {
- String from = jsonObject.get("from").toString();
-
- // PackageName of the application that sent this message.
- String category = jsonObject.get("category").toString();
-
- // Use the packageName as the collapseKey in the echo packet
- String collapseKey = "echo:CollapseKey";
- @SuppressWarnings("unchecked")
- Map<String, String> payload = (Map<String, String>) jsonObject.get("data");
- payload.put("ECHO", "Application: " + category);
-
- // Send an ECHO response back
- String echo = createJsonMessage(from, getRandomMessageId(), payload, collapseKey, null, false);
- send(echo);
- }
-
- /**
- * Handles an ACK.
- *
- * <p>By default, it only logs a {@code INFO} message, but subclasses could override it to
- * properly handle ACKS.
- */
- public void handleAckReceipt(Map<String, Object> jsonObject) {
- String messageId = jsonObject.get("message_id").toString();
- String from = jsonObject.get("from").toString();
- logger.log(Level.INFO, "handleAckReceipt() from: " + from + ", messageId: " + messageId);
- }
-
- /**
- * Handles a NACK.
- *
- * <p>By default, it only logs a {@code INFO} message, but subclasses could override it to
- * properly handle NACKS.
- */
- public void handleNackReceipt(Map<String, Object> jsonObject) {
- String messageId = jsonObject.get("message_id").toString();
- String from = jsonObject.get("from").toString();
- logger.log(Level.INFO, "handleNackReceipt() from: " + from + ", messageId: " + messageId);
- }
-
- /**
- * Creates a JSON encoded GCM message.
- *
- * @param to RegistrationId of the target device (Required).
- * @param messageId Unique messageId for which CCS will send an "ack/nack" (Required).
- * @param payload Message content intended for the application. (Optional).
- * @param collapseKey GCM collapse_key parameter (Optional).
- * @param timeToLive GCM time_to_live parameter (Optional).
- * @param delayWhileIdle GCM delay_while_idle parameter (Optional).
- * @return JSON encoded GCM message.
- */
- public static String createJsonMessage(String to, String messageId, Map<String, String> payload,
- String collapseKey, Long timeToLive, Boolean delayWhileIdle) {
- Map<String, Object> message = new HashMap<String, Object>();
- message.put("to", to);
- if (collapseKey != null) {
- message.put("collapse_key", collapseKey);
- }
- if (timeToLive != null) {
- message.put("time_to_live", timeToLive);
- }
- if (delayWhileIdle != null && delayWhileIdle) {
- message.put("delay_while_idle", true);
- }
- message.put("message_id", messageId);
- message.put("data", payload);
- return JSONValue.toJSONString(message);
- }
-
- /**
- * Creates a JSON encoded ACK message for an upstream message received from an application.
- *
- * @param to RegistrationId of the device who sent the upstream message.
- * @param messageId messageId of the upstream message to be acknowledged to CCS.
- * @return JSON encoded ack.
- */
- public static String createJsonAck(String to, String messageId) {
- Map<String, Object> message = new HashMap<String, Object>();
- message.put("message_type", "ack");
- message.put("to", to);
- message.put("message_id", messageId);
- return JSONValue.toJSONString(message);
- }
-
- /**
- * Connects to GCM Cloud Connection Server using the supplied credentials.
- *
- * @param username GCM_SENDER_ID@gcm.googleapis.com
- * @param password API Key
- * @throws XMPPException
- */
- public void connect(String username, String password) throws XMPPException {
- config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
- config.setSecurityMode(SecurityMode.enabled);
- config.setReconnectionAllowed(true);
- config.setRosterLoadedAtLogin(false);
- config.setSendPresence(false);
- config.setSocketFactory(SSLSocketFactory.getDefault());
-
- // NOTE: Set to true to launch a window with information about packets sent and received
- config.setDebuggerEnabled(true);
-
- // -Dsmack.debugEnabled=true
- XMPPConnection.DEBUG_ENABLED = true;
-
- connection = new XMPPConnection(config);
- connection.connect();
-
- connection.addConnectionListener(new ConnectionListener() {
-
- @Override
- public void reconnectionSuccessful() {
- logger.info("Reconnecting..");
- }
-
- @Override
- public void reconnectionFailed(Exception e) {
- logger.log(Level.INFO, "Reconnection failed.. ", e);
- }
-
- @Override
- public void reconnectingIn(int seconds) {
- logger.log(Level.INFO, "Reconnecting in %d secs", seconds);
- }
-
- @Override
- public void connectionClosedOnError(Exception e) {
- logger.log(Level.INFO, "Connection closed on error.");
- }
-
- @Override
- public void connectionClosed() {
- logger.info("Connection closed.");
- }
- });
-
- // Handle incoming packets
- connection.addPacketListener(new PacketListener() {
-
- @Override
- public void processPacket(Packet packet) {
- logger.log(Level.INFO, "Received: " + packet.toXML());
- Message incomingMessage = (Message) packet;
- GcmPacketExtension gcmPacket =
- (GcmPacketExtension) incomingMessage.getExtension(GCM_NAMESPACE);
- String json = gcmPacket.getJson();
- try {
- @SuppressWarnings("unchecked")
- Map<String, Object> jsonObject =
- (Map<String, Object>) JSONValue.parseWithException(json);
-
- // present for "ack"/"nack", null otherwise
- Object messageType = jsonObject.get("message_type");
-
- if (messageType == null) {
- // Normal upstream data message
- handleIncomingDataMessage(jsonObject);
-
- // Send ACK to CCS
- String messageId = jsonObject.get("message_id").toString();
- String from = jsonObject.get("from").toString();
- String ack = createJsonAck(from, messageId);
- send(ack);
- } else if ("ack".equals(messageType.toString())) {
- // Process Ack
- handleAckReceipt(jsonObject);
- } else if ("nack".equals(messageType.toString())) {
- // Process Nack
- handleNackReceipt(jsonObject);
- } else {
- logger.log(Level.WARNING, "Unrecognized message type (%s)",
- messageType.toString());
- }
- } catch (ParseException e) {
- logger.log(Level.SEVERE, "Error parsing JSON " + json, e);
- } catch (Exception e) {
- logger.log(Level.SEVERE, "Couldn't send echo.", e);
+ public Packet toPacket() {
+ Message message = new Message();
+ message.addExtension(this);
+ return message;
}
- }
- }, new PacketTypeFilter(Message.class));
-
-
- // Log all outgoing packets
- connection.addPacketInterceptor(new PacketInterceptor() {
- @Override
- public void interceptPacket(Packet packet) {
- logger.log(Level.INFO, "Sent: {0}", packet.toXML());
- }
- }, new PacketTypeFilter(Message.class));
-
- connection.login(username, password);
- }
-
- public static void main(String [] args) {
- final String userName = "Your GCM Sender Id" + "@gcm.googleapis.com";
- final String password = "API Key";
-
- SmackCcsClient ccsClient = new SmackCcsClient();
-
- try {
- ccsClient.connect(userName, password);
- } catch (XMPPException e) {
- e.printStackTrace();
}
- // Send a sample hello downstream message to a device.
- String toRegId = "RegistrationIdOfTheTargetDevice";
- String messageId = ccsClient.getRandomMessageId();
- Map<String, String> payload = new HashMap<String, String>();
- payload.put("Hello", "World");
- payload.put("CCS", "Dummy Message");
- payload.put("EmbeddedMessageId", messageId);
- String collapseKey = "sample";
- Long timeToLive = 10000L;
- Boolean delayWhileIdle = true;
- ccsClient.send(createJsonMessage(toRegId, messageId, payload, collapseKey,
- timeToLive, delayWhileIdle));
- }
+ private static final class LoggingConnectionListener
+ implements ConnectionListener {
+
+ @Override
+ public void connected(XMPPConnection xmppConnection) {
+ logger.info("Connected.");
+ }
+
+ @Override
+ public void authenticated(XMPPConnection xmppConnection) {
+ logger.info("Authenticated.");
+ }
+
+ @Override
+ public void reconnectionSuccessful() {
+ logger.info("Reconnecting..");
+ }
+
+ @Override
+ public void reconnectionFailed(Exception e) {
+ logger.log(Level.INFO, "Reconnection failed.. ", e);
+ }
+
+ @Override
+ public void reconnectingIn(int seconds) {
+ logger.log(Level.INFO, "Reconnecting in %d secs", seconds);
+ }
+
+ @Override
+ public void connectionClosedOnError(Exception e) {
+ logger.info("Connection closed on error.");
+ }
+
+ @Override
+ public void connectionClosed() {
+ logger.info("Connection closed.");
+ }
+ }
}</pre>
+
<h3 id="python">Python sample</h3>
<p>Here is an example of a CCS app server written in Python. This sample echo
diff --git a/docs/html/google/play-services/setup.jd b/docs/html/google/play-services/setup.jd
index cc2047e..ebd3694 100644
--- a/docs/html/google/play-services/setup.jd
+++ b/docs/html/google/play-services/setup.jd
@@ -129,7 +129,7 @@
<ol>
<li>Copy the library project at <code><android-sdk>/extras/google/google_play_services/libproject/google-play-services_lib/</code> to the location where you maintain your Android app projects.</li>
- <li>In your app project, reference Google Play services library project. See
+ <li>In your app project, reference the Google Play services library project. See
<a href="{@docRoot}tools/projects/projects-cmdline.html#ReferencingLibraryProject">Referencing
a Library Project on the Command Line</a> for more information on how to do this.
<p class="note"><strong>Note:</strong>
diff --git a/docs/html/google/play/billing/billing_overview.jd b/docs/html/google/play/billing/billing_overview.jd
index 301d911..12f8c9a 100644
--- a/docs/html/google/play/billing/billing_overview.jd
+++ b/docs/html/google/play/billing/billing_overview.jd
@@ -38,6 +38,16 @@
features that you need to understand in order to add In-app
Billing features into your application.</p>
+<p class="note"><b>Note</b>: Ensure that you comply with applicable laws in the countries where you
+distribute apps. For example, in EU countries, laws based on the
+<a href="http://ec.europa.eu/justice/consumer-marketing/unfair-trade/unfair-practices/">Unfair
+Commercial Practices Directive</a> prohibit direct exhortations to children to buy advertised
+products or to persuade their parents or other adults to buy advertised products for them.
+See the
+<a href="http://ec.europa.eu/consumers/enforcement/docs/common_position_on_online_games_en.pdf">position
+of the EU consumer protection authorities</a> for more information on this and other topics.
+</p>
+
<h2 id="api">In-app Billing API</h2>
<p>Your application accesses the In-app Billing service using an API that is
exposed by the Google Play app that is installed on the device. The Google Play
diff --git a/docs/html/guide/topics/graphics/2d-graphics.jd b/docs/html/guide/topics/graphics/2d-graphics.jd
index d842cb9..4b5a121 100644
--- a/docs/html/guide/topics/graphics/2d-graphics.jd
+++ b/docs/html/guide/topics/graphics/2d-graphics.jd
@@ -32,7 +32,7 @@
</div>
</div>
-<p>The Android framework APIs provides a set 2D drawing APIs that allow you to render your own
+<p>The Android framework APIs provides a set of 2D-drawing APIs that allow you to render your own
custom graphics onto a canvas or to modify existing Views to customize their look and feel.
When drawing 2D graphics, you'll typically do so in one of two ways:</p>
@@ -515,4 +515,4 @@
stretches to accommodate it.
</p>
-<img src="{@docRoot}images/ninepatch_examples.png" alt=""/>
\ No newline at end of file
+<img src="{@docRoot}images/ninepatch_examples.png" alt=""/>
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index 56ef624..8b79b23 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -86,14 +86,17 @@
<h2 id="basics">The Basics</h2>
<p>The Android framework supports capturing images and video through the
-{@link android.hardware.Camera} API or camera {@link android.content.Intent}. Here are the relevant
+{@link android.hardware.camera2} API or camera {@link android.content.Intent}. Here are the relevant
classes:</p>
<dl>
- <dt>{@link android.hardware.Camera}</dt>
- <dd>This class is the primary API for controlling device cameras. This class is used to take
+ <dt>{@link android.hardware.camera2}</dt>
+ <dd>This package is the primary API for controlling device cameras. It can be used to take
pictures or videos when you are building a camera application.</dd>
+ <dt>{@link android.hardware.Camera}</dt>
+ <dd>This class is the older deprecated API for controlling device cameras.</dd>
+
<dt>{@link android.view.SurfaceView}</dt>
<dd>This class is used to present a live camera preview to the user.</dd>
@@ -354,6 +357,10 @@
code than <a href="#intents">using an intent</a>, but it can provide a more compelling experience
for your users.</p>
+<p><strong> Note: The following guide is for the older, deprecated {@link android.hardware.Camera}
+API. For new or advanced camera applications, the newer {@link android.hardware.camera2} API is
+recommended.</strong></p>
+
<p>The general steps for creating a custom camera interface for your application are as follows:</p>
<ul>
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index 616949b..0c72657 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -88,8 +88,8 @@
<pre>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:orientation="vertical" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
@@ -215,14 +215,14 @@
<ul>
<li><var>wrap_content</var> tells your view to size itself to the dimensions
required by its content</li>
- <li><var>fill_parent</var> (renamed <var>match_parent</var> in API Level 8)
+ <li><var>match_parent</var> (named <var>fill_parent</var> before API Level 8)
tells your view to become as big as its parent view group will allow.</li>
</ul>
<p>In general, specifying a layout width and height using absolute units such as
pixels is not recommended. Instead, using relative measurements such as
density-independent pixel units (<var>dp</var>), <var>wrap_content</var>, or
-<var>fill_parent</var>, is a better approach, because it helps ensure that
+<var>match_parent</var>, is a better approach, because it helps ensure that
your application will display properly across a variety of device screen sizes.
The accepted measurement types are defined in the
<a href="{@docRoot}guide/topics/resources/available-resources.html#dimension">
diff --git a/docs/html/guide/topics/ui/layout/grid.jd b/docs/html/guide/topics/ui/layout/grid.jd
index 52f453b..c2f1321 100644
--- a/docs/html/guide/topics/ui/layout/grid.jd
+++ b/docs/html/guide/topics/ui/layout/grid.jd
@@ -41,8 +41,8 @@
<pre>
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:stretchColumns="1">
<TableRow>
<TextView
@@ -82,8 +82,8 @@
<pre>
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:stretchColumns="1">
<TableRow>
diff --git a/docs/html/guide/topics/ui/layout/gridview.jd b/docs/html/guide/topics/ui/layout/gridview.jd
index b8d24b60..a4bf224 100644
--- a/docs/html/guide/topics/ui/layout/gridview.jd
+++ b/docs/html/guide/topics/ui/layout/gridview.jd
@@ -43,10 +43,10 @@
<li>Open the <code>res/layout/main.xml</code> file and insert the following:
<pre>
<?xml version="1.0" encoding="utf-8"?>
-<GridView xmlns:android="http://schemas.android.com/apk/res/android"
+<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:columnWidth="90dp"
android:numColumns="auto_fit"
android:verticalSpacing="10dp"
diff --git a/docs/html/guide/topics/ui/layout/linear.jd b/docs/html/guide/topics/ui/layout/linear.jd
index 902f22f..f4babfe0 100644
--- a/docs/html/guide/topics/ui/layout/linear.jd
+++ b/docs/html/guide/topics/ui/layout/linear.jd
@@ -82,21 +82,21 @@
<pre>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:orientation="vertical" >
<EditText
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/to" />
<EditText
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/subject" />
<EditText
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="top"
diff --git a/docs/html/guide/topics/ui/layout/relative.jd b/docs/html/guide/topics/ui/layout/relative.jd
index 4354d7f..ca5cb48 100644
--- a/docs/html/guide/topics/ui/layout/relative.jd
+++ b/docs/html/guide/topics/ui/layout/relative.jd
@@ -82,13 +82,13 @@
<pre>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp" >
<EditText
android:id="@+id/name"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/reminder" />
<Spinner
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index cd49ace..852db1f 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -7,12 +7,26 @@
"sdk/installing/studio.html"
]
},
- "index/devices": {
+ "distribute/edu/videos/stories": {
"title": "",
"resources": [
- "wear/index.html",
- "tv/index.html",
- "auto/index.html"
+ "https://www.youtube.com/watch?v=Idu7VcTTXfk",
+ "https://www.youtube.com/watch?v=iokH4SAIfRw"
+ ]
+ },
+ "distribute/edu/videos/bestpractices": {
+ "title": "",
+ "resources": [
+ "https://www.youtube.com/watch?v=iulXz8QTD1g",
+ "https://www.youtube.com/watch?v=IKhU180eJMo",
+ "https://www.youtube.com/watch?v=_AZ6UcPz-_g",
+ "https://www.youtube.com/watch?v=Eh2adsAyTKc"
+ ]
+ },
+ "distribute/edu/videos/experience": {
+ "title": "",
+ "resources": [
+ "http://youtu.be/vzvpcEffvaE"
]
},
"launch/static": {
@@ -45,7 +59,7 @@
"resources": [
"distribute/googleplay/edu/about.html",
"distribute/googleplay/edu/start.html",
- "https://developers.google.com/edu/faq"
+ "distribute/googleplay/edu/videos.html"
]
},
"distribute/essentials": {
diff --git a/docs/html/jd_extras.js b/docs/html/jd_extras.js
index dccdf7e..a4302ef 100644
--- a/docs/html/jd_extras.js
+++ b/docs/html/jd_extras.js
@@ -15,6 +15,90 @@
DISTRIBUTE_RESOURCES = DISTRIBUTE_RESOURCES.concat([
{
+ "title":"Quizlet Developer Story",
+ "titleFriendly":"",
+ "summary":"Quizlet is an extremely popular online learning tool for students. See how they optimized for the classroom with Android and the power of Google Play for Education.",
+ "url":"https://www.youtube.com/watch?v=Idu7VcTTXfk",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ "#gpfe",
+ "#googleplay"
+ ],
+ "image":"http://i1.ytimg.com/vi/Idu7VcTTXfk/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Whats New in Google Play",
+ "titleFriendly":"",
+ "summary":"Learn about the vision and philosophy behind Google Play for Education",
+ "url":"https://www.youtube.com/watch?v=IKhU180eJMo",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ "#gpfe",
+ "#googleplay"
+ ],
+ "image":"http://i1.ytimg.com/vi/IKhU180eJMo/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"ClassDojo Developer Story",
+ "titleFriendly":"",
+ "summary":"ClassDojo is a classroom tool that helps teachers improve behavior in their classrooms quickly and easily. See how they optimized for the classroom with Android and the power of Google Play for Education.",
+ "url":"https://www.youtube.com/watch?v=iokH4SAIfRw",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ "#gpfe",
+ "#googleplay"
+ ],
+ "image":"http://i1.ytimg.com/vi/iokH4SAIfRw/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"5 Tips for Succeeding",
+ "titleFriendly":"",
+ "summary":"See inspirational ways of using technology in the classroom.",
+ "url":"https://www.youtube.com/watch?v=Eh2adsAyTKc",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ "#gpfe",
+ "#googleplay"
+ ],
+ "image":"http://i1.ytimg.com/vi/Eh2adsAyTKc/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Optimizing Apps for Education",
+ "titleFriendly":"",
+ "summary":"Learn how to optimize your app for teachers and students.",
+ "url":"https://www.youtube.com/watch?v=_AZ6UcPz-_g",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ "#gpfe",
+ "#googleplay"
+ ],
+ "image":"http://i1.ytimg.com/vi/_AZ6UcPz-_g/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
+ "title":"Ideas and Tools for Building Innovative Education Apps",
+ "titleFriendly":"",
+ "summary":"Are you hungry to build an awesome app for education but don't quite know where to start? Come hear about apps that teachers want, and the APIs you're going to need to build them! In particular, we'll talk about app ideas that combine APIs for Google Drive, Google Login, Android Single Task Mode and more to build transformative Educational apps that will delight educators and kids in and out of the classroom.",
+ "url":"https://www.youtube.com/watch?v=iulXz8QTD1g",
+ "group":"",
+ "keywords": [],
+ "tags": [
+ "#gpfe",
+ "#googleplay"
+ ],
+ "image":"http://i1.ytimg.com/vi/iulXz8QTD1g/maxresdefault.jpg",
+ "type":"video"
+ },
+ {
"title":"Developer Registration",
"titleFriendly":"",
"summary":"Additional information about the registration process.",
@@ -699,10 +783,10 @@
"url": "http://youtu.be/vzvpcEffvaE",
"timestamp": 1383243492000,
"image": "http://i1.ytimg.com/vi/vzvpcEffvaE/maxresdefault.jpg",
- "title": "Introducing Google Play for Education",
- "summary": "Google Play for Education is a destination where schools can find great, teacher-approved, educational content—from videos and books, to educational apps—all in one place. Teachers can filter content by subject matter, grade and other criteria. Bulk purchase and instant distribution let educators bring your apps directly to classrooms and schools.",
+ "title": "Introducing Tablets with Google Play for Education",
+ "summary": "Schools in Hillsborough, New Jersey were among the first to try out Nexus 7 tablets with Google Play for Education. See the difference it made for students, teachers, and administrators.",
"keywords": [],
- "type": "youtube",
+ "type": "video",
"titleFriendly": ""
},
{
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index 16bc444..cf594dc 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -571,7 +571,7 @@
manifest in order for your app to use the new advertising and scanning features.</a>
<p>To begin Bluetooth LE advertising so that other devices can discover
-your app, call {@code android.bluetooth.le.BluetoothAdvertiser.startAdvisertising()}
+your app, call {@code android.bluetooth.le.BluetoothAdvertiser.startAdvertising()}
and pass in an implementation of the
{@code android.bluetooth.le.AdvertiseCallback} class. The callback object
receives a report of the success or failure of the advertising operation.</p>
diff --git a/docs/html/preview/material/animations.jd b/docs/html/preview/material/animations.jd
index b8d063b..353f0f2 100644
--- a/docs/html/preview/material/animations.jd
+++ b/docs/html/preview/material/animations.jd
@@ -130,7 +130,7 @@
<ul>
<li><em>explode</em> - Moves views in or out from the center of the scene.</li>
<li><em>slide</em> - Moves views in or out from one of the edges of the scene.</li>
-<li><em>fade</em> - Mades views in or out of the scene.</li>
+<li><em>fade</em> - Moves views in or out of the scene.</li>
</ul>
<p>Any transition that extends the <code>android.transition.Visibility</code> class is supported
@@ -236,7 +236,7 @@
<h3>Shared elements transitions</h3>
-<p>To make a screne transition animation between two activities that have a shared element:</p>
+<p>To make a screen transition animation between two activities that have a shared element:</p>
<ol>
<li>Enable window content transitions in your style.</li>
diff --git a/docs/html/preview/material/compatibility.jd b/docs/html/preview/material/compatibility.jd
index fb97112..b4d26a7 100644
--- a/docs/html/preview/material/compatibility.jd
+++ b/docs/html/preview/material/compatibility.jd
@@ -78,5 +78,5 @@
<li>Path-based animations</li>
</ul>
-<p>To preserve compatibility with earlier verisons of Android, check the system version at
+<p>To preserve compatibility with earlier versions of Android, check the system version at
runtime before you invoke these APIs.</p>
\ No newline at end of file
diff --git a/docs/html/preview/material/theme.jd b/docs/html/preview/material/theme.jd
index 740bf56..dceeb47 100644
--- a/docs/html/preview/material/theme.jd
+++ b/docs/html/preview/material/theme.jd
@@ -6,7 +6,7 @@
<div id="qv">
<h2>In this document</h2>
<ol>
- <li><a href="#colorpalette">Customize the Colot Palette</a></li>
+ <li><a href="#colorpalette">Customize the Color Palette</a></li>
<li><a href="#statusbar">Customize the Status Bar</a></li>
<li><a href="#inheritance">Theme Individual Views</a></li>
</ol>
diff --git a/docs/html/preview/material/ui-widgets.jd b/docs/html/preview/material/ui-widgets.jd
index 31604d6..2266815 100644
--- a/docs/html/preview/material/ui-widgets.jd
+++ b/docs/html/preview/material/ui-widgets.jd
@@ -171,10 +171,10 @@
<p>Here's how to specify properties of <code>CardView</code>:</p>
<ul>
- <li>To set the corner radius in your layouts, use the <code>android:cardCornerRadius</code>
+ <li>To set the corner radius in your layouts, use the <code>card_view:cardCornerRadius</code>
attribute.</li>
<li>To set the corner radius in your code, use the <code>CardView.setRadius</code> method.</li>
- <li>To set the background color of a card, use the <code>android:cardBackgroundColor</code>
+ <li>To set the background color of a card, use the <code>card_view:cardBackgroundColor</code>
attribute.</li>
</ul>
diff --git a/docs/html/preview/material/views-shadows.jd b/docs/html/preview/material/views-shadows.jd
index f7682f5..78c0062 100644
--- a/docs/html/preview/material/views-shadows.jd
+++ b/docs/html/preview/material/views-shadows.jd
@@ -73,7 +73,7 @@
</shape>
</pre>
-<p>Then this view and drawable cast the appropiate shadow.</p>
+<p>Then this view and drawable cast the appropriate shadow.</p>
<p>You can also create outlines in your code using the methods in the <code>Outline</code> class,
and you can assign them to views with the <code>View.setOutline</code> method.</p>
diff --git a/docs/html/preview/notifications.jd b/docs/html/preview/notifications.jd
index 375fad9..44f46ea5 100644
--- a/docs/html/preview/notifications.jd
+++ b/docs/html/preview/notifications.jd
@@ -183,7 +183,7 @@
<img src="{@docRoot}preview/images/notifications/ReplyAction.png" width="156px" height="156px"
alt="" />
-
+
</div>
@@ -315,7 +315,7 @@
priority</strong></h4>
<p>Default, High, and Max priority are interruptive priority levels and risk interrupting the user
-from what they are doing. This should not not be taken lightly, so these levels should be reserved
+from what they are doing. This should not be taken lightly, so these levels should be reserved
for notifications that:</p>
<ul>
@@ -498,7 +498,7 @@
<h3 style="clear:both" id="make_notifications_optional">Make notifications optional</h3>
-<p>Users should always be in control of notifications. Allow the user to diszable your app's
+<p>Users should always be in control of notifications. Allow the user to disable your app's
notifications or change their alert properties, such as alert sound and whether to use vibration,
by adding a notification settings item to your application settings.</p>
diff --git a/docs/html/preview/tv/adt-1/index.jd b/docs/html/preview/tv/adt-1/index.jd
index d83dd11..e09dcbf 100644
--- a/docs/html/preview/tv/adt-1/index.jd
+++ b/docs/html/preview/tv/adt-1/index.jd
@@ -160,7 +160,7 @@
<p>
<p>You cast to an ADT-1 device the same way you do with a Chromecast device. Open the supported
Cast apps or webpages, press the <strong>Cast</strong> button and you should see the ADT-1 as a
- Cast target. For more infomation about on how to cast, see
+ Cast target. For more information about on how to cast, see
<a href="http://www.google.com/intl/en/chrome/devices/chromecast/learn.html">Learn How to
Cast</a>.
</p>
diff --git a/docs/html/preview/tv/design/patterns.jd b/docs/html/preview/tv/design/patterns.jd
index cdba74c..48faee9 100644
--- a/docs/html/preview/tv/design/patterns.jd
+++ b/docs/html/preview/tv/design/patterns.jd
@@ -45,7 +45,7 @@
<h3>Recommendation Icons</h3>
<p>Recommendation cards include a small icon that is imposed over a colored background.
- An example and specifications for the this icon are shown below:</p>
+ An example and specifications for this icon are shown below:</p>
<img src="{@docRoot}preview/tv/design/images/icon.png" alt="Recommendation icon examples" />
diff --git a/docs/html/preview/tv/games/index.jd b/docs/html/preview/tv/games/index.jd
index 763eada..61a26d2c 100644
--- a/docs/html/preview/tv/games/index.jd
+++ b/docs/html/preview/tv/games/index.jd
@@ -146,7 +146,7 @@
site.</p>
<h2 id="web">Web</h2>
-<p>We discourage including web browsing in games for Android TV. The television set is not well-suited for browsing,, either in terms of display or control scheme.</p>
+<p>We discourage including web browsing in games for Android TV. The television set is not well-suited for browsing, either in terms of display or control scheme.</p>
<p class="note"><strong>Note:</strong> You can use the {@link android.webkit.WebView} class for logins to services like Google+ and
Facebook. </p>
diff --git a/docs/html/preview/tv/ui/navigation.jd b/docs/html/preview/tv/ui/navigation.jd
index 92b34cf..684b743 100644
--- a/docs/html/preview/tv/ui/navigation.jd
+++ b/docs/html/preview/tv/ui/navigation.jd
@@ -104,7 +104,7 @@
<p>Android provides <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">
Drawable State List Resources</a> to implement highlights for selected and focused controls. The
-following code example demonstates how to indicate selection of a button object:
+following code example demonstrates how to indicate selection of a button object:
</p>
<pre>
diff --git a/docs/html/tools/publishing/preparing.jd b/docs/html/tools/publishing/preparing.jd
index 7192aa8..5265fce 100644
--- a/docs/html/tools/publishing/preparing.jd
+++ b/docs/html/tools/publishing/preparing.jd
@@ -191,6 +191,13 @@
added to your code, such as {@link android.os.Debug#startMethodTracing()} and
{@link android.os.Debug#stopMethodTracing()} method calls.</p>
+<p class="caution"><strong>Important:</strong> Ensure that you disable debugging for
+your app if using {@link android.webkit.WebView} to display paid for content or if using JavaScript
+interfaces, since debugging allows users to inject scripts and extract content using Chrome
+DevTools. To disable debugging, use the
+{@link android.webkit.WebView#setWebContentsDebuggingEnabled(boolean) WebView.setWebContentsDebuggingEnabled()}
+method.</p>
+
<h4>Clean up your project directories</h4>
<p>Clean up your project and make sure it conforms to the directory structure described in <a
diff --git a/docs/html/tools/sdk/ndk/index.jd b/docs/html/tools/sdk/ndk/index.jd
index 0ac1881..71b15d5 100644
--- a/docs/html/tools/sdk/ndk/index.jd
+++ b/docs/html/tools/sdk/ndk/index.jd
@@ -2,33 +2,59 @@
page.template=sdk
-ndk.mac64_download=android-ndk-r9d-darwin-x86_64.tar.bz2
-ndk.mac64_bytes=400339614
-ndk.mac64_checksum=c914164b1231c574dbe40debef7048be
+ndk.mac64_download=android-ndk32-r10-darwin-x86_64.tar.bz2
+ndk.mac64_bytes=411610468
+ndk.mac64_checksum=3ce1fa3dbe7a188f5d2640fd2f7ca944
-ndk.mac32_download=android-ndk-r9d-darwin-x86.tar.bz2
-ndk.mac32_bytes=393866116
-ndk.mac32_checksum=ee6544bd8093c79ea08c2e3a6ffe3573
+ndk.mac32_download=android-ndk32-r10-darwin-x86.tar.bz2
+ndk.mac32_bytes=404768263
+ndk.mac32_checksum=1824eec1f6749b6cb7bb306a3b924c33
-ndk.linux64_download=android-ndk-r9d-linux-x86_64.tar.bz2
-ndk.linux64_bytes=412879983
-ndk.linux64_checksum=c7c775ab3342965408d20fd18e71aa45
+ndk.linux64_download=android-ndk32-r10-linux-x86_64.tar.bz2
+ndk.linux64_bytes=420671390
+ndk.linux64_checksum=e3ff629d212a8106a43415862fa39baf
-ndk.linux32_download=android-ndk-r9d-linux-x86.tar.bz2
-ndk.linux32_bytes=405218267
-ndk.linux32_checksum=6c1d7d99f55f0c17ecbcf81ba0eb201f
+ndk.linux32_download=android-ndk32-r10-linux-x86.tar.bz2
+ndk.linux32_bytes=420078216
+ndk.linux32_checksum=8d9a5faa6e77b43bfae0f169079b21c4
-ndk.win64_download=android-ndk-r9d-windows-x86_64.zip
-ndk.win64_bytes=520997454
-ndk.win64_checksum=8cd244fc799d0e6e59d65a59a8692588
+ndk.win64_download=android-ndk32-r10-windows-x86_64.zip
+ndk.win64_bytes=529850429
+ndk.win64_checksum=b11f9239344f7c377ed5b627f0fb236e
-ndk.win32_download=android-ndk-r9d-windows-x86.zip
-ndk.win32_bytes=491440074
-ndk.win32_checksum=b16516b611841a075685a10c59d6d7a2
+ndk.win32_download=android-ndk32-r10-windows-x86.zip
+ndk.win32_bytes=500135685
+ndk.win32_checksum=0a3c01147abba945cc4ef5837519ec97
-ndk.debug_info_download=android-ndk-r9d-cxx-stl-libs-with-debug-info.zip
-ndk.debug_info_bytes=104947363
-ndk.debug_info_checksum=906c8d88e0f02295c3bfe6b8e98a1a35
+
+
+ndk.mac64_64_download=android-ndk64-r10-darwin-x86_64.tar.bz2
+ndk.mac64_64_bytes=327740247
+ndk.mac64_64_checksum=72561b27acc6192a2e81b345ea128a20
+
+ndk.mac32_64_download=android-ndk64-r10-darwin-x86.tar.bz2
+ndk.mac32_64_bytes=323736411
+ndk.mac32_64_checksum=5bbaf9d8051ba5d2c0fff74cfd87c374
+
+ndk.linux64_64_download=android-ndk64-r10-linux-x86_64.tar.bz2
+ndk.linux64_64_bytes=339708042
+ndk.linux64_64_checksum=737290195583268b7fbff4aa56465ab6
+
+ndk.linux32_64_download=android-ndk64-r10-linux-x86.tar.bz2
+ndk.linux32_64_bytes=338544906
+ndk.linux32_64_checksum=bea5d027baeb948cbff6af840d26b80d
+
+ndk.win64_64_download=android-ndk64-r10-windows-x86_64.zip
+ndk.win64_64_bytes=417411195
+ndk.win64_64_checksum=91879ec85539b45313a21b9526b911a8
+
+ndk.win32_64_download=android-ndk64-r10-windows-x86.zip
+ndk.win32_64_bytes=396751892
+ndk.win32_64_checksum=f79070ace2cde9ebf6a2e2be4a61ac7a
+
+ndk.debug_info_download=android-ndk-r10-cxx-stl-libs-with-debug-info.zip
+ndk.debug_info_bytes=253198908
+ndk.debug_info_checksum=c2a90c43d17dbb5f0609cc8237491788
page.title=Android NDK
@@ -56,129 +82,261 @@
This is the Android Software Development Kit License Agreement
<h3>1. Introduction</h3>
-1.1 The Android Software Development Kit (referred to in this License Agreement as the "SDK" and specifically including the Android system files, packaged APIs, and Google APIs add-ons) is licensed to you subject to the terms of this License Agreement. This License Agreement forms a legally binding contract between you and Google in relation to your use of the SDK.
+1.1 The Android Software Development Kit (referred to in this License Agreement as the "SDK" and
+specifically including the Android system files, packaged APIs, and Google APIs add-ons) is
+licensed to you subject to the terms of this License Agreement. This License Agreement forms a
+legally binding contract between you and Google in relation to your use of the SDK.
-1.2 “Android” means the Android software stack for devices, as made available under the Android Open Source Project, which is located at the following URL: http://source.android.com/, as updated from time to time.
+1.2 “Android” means the Android software stack for devices, as made available under the Android
+Open Source Project, which is located at the following URL: http://source.android.com/, as updated
+from time to time.
-1.3 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States.
+1.3 "Google" means Google Inc., a Delaware corporation with principal place of business at 1600
+Amphitheatre Parkway, Mountain View, CA 94043, United States.
<h3>2. Accepting this License Agreement</h3>
-2.1 In order to use the SDK, you must first agree to this License Agreement. You may not use the SDK if you do not accept this License Agreement.
+2.1 In order to use the SDK, you must first agree to this License Agreement. You may not use the
+SDK if you do not accept this License Agreement.
2.2 By clicking to accept, you hereby agree to the terms of this License Agreement.
-2.3 You may not use the SDK and may not accept the License Agreement if you are a person barred from receiving the SDK under the laws of the United States or other countries including the country in which you are resident or from which you use the SDK.
+2.3 You may not use the SDK and may not accept the License Agreement if you are a person barred
+from receiving the SDK under the laws of the United States or other countries including the country
+in which you are resident or from which you use the SDK.
-2.4 If you are agreeing to be bound by this License Agreement on behalf of your employer or other entity, you represent and warrant that you have full legal authority to bind your employer or such entity to this License Agreement. If you do not have the requisite authority, you may not accept the License Agreement or use the SDK on behalf of your employer or other entity.
+2.4 If you are agreeing to be bound by this License Agreement on behalf of your employer or other
+entity, you represent and warrant that you have full legal authority to bind your employer or such
+entity to this License Agreement. If you do not have the requisite authority, you may not accept
+the License Agreement or use the SDK on behalf of your employer or other entity.
<h3>3. SDK License from Google</h3>
-3.1 Subject to the terms of this License Agreement, Google grants you a limited, worldwide, royalty-free, non-assignable and non-exclusive license to use the SDK solely to develop applications to run on the Android platform.
+3.1 Subject to the terms of this License Agreement, Google grants you a limited, worldwide,
+royalty-free, non-assignable and non-exclusive license to use the SDK solely to develop
+applications to run on the Android platform.
-3.2 You agree that Google or third parties own all legal right, title and interest in and to the SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law, and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
+3.2 You agree that Google or third parties own all legal right, title and interest in and to the
+SDK, including any Intellectual Property Rights that subsist in the SDK. "Intellectual Property
+Rights" means any and all rights under patent law, copyright law, trade secret law, trademark law,
+and any and all other proprietary rights. Google reserves all rights not expressly granted to you.
-3.3 You may not use the SDK for any purpose not expressly permitted by this License Agreement. Except to the extent required by applicable third party licenses, you may not: (a) copy (except for backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create derivative works of the SDK or any part of the SDK; or (b) load any part of the SDK onto a mobile handset or any other hardware device except a personal computer, combine any part of the SDK with other software, or distribute any software or device incorporating a part of the SDK.
+3.3 You may not use the SDK for any purpose not expressly permitted by this License Agreement.
+Except to the extent required by applicable third party licenses, you may not: (a) copy (except for
+backup purposes), modify, adapt, redistribute, decompile, reverse engineer, disassemble, or create
+derivative works of the SDK or any part of the SDK; or (b) load any part of the SDK onto a mobile
+handset or any other hardware device except a personal computer, combine any part of the SDK with
+other software, or distribute any software or device incorporating a part of the SDK.
-3.4 You agree that you will not take any actions that may cause or result in the fragmentation of Android, including but not limited to distributing, participating in the creation of, or promoting in any way a software development kit derived from the SDK.
+3.4 You agree that you will not take any actions that may cause or result in the fragmentation of
+Android, including but not limited to distributing, participating in the creation of, or promoting
+in any way a software development kit derived from the SDK.
-3.5 Use, reproduction and distribution of components of the SDK licensed under an open source software license are governed solely by the terms of that open source software license and not this License Agreement.
+3.5 Use, reproduction and distribution of components of the SDK licensed under an open source
+software license are governed solely by the terms of that open source software license and not this
+License Agreement.
-3.6 You agree that the form and nature of the SDK that Google provides may change without prior notice to you and that future versions of the SDK may be incompatible with applications developed on previous versions of the SDK. You agree that Google may stop (permanently or temporarily) providing the SDK (or any features within the SDK) to you or to users generally at Google's sole discretion, without prior notice to you.
+3.6 You agree that the form and nature of the SDK that Google provides may change without prior
+notice to you and that future versions of the SDK may be incompatible with applications developed
+on previous versions of the SDK. You agree that Google may stop (permanently or temporarily)
+providing the SDK (or any features within the SDK) to you or to users generally at Google's sole
+discretion, without prior notice to you.
-3.7 Nothing in this License Agreement gives you a right to use any of Google's trade names, trademarks, service marks, logos, domain names, or other distinctive brand features.
+3.7 Nothing in this License Agreement gives you a right to use any of Google's trade names,
+trademarks, service marks, logos, domain names, or other distinctive brand features.
-3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including copyright and trademark notices) that may be affixed to or contained within the SDK.
+3.8 You agree that you will not remove, obscure, or alter any proprietary rights notices (including
+copyright and trademark notices) that may be affixed to or contained within the SDK.
<h3>4. Use of the SDK by You</h3>
-4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under this License Agreement in or to any software applications that you develop using the SDK, including any intellectual property rights that subsist in those applications.
+4.1 Google agrees that it obtains no right, title or interest from you (or your licensors) under
+this License Agreement in or to any software applications that you develop using the SDK, including
+any intellectual property rights that subsist in those applications.
-4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a) this License Agreement and (b) any applicable law, regulation or generally accepted practices or guidelines in the relevant jurisdictions (including any laws regarding the export of data or software to and from the United States or other relevant countries).
+4.2 You agree to use the SDK and write applications only for purposes that are permitted by (a)
+this License Agreement and (b) any applicable law, regulation or generally accepted practices or
+guidelines in the relevant jurisdictions (including any laws regarding the export of data or
+software to and from the United States or other relevant countries).
-4.3 You agree that if you use the SDK to develop applications for general public users, you will protect the privacy and legal rights of those users. If the users provide you with user names, passwords, or other login information or personal information, you must make the users aware that the information will be available to your application, and you must provide legally adequate privacy notice and protection for those users. If your application stores personal or sensitive information provided by users, it must do so securely. If the user provides your application with Google Account information, your application may only use that information to access the user's Google Account when, and for the limited purposes for which, the user has given you permission to do so.
+4.3 You agree that if you use the SDK to develop applications for general public users, you will
+protect the privacy and legal rights of those users. If the users provide you with user names,
+passwords, or other login information or personal information, you must make the users aware that
+the information will be available to your application, and you must provide legally adequate
+privacy notice and protection for those users. If your application stores personal or sensitive
+information provided by users, it must do so securely. If the user provides your application with
+Google Account information, your application may only use that information to access the user's
+Google Account when, and for the limited purposes for which, the user has given you permission to
+do so.
-4.4 You agree that you will not engage in any activity with the SDK, including the development or distribution of an application, that interferes with, disrupts, damages, or accesses in an unauthorized manner the servers, networks, or other properties or services of any third party including, but not limited to, Google or any mobile communications carrier.
+4.4 You agree that you will not engage in any activity with the SDK, including the development or
+distribution of an application, that interferes with, disrupts, damages, or accesses in an
+unauthorized manner the servers, networks, or other properties or services of any third party
+including, but not limited to, Google or any mobile communications carrier.
-4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any data, content, or resources that you create, transmit or display through Android and/or applications for Android, and for the consequences of your actions (including any loss or damage which Google may suffer) by doing so.
+4.5 You agree that you are solely responsible for (and that Google has no responsibility to you or
+to any third party for) any data, content, or resources that you create, transmit or display
+through Android and/or applications for Android, and for the consequences of your actions
+(including any loss or damage which Google may suffer) by doing so.
-4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or to any third party for) any breach of your obligations under this License Agreement, any applicable third party contract or Terms of Service, or any applicable law or regulation, and for the consequences (including any loss or damage which Google or any third party may suffer) of any such breach.
+4.6 You agree that you are solely responsible for (and that Google has no responsibility to you or
+to any third party for) any breach of your obligations under this License Agreement, any applicable
+third party contract or Terms of Service, or any applicable law or regulation, and for the
+consequences (including any loss or damage which Google or any third party may suffer) of any such
+breach.
<h3>5. Your Developer Credentials</h3>
-5.1 You agree that you are responsible for maintaining the confidentiality of any developer credentials that may be issued to you by Google or which you may choose yourself and that you will be solely responsible for all applications that are developed under your developer credentials.
+5.1 You agree that you are responsible for maintaining the confidentiality of any developer
+credentials that may be issued to you by Google or which you may choose yourself and that you will
+be solely responsible for all applications that are developed under your developer credentials.
<h3>6. Privacy and Information</h3>
-6.1 In order to continually innovate and improve the SDK, Google may collect certain usage statistics from the software including but not limited to a unique identifier, associated IP address, version number of the software, and information on which tools and/or services in the SDK are being used and how they are being used. Before any of this information is collected, the SDK will notify you and seek your consent. If you withhold consent, the information will not be collected.
+6.1 In order to continually innovate and improve the SDK, Google may collect certain usage
+statistics from the software including but not limited to a unique identifier, associated IP
+address, version number of the software, and information on which tools and/or services in the SDK
+are being used and how they are being used. Before any of this information is collected, the SDK
+will notify you and seek your consent. If you withhold consent, the information will not be
+collected.
-6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in accordance with Google's Privacy Policy.
+6.2 The data collected is examined in the aggregate to improve the SDK and is maintained in
+accordance with Google's Privacy Policy.
<h3>7. Third Party Applications</h3>
-7.1 If you use the SDK to run applications developed by a third party or that access data, content or resources provided by a third party, you agree that Google is not responsible for those applications, data, content, or resources. You understand that all data, content or resources which you may access through such third party applications are the sole responsibility of the person from which they originated and that Google is not liable for any loss or damage that you may experience as a result of the use or access of any of those third party applications, data, content, or resources.
+7.1 If you use the SDK to run applications developed by a third party or that access data, content
+or resources provided by a third party, you agree that Google is not responsible for those
+applications, data, content, or resources. You understand that all data, content or resources which
+you may access through such third party applications are the sole responsibility of the person from
+which they originated and that Google is not liable for any loss or damage that you may experience
+as a result of the use or access of any of those third party applications, data, content, or
+resources.
-7.2 You should be aware the data, content, and resources presented to you through such a third party application may be protected by intellectual property rights which are owned by the providers (or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell, distribute or create derivative works based on these data, content, or resources (either in whole or in part) unless you have been specifically given permission to do so by the relevant owners.
+7.2 You should be aware the data, content, and resources presented to you through such a third
+party application may be protected by intellectual property rights which are owned by the providers
+(or by other persons or companies on their behalf). You may not modify, rent, lease, loan, sell,
+distribute or create derivative works based on these data, content, or resources (either in whole
+or in part) unless you have been specifically given permission to do so by the relevant owners.
-7.3 You acknowledge that your use of such third party applications, data, content, or resources may be subject to separate terms between you and the relevant third party. In that case, this License Agreement does not affect your legal relationship with these third parties.
+7.3 You acknowledge that your use of such third party applications, data, content, or resources may
+be subject to separate terms between you and the relevant third party. In that case, this License
+Agreement does not affect your legal relationship with these third parties.
<h3>8. Using Android APIs</h3>
8.1 Google Data APIs
-8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be protected by intellectual property rights which are owned by Google or those parties that provide the data (or by other persons or companies on their behalf). Your use of any such API may be subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or create derivative works based on this data (either in whole or in part) unless allowed by the relevant Terms of Service.
+8.1.1 If you use any API to retrieve data from Google, you acknowledge that the data may be
+protected by intellectual property rights which are owned by Google or those parties that provide
+the data (or by other persons or companies on their behalf). Your use of any such API may be
+subject to additional Terms of Service. You may not modify, rent, lease, loan, sell, distribute or
+create derivative works based on this data (either in whole or in part) unless allowed by the
+relevant Terms of Service.
-8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you shall retrieve data only with the user's explicit consent and only when, and for the limited purposes for which, the user has given you permission to do so.
+8.1.2 If you use any API to retrieve a user's data from Google, you acknowledge and agree that you
+shall retrieve data only with the user's explicit consent and only when, and for the limited
+purposes for which, the user has given you permission to do so.
<h3>9. Terminating this License Agreement</h3>
-9.1 This License Agreement will continue to apply until terminated by either you or Google as set out below.
+9.1 This License Agreement will continue to apply until terminated by either you or Google as set
+out below.
-9.2 If you want to terminate this License Agreement, you may do so by ceasing your use of the SDK and any relevant developer credentials.
+9.2 If you want to terminate this License Agreement, you may do so by ceasing your use of the SDK
+and any relevant developer credentials.
9.3 Google may at any time, terminate this License Agreement with you if:
(A) you have breached any provision of this License Agreement; or
(B) Google is required to do so by law; or
-(C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated its relationship with Google or ceased to offer certain parts of the SDK to you; or
-(D) Google decides to no longer provide the SDK or certain parts of the SDK to users in the country in which you are resident or from which you use the service, or the provision of the SDK or certain SDK services to you by Google is, in Google's sole discretion, no longer commercially viable.
+(C) the partner with whom Google offered certain parts of SDK (such as APIs) to you has terminated
+its relationship with Google or ceased to offer certain parts of the SDK to you; or
+(D) Google decides to no longer provide the SDK or certain parts of the SDK to users in the country
+in which you are resident or from which you use the service, or the provision of the SDK or certain
+SDK services to you by Google is, in Google's sole discretion, no longer commercially viable.
-9.4 When this License Agreement comes to an end, all of the legal rights, obligations and liabilities that you and Google have benefited from, been subject to (or which have accrued over time whilst this License Agreement has been in force) or which are expressed to continue indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall continue to apply to such rights, obligations and liabilities indefinitely.
+9.4 When this License Agreement comes to an end, all of the legal rights, obligations and
+liabilities that you and Google have benefited from, been subject to (or which have accrued over
+time whilst this License Agreement has been in force) or which are expressed to continue
+indefinitely, shall be unaffected by this cessation, and the provisions of paragraph 14.7 shall
+continue to apply to such rights, obligations and liabilities indefinitely.
<h3>10. DISCLAIMER OF WARRANTIES</h3>
-10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
+10.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SDK IS AT YOUR SOLE RISK AND THAT THE
+SDK IS PROVIDED "AS IS" AND "AS AVAILABLE" WITHOUT WARRANTY OF ANY KIND FROM GOOGLE.
-10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE.
+10.2 YOUR USE OF THE SDK AND ANY MATERIAL DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE
+SDK IS AT YOUR OWN DISCRETION AND RISK AND YOU ARE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR
+COMPUTER SYSTEM OR OTHER DEVICE OR LOSS OF DATA THAT RESULTS FROM SUCH USE.
-10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+10.3 GOOGLE FURTHER EXPRESSLY DISCLAIMS ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
<h3>11. LIMITATION OF LIABILITY</h3>
-11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
+11.1 YOU EXPRESSLY UNDERSTAND AND AGREE THAT GOOGLE, ITS SUBSIDIARIES AND AFFILIATES, AND ITS
+LICENSORS SHALL NOT BE LIABLE TO YOU UNDER ANY THEORY OF LIABILITY FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES THAT MAY BE INCURRED BY YOU, INCLUDING ANY
+LOSS OF DATA, WHETHER OR NOT GOOGLE OR ITS REPRESENTATIVES HAVE BEEN ADVISED OF OR SHOULD HAVE BEEN
+AWARE OF THE POSSIBILITY OF ANY SUCH LOSSES ARISING.
<h3>12. Indemnification</h3>
-12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless Google, its affiliates and their respective directors, officers, employees and agents from and against any and all claims, actions, suits or proceedings, as well as any and all losses, liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of any person or defames any person or violates their rights of publicity or privacy, and (c) any non-compliance by you with this License Agreement.
+12.1 To the maximum extent permitted by law, you agree to defend, indemnify and hold harmless
+Google, its affiliates and their respective directors, officers, employees and agents from and
+against any and all claims, actions, suits or proceedings, as well as any and all losses,
+liabilities, damages, costs and expenses (including reasonable attorneys fees) arising out of or
+accruing from (a) your use of the SDK, (b) any application you develop on the SDK that infringes
+any copyright, trademark, trade secret, trade dress, patent or other intellectual property right of
+any person or defames any person or violates their rights of publicity or privacy, and (c) any
+non-compliance by you with this License Agreement.
<h3>13. Changes to the License Agreement</h3>
-13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK. When these changes are made, Google will make a new version of the License Agreement available on the website where the SDK is made available.
+13.1 Google may make changes to the License Agreement as it distributes new versions of the SDK.
+When these changes are made, Google will make a new version of the License Agreement available on
+the website where the SDK is made available.
<h3>14. General Legal Terms</h3>
-14.1 This License Agreement constitutes the whole legal agreement between you and Google and governs your use of the SDK (excluding any services which Google may provide to you under a separate written agreement), and completely replaces any prior agreements between you and Google in relation to the SDK.
+14.1 This License Agreement constitutes the whole legal agreement between you and Google and
+governs your use of the SDK (excluding any services which Google may provide to you under a
+separate written agreement), and completely replaces any prior agreements between you and Google in
+relation to the SDK.
-14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is contained in this License Agreement (or which Google has the benefit of under any applicable law), this will not be taken to be a formal waiver of Google's rights and that those rights or remedies will still be available to Google.
+14.2 You agree that if Google does not exercise or enforce any legal right or remedy which is
+contained in this License Agreement (or which Google has the benefit of under any applicable law),
+this will not be taken to be a formal waiver of Google's rights and that those rights or remedies
+will still be available to Google.
-14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any provision of this License Agreement is invalid, then that provision will be removed from this License Agreement without affecting the rest of this License Agreement. The remaining provisions of this License Agreement will continue to be valid and enforceable.
+14.3 If any court of law, having the jurisdiction to decide on this matter, rules that any
+provision of this License Agreement is invalid, then that provision will be removed from this
+License Agreement without affecting the rest of this License Agreement. The remaining provisions of
+this License Agreement will continue to be valid and enforceable.
-14.4 You acknowledge and agree that each member of the group of companies of which Google is the parent shall be third party beneficiaries to this License Agreement and that such other companies shall be entitled to directly enforce, and rely upon, any provision of this License Agreement that confers a benefit on (or rights in favor of) them. Other than this, no other person or company shall be third party beneficiaries to this License Agreement.
+14.4 You acknowledge and agree that each member of the group of companies of which Google is the
+parent shall be third party beneficiaries to this License Agreement and that such other companies
+shall be entitled to directly enforce, and rely upon, any provision of this License Agreement that
+confers a benefit on (or rights in favor of) them. Other than this, no other person or company
+shall be third party beneficiaries to this License Agreement.
-14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
+14.5 EXPORT RESTRICTIONS. THE SDK IS SUBJECT TO UNITED STATES EXPORT LAWS AND REGULATIONS. YOU MUST
+COMPLY WITH ALL DOMESTIC AND INTERNATIONAL EXPORT LAWS AND REGULATIONS THAT APPLY TO THE SDK. THESE
+LAWS INCLUDE RESTRICTIONS ON DESTINATIONS, END USERS AND END USE.
-14.6 The rights granted in this License Agreement may not be assigned or transferred by either you or Google without the prior written approval of the other party. Neither you nor Google shall be permitted to delegate their responsibilities or obligations under this License Agreement without the prior written approval of the other party.
+14.6 The rights granted in this License Agreement may not be assigned or transferred by either you
+or Google without the prior written approval of the other party. Neither you nor Google shall be
+permitted to delegate their responsibilities or obligations under this License Agreement without
+the prior written approval of the other party.
-14.7 This License Agreement, and your relationship with Google under this License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from this License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
+14.7 This License Agreement, and your relationship with Google under this License Agreement, shall
+be governed by the laws of the State of California without regard to its conflict of laws
+provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located
+within the county of Santa Clara, California to resolve any legal matter arising from this License
+Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for
+injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
<em>November 13, 2012</em>
@@ -272,6 +430,182 @@
<p>
<a href="#" onclick="return toggleContent(this)"> <img
src="/assets/images/triangle-opened.png" class="toggle-content-img" alt=""
+ >Android NDK, Revision 10</a> <em>(July 2014)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+ <dl>
+ <dt>Important changes:</dt>
+ <dd>
+ <ul>
+ <li>Added 3 new ABIs, all 64-bit: arm64-v8a, x86_64, mips64.</li> Note that:
+ <ul>
+ <li>GCC 4.9 is the default compiler for 64-bit ABIs. Clang is currently version 3.4.
+<code>NDK_TOOLCHAIN_VERSION=clang</code>
+ may not work for arm64-v8a and mips64.</li>
+ <li>Android API level L is the first level with 64-bit support. Note that this API
+level is a temporary one, and only for L-preview. An actual API level number will replace it at
+L-release.</li>
+ <li>This release includes now includes <code>all32</code> and <code>all64</code>
+settings for <code>APP_ABI</code>.
+ <ul>
+ <li><code>APP_ABI=all32</code> is equivalent to
+<code>APP_ABI=armeabi,armeabi-v7a,x86,mips</code>.</li>
+ <li><code>APP_ABI=all64</code> is equivalent to
+<code>APP_ABI=arm64-v8a,x86_64,mips64</code>.</li>
+ <li><code>APP_ABI=all</code> selects all ABIs.</li>
+ </ul>
+ <li>The new GNU libstdc++ in Android-L contains all <code><tr1/cmath></code>
+Before defining your own math function, check <code>_GLIBCXX_USE_C99_MATH_TR1</code> to see a
+function with that name already exists, in order to avoid "multiple definition" errors from the
+linker.</li>
+ <li>The cpu-features library has been updated for the ARMv8 kernel. The existing
+cpu-features library may fail to detect the presence of NEON on the ARMv8 platform. Recompile your
+code with the new version.</li>
+ </ul>
+ <li>Added a new <code>platforms/android-L/</code> API directory. It includes:</li>
+ <ul>
+ <li>Updated Bionic headers, which had not changed from Android API levels 3
+(Cupcake) to 19 (KitKat). This new version, for level L, is to be synchronized with AOSP.</li>
+ <li>New media APIs and a native-codec sample.</li>
+ <li>An updated <code>Android.h</code> header for SLES/OpenSLES, enabling support for
+single-precision, floating-point audio format in AudioPlayer.</li>
+ <li>GLES 3.1 and AEP extensions to <code>libGLESv3.so.</code></li>
+ <li>GLES2 and GLES3 headers updated to the latest official Khronos versions.</li>
+ </ul>
+ <li>Added GCC 4.9 compilers to the 32-/64-bit ABIs. GCC 4.9 is the default (only) compiler
+for 64-bit ABIs, as previously mentioned. For 32-bit ABIs, you must explcitly enable GCC 4.9, as
+GCC 4.6 is still the default.</li>
+ <ul>
+ <li>For ndk-build, enable 32-bit, GCC 4.9 building either by adding
+<code>NDK_TOOLCHAIN_VERSION=4.9</code> to <code>Application.mk</code>, or exporting it as an
+environment variable from the command line.</li>
+ <li>For a standalone toolchain, use the <code> --toolchain=</code> option in the
+<code>make-standalone-toolchain.sh</code> script. For example: <code>--toolchain=arm-linux-androideabi-4.9.</code></li>
+ </ul>
+ <li>Upgraded GDB to version 7.6 in GCC 4.8/4.9 and x86*. Since GDB is still at version GDB-7.3.x in
+GCC 4.6 (the default for ARM and MIPS), you must set
+<code>NDK_TOOLCHAIN_VERSION=4.8</code> or <code>4.9</code> to enable ndk-gdb to select GDB 7.6.</li>
+ <li>Added the <code>-mssse3</code> build option to provide SSSE3 support, and made it the default for ABI x86
+(upgrading from SSE3). The image released by Google does not contain SSSE3 instructions.</li>
+ <li>Updated GCC 4.8 to 4.8.3.</li>
+ <li>Improved ARM libc++ EH support by switching from gabi++ to libc++abi. For details, see the "C++ Support" section of the documentation.
+ Note that:</li>
+ <ul>
+ <li>All tests except for locale now pass for Clang 3.4 and GCC 4.8. For more
+information, see the "C++ Support" section of the documentation.</li>
+ <li>The libc++ libraries for X86 and MIPS libc++ still use gabi++.</li>
+ <li>GCC 4.7 and later can now use <atomic>.</li>
+ <li>You must add <code>-fno-strict-aliasing</code> if you use <code> <list></code>, because <code>__list_imp::_end</code>_ breaks
+ TBAA rules. (Issue <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61571">61571</a>.)</li>
+ <li>As of GCC 4.6, LIBCXX_FORCE_REBUILD:=true no longer rebuilds libc++. Rebuilding it
+requires the use of a different compiler. Note that Clang 3.3 is untested.</li>
+ </ul>
+ <li>mclinker is now version 2.7, and has aarch64 Linux support.</li>
+ <li>Added precompiled header support for headers specified by <code>LOCAL_PCH</code>. (Issue <a href="http://b.android.com/25412">25412</a>).</li>
+ </dd>
+ <dl>
+
+
+ <dt>Important bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed libc++ so that it now compiles <code>std::feof</code>, etc. (Issue <a
+href="http://b.android.com/66668">66668</a>).</li>
+ <li>Fixed a Clang 3.3/3.4 atomic library call that caused crashes in some of the libc++
+tests for ABI armeabi.</li>
+ <li>Fixed Clang 3.4 crashes that were occurring on reading precompiled headers. (Issue <a
+href="http://b.android.com/66657">66657</a>).</li>
+ <li>Fixed the Clang 3.3/3.4 <code>-O3</code> assert on:</li>
+ <code>llvm-3.2/llvm/include/llvm/MDBuilder.h:64: llvm::MDNode*
+llvm::MDBuilder::createBranchWeights(llvm::ArrayRef<unsigned int>): Assertion Weights.size() >= 2
+&& "Need at least two branch weights!"</code> (Issue <a href="http://b.android.com/57381">57381</a>).
+ <li>Fixed the following Clang 3.3/3.4 crash:</li>
+ <code>Assertion failed: (!Fn && "cast failed but able to resolve overload expression!!"), function CheckCXXCStyleCast, file
+Volumes/data/ndk-toolchain/src/llvm-3.3/llvm/tools/clang/lib/Sema/SemaCast.cpp, line 2018</code>.
+(Issue <a href="http://b.android.com/66950">66950</a>).
+ </ul>
+ </dd>
+
+ <dt>Other bug fixes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed headers:</li>
+ <ul>
+ <li>Fixed 32-bit <code>ssize_t</code> to be <code>int</code> instead of <code>long
+int</code>.</li>
+ <li>Fixed <code>WCHAR_MIN</code> and <code>WCHAR_MAX</code> so that they they take
+appropriate signs according to the architecture they're running on:</li>
+ <ul>
+ <li>X86/MIPS: signed.
+ <li>ARM: unsigned.
+ <li>To force X86/MIPS to default to unsigned, use
+<code>-D__WCHAR_UNSIGNED__</code>.</li>
+ <li>To force <code>wchar_t</code> to be 16 bits, use <code>-fshort-wchar</code>.</li>
+ </ul>
+ <li>Removed non-existent symbols from 32-bit <code>libc.so</code>, and added <code>pread64</code>,
+<code>pwrite64</code>, <code>ftruncate64</code> for
+Android API level 12 and higher. (Issue <a href="http://b.android.com/69319">69319</a>). For more
+information, see the commit message accompanying AOSP change list
+ <a href="https://android-review.googlesource.com/#/c/94137">94137</a>.</li>
+ </ul>
+ <li>Fixed GCC warning about redefinition of <code>putchar</code>. Warning message reads:</li>
+ <code>include/stdio.h:236:5: warning: conflicts with previous declaration here
+[-Wattributes] int putchar(int);</code> (Change list <a
+href="https://android-review.googlesource.com/#/c/91185">91185</a>).
+ <li>Fixed <code>make-standalone-toolchain.sh --stl=libc++</code> so that it:</li>
+ <ul>
+ <li>Copies <code>cxxabi.h</code>. (Issue <a
+href="http://b.android.com/68001">68001</a>).</li>
+ <li>Runs in directories other than the NDK install directory. (Issues <a
+href="http://b.android.com/67690">67690</a> and <a href="http://b.android.com/68647">68647</a>).</li>
+ </ul>
+ <li>Fixed GCC/Windows to quote arguments only when necessary for spawning processes in
+external programs. This change decreases the likelihood of exceeding the 32K length limit.</li>
+ <li>Fixed an issue that made it impossible to adjust the <code>APP_PLATFORM</code>
+environment variable.</li>
+ <li>Fixed the implementation of <code>IsSystemLibrary()</code> in crazy_linker so that it
+uses <code>strrchr()</code>
+ instead of <code>strchr()</code> to find the library path's true basename.</li>
+ <li>Fixed native-audio's inability to build in debug mode.</li>
+ <li>Fixed gdb's inability to print extreme floating-point numbers. (Issue <a
+href="http://b.android.com/69203">69203</a>).</li>
+ <li>Fixed Clang 3.4 inability to compile with <code>-Wl,-shared</code> (as opposed to
+<code>-shared</code>, which
+ had no compilation issues). The problem was that Clang added <code>-pie</code> for Android
+targets if neither <code>-shared</code> nor <code>-static</code> existed. This behavior, which was
+incorrect, caused the linker to complain that <code>-shared</code> and <code>-pie</code> could not
+co-exist.</li>
+
+ </ul>
+ </dd>
+
+
+ <dt>Other changes:</dt>
+ <dd>
+ <ul>
+ <li>Added <code>arm_neon.h</code> to the x86 toolchain so that it now emulates ~47% of
+Neon. There is currently no support for 64-bit types. For more information, see the section on ARM
+Neon intrinsics support in the x86 documentation.</li>
+ <li>Ported ARM/GOT_PREL optimization (present in GCC 4.6 built from the GCC google branch) to
+ARM GCC 4.8/4.9. This optimization sometimes reduces instruction count when accessing global
+variables. As an example, see the build.sh script in
+<code>$NDK/tests/build/b14811006-GOT_PREL-optimization/</code>.</li>
+ <li>Added ARM version for STL gabi++, stlport, and libc++. They now have both it and Thumb
+mode.</li>
+ <li>It is now possible to call the make-standalone-toolchain.sh script with
+<code>--toolchain=x86_64-linux-android-4.9</code>, which is equivalent to
+<code>--toolchain=x86_64-4.9</code>.</li>
+ </dd>
+ </ul>
+ </dl>
+ </div>
+</div>
+
+
+<div class="toggle-content closed">
+ <p>
+ <a href="#" onclick="return toggleContent(this)"> <img
+ src="/assets/images/triangle-closed.png" class="toggle-content-img" alt=""
>Android NDK, Revision 9d</a> <em>(March 2014)</em>
</p>
<div class="toggle-content-toggleme">
@@ -284,7 +618,7 @@
still the default compiler.</li>
<li>Added <code>APP_ABI=armeabi-v7a-hard</code>, with
additional multilib option <code>-mfloat-abi=hard</code>. These options are for
-use with ARM GCC 4.6/4.8 and clang 3.3/3.4 (which use 4.8's assembler, linker,
+use with ARM GCC 4.6/4.8 and Clang 3.3/3.4 (which use 4.8's assembler, linker,
and libs). When using these options, note the following changes:</li>
<ul>
<li> When executing the <code>ndk-build</code> script, add the
@@ -322,7 +656,7 @@
</ul>
For more information, see
<code>CPLUSPLUS-SUPPORT.html</code>.
-(Issue <a href="b.android.com/36496">36496</a>)</li>
+(Issue <a href="http://b.android.com/36496">36496</a>)</li>
</ul>
</dd>
<dl>
@@ -337,7 +671,7 @@
a dependent, non-type template argument. (GCC Issue <a
href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59052">59052</a>)</li>
<li>Added more modules to prebuilt python (Issue <a
-href="b.android.com/59902">59902</a>):
+href="http://b.android.com/59902">59902</a>):
<ul>
<li>Mac OS X: <code>zlib</code>, <code>bz2</code>,
<code>_curses</code>, <code>_curses_panel</code>, <code>_hashlib</code>,
@@ -637,7 +971,8 @@
(<a href="http://b.android.com/55826">Issue 55826</a>)</li>
<li>Fixed Clang 3.3 MIPS compiler problem where HI and LO registers are incorrectly
reused.</li>
- <li>Fixed issue with MIPS 4.7 ICE in {@code dbx_reg_number}. The error message is as follows:
+ <li>Fixed issue with MIPS 4.7 ICE in {@code dbx_reg_number}. The error message is as
+follows:
<pre>
external/icu4c/i18n/decimfmt.cpp:1322:1:
internal compiler error: in dbx_reg_number, at dwarf2out.c:10185
@@ -721,11 +1056,13 @@
<li>Modified GCC builds so that all {@code libgcc.a} files are built with
<code>-funwind-tables</code> to allow the stack to be unwound past previously blocked
points, such as <code>__aeabi_idiv0</code>.</li>
- <li>Added Ingenic MXU support in MIPS GCC4.6/4.7/4.8 with new <code>-mmxu</code> option.</li>
+ <li>Added Ingenic MXU support in MIPS GCC4.6/4.7/4.8 with new <code>-mmxu</code>
+option.</li>
<li>Extended MIPS GCC4.6/4.7/4.8 <code>-mldc1-sdc1</code> to control ldxc1/sdxc1 too</li>
<li>Added crazy linker. For more information, see
{@code sources/android/crazy_linker/README.TXT}.</li>
- <li>Fixed {@code bitmap-plasma} to draw to full screen rather than a 200x200 pixel area.</li>
+ <li>Fixed {@code bitmap-plasma} to draw to full screen rather than a 200x200 pixel
+area.</li>
<li>Reduced linux and darwin toolchain sizes by 25% by creating symlinks to identical files.
</li>
</ul>
@@ -935,7 +1272,8 @@
<li>Added two flags to re-enable two optimizations in upstream Clang but disabled in
NDK for better compatibility with code compiled by GCC:
<ul>
- <li>Added a {@code -fcxx-missing-return-semantics} flag to re-enable <em>missing return
+ <li>Added a {@code -fcxx-missing-return-semantics} flag to re-enable <em>missing
+return
semantics</em> in Clang 3.2+. Normally, all paths should terminate with a return
statement for a value-returning function. If this is not the case, clang inserts
an undefined instruction (or trap in debug mode) at the path without a return
@@ -1079,7 +1417,8 @@
(<a href="https://android-review.googlesource.com/#/c/52134">Change 52134</a>)</li>
<li>Fixed Clang 3.1 internal compiler error when using Eigen library.
(<a href="http://b.android.com/41246">Issue 41246</a>)</li>
- <li>Fixed Clang 3.1 internal compiler error including {@code <chrono>} in C++11 mode.
+ <li>Fixed Clang 3.1 internal compiler error including {@code <chrono>} in C++11
+mode.
(<a href="http://b.android.com/39600">Issue 39600</a>)</li>
<li>Fixed Clang 3.1 internal compiler error when generating object code for a method
call to a uniform initialized {@code rvalue}.
@@ -1088,7 +1427,8 @@
(<a href="https://android-review.googlesource.com/#/c/52154">Change 52154</a>)</li>
<li>Fixed problem with GNU Debugger (GDB) SIGILL when debugging on Android 4.1.2.
(<a href="http://b.android.com/40941">Issue 40941</a>)</li>
- <li>Fixed problem where GDB cannot set {@code source:line} breakpoints when symbols contain
+ <li>Fixed problem where GDB cannot set {@code source:line} breakpoints when symbols
+contain
long, indirect file paths.
(<a href="http://b.android.com/42448">Issue 42448</a>)</li>
<li>Fixed GDB {@code read_program_header} for MIPS PIE executables.
@@ -1182,7 +1522,8 @@
<li>Enabled MIPS floating-point {@code madd/msub/nmadd/nmsub/recip/rsqrt}
instructions with 32-bit FPU.</li>
<li>Enabled graphite loop optimizer in GCC 4.6 and 4.7 to allow more optimizations:
- {@code -fgraphite}, {@code -fgraphite-identity}, {@code -floop-block}, {@code -floop-flatten},
+ {@code -fgraphite}, {@code -fgraphite-identity}, {@code -floop-block}, {@code
+-floop-flatten},
{@code -floop-interchange}, {@code -floop-strip-mine}, {@code -floop-parallelize-all},
and {@code -ftree-loop-linear}.
(<a href="http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html">info</a>)</li>
@@ -1379,7 +1720,9 @@
<li>Updated {@code make-standalone-toolchain.sh} to accept the suffix {@code -clang3.1}
which is equivalent to adding {@code --llvm-version=3.1} to the GCC 4.6 toolchain.</li>
<li>Updated GCC and Clang bug report URL to:
- <a href="http://source.android.com/source/report-bugs.html">http://source.android.com/source/report-bugs.html</a></li>
+ <a
+href="http://source.android.com/source/report-bugs.html">http://source.android.com/source/report-bug
+s.html</a></li>
<li>Added ARM ELF support to {@code llvm-objdump}.</li>
<li>Suppressed <em>treating c input as c++</em> warning for Clang builds.</li>
<li>Updated build so that only the 32-bit version of {@code libiberty.a} is built and
@@ -1418,7 +1761,8 @@
<a href="http://code.google.com/p/android/issues/list">report any issues</a>.</p></li>
<li>Added Gold linker {@code ld.gold} for the Windows toolchain. Gold linker is also the
default for ARM and X86 on all hosts. You may override it to use the {@code ld.bfd}
- linker by adding {@code LOCAL_LDFLAGS += -fuse-ld=bfd} to {@code Android.mk}, or by passing
+ linker by adding {@code LOCAL_LDFLAGS += -fuse-ld=bfd} to {@code Android.mk}, or by
+passing
{@code -fuse-ld=bfd} to the g++/clang++ command line that does the linking.</li>
<li>Added checks for spaces in the NDK path to the {@code ndk-build[.cmd]} and
{@code ndk-gdb} scripts, to prevent build errors that are difficult to diagnose.</li>
@@ -1605,7 +1949,8 @@
<li>Replaced {@code link.h} for MIPS with new version supporting all platforms.</li>
<li>Removed {@code linux-unistd.h}</li>
<li>Move GLibc-specific macros {@code LONG_LONG_MIN}, {@code LONG_LONG_MAX} and
- {@code ULONG_LONG_MAX} from {@code <pthread.h>} to {@code <limits.h>}.</li>
+ {@code ULONG_LONG_MAX} from {@code <pthread.h>} to {@code
+<limits.h>}.</li>
</ul>
</li>
<li>Fixed a buffer overflow in {@code ndk-stack-parser}.</li>
@@ -1767,7 +2112,8 @@
<li>Fixed ARM {@code strip} command to preserve the original {@code p_align} and
{@code p_flags} in {@code GNU_RELRO} section if they are valid. Without this fix, programs
built with {@code -fPIE} could not be debugged. (<a
-href="http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf.c.diff?cvsroot=src&r1=1.552&r2=1.553">more info</a>)</li>
+href="http://sourceware.org/cgi-bin/cvsweb.cgi/src/bfd/elf.c.diff?cvsroot=src&r1=1.552&r2=1.553">mor
+e info</a>)</li>
</ul>
</li>
<li>Disabled {@code sincos()} optimization for compatibility with older
@@ -2505,7 +2851,8 @@
</li>
- <li>You can build a standalone x86 toolchain using the <code>--toolchain=x86-4.4.3</code>
+ <li>You can build a standalone x86 toolchain using the
+<code>--toolchain=x86-4.4.3</code>
option when calling <code>make-standalone-toolchain.sh</code>. See
<code>docs/STANDALONE-TOOLCHAIN.html</code> for more details.
</li>
@@ -2548,7 +2895,8 @@
<li>Fixed a bug where code linked against <code>gnustl_static</code> crashed when run on
platform releases older than API level 8 (Android 2.2).</li>
- <li><code>ndk-gdb</code>: Fixed a bug that caused a segmentation fault when debugging Android 3.0
+ <li><code>ndk-gdb</code>: Fixed a bug that caused a segmentation fault when debugging
+Android 3.0
or newer devices.</li>
<li><code><android/input.h></code>: Two functions that were introduced in API level
@@ -2617,12 +2965,14 @@
</p>
<div class="toggle-content-toggleme">
- <p>This release of the NDK does not include any new features compared to r5. The r5b release addresses the
+ <p>This release of the NDK does not include any new features compared to r5. The r5b release
+addresses the
following problems in the r5 release:
</p>
<ul>
<li>The r5 binaries required glibc 2.11, but the r5b binaries are generated with a special
- toolchain that targets glibc 2.7 or higher instead. The Linux toolchain binaries now run on Ubuntu 8.04 or higher. </li>
+ toolchain that targets glibc 2.7 or higher instead. The Linux toolchain binaries now run on
+Ubuntu 8.04 or higher. </li>
<li>Fixes a compiler bug in the arm-linux-androideabi-4.4.3 toolchain.
The previous binary generated invalid thumb instruction sequences when
dealing with signed chars.</li>
@@ -2642,21 +2992,29 @@
with the new NDK toolchain.</li>
<li>Builds in Cygwin are faster by avoiding calls to <code>cygpath -m</code>
from GNU Make for every source or object file, which caused problems
- with very large source trees. In case this doesn't work properly, define <code>NDK_USE_CYGPATH=1</code> in your
+ with very large source trees. In case this doesn't work properly, define
+<code>NDK_USE_CYGPATH=1</code> in your
environment to use <code>cygpath -m</code> again.</li>
- <li>The Cygwin installation now notifies the user of invalid installation paths that contain spaces. Previously, an invalid path
- would output an error that complained about an incorrect version of GNU Make, even if the right one was installed.
+ <li>The Cygwin installation now notifies the user of invalid installation paths that
+contain spaces. Previously, an invalid path
+ would output an error that complained about an incorrect version of GNU Make, even if the
+right one was installed.
</ul>
</li>
- <li>Fixed a typo that prevented the <code>NDK_MODULE_PATH</code> environment variable from working properly when
+ <li>Fixed a typo that prevented the <code>NDK_MODULE_PATH</code> environment variable from
+working properly when
it contained multiple directories separated with a colon. </li>
<li>The <code>prebuilt-common.sh</code> script contains fixes to check the compiler for 64-bit
generated machine code, instead of relying on the host tag, which
- allows the 32-bit toolchain to rebuild properly on Snow Leopard. The toolchain rebuild scripts now also support
+ allows the 32-bit toolchain to rebuild properly on Snow Leopard. The toolchain rebuild scripts
+now also support
using a 32-bit host toolchain.</li>
- <li>A missing declaration for <code>INET_ADDRSTRLEN</code> was added to <code><netinet/in.h></code>.</li>
- <li>Missing declarations for <code>IN6_IS_ADDR_MC_NODELOCAL</code> and <code>IN6_IS_ADDR_MC_GLOBAL</code> were added to <code><netinet/in6.h></code>.</li>
- <li>'asm' was replaced with '__asm__' in <code><asm/byteorder.h></code> to allow compilation with <code>-std=c99</code>.</li>
+ <li>A missing declaration for <code>INET_ADDRSTRLEN</code> was added to
+<code><netinet/in.h></code>.</li>
+ <li>Missing declarations for <code>IN6_IS_ADDR_MC_NODELOCAL</code> and
+<code>IN6_IS_ADDR_MC_GLOBAL</code> were added to <code><netinet/in6.h></code>.</li>
+ <li>'asm' was replaced with '__asm__' in <code><asm/byteorder.h></code> to allow
+compilation with <code>-std=c99</code>.</li>
</ul>
</div>
</div>
@@ -2673,8 +3031,10 @@
of native code. Using the APIs, developers have direct native access to events, audio,
graphics and window management, assets, and storage. Developers can also implement the
Android application lifecycle in native code with help from the new
- {@link android.app.NativeActivity} class. For detailed information describing the changes in this
- release, read the <code>CHANGES.HTML</code> document included in the downloaded NDK package.
+ {@link android.app.NativeActivity} class. For detailed information describing the changes
+in this
+ release, read the <code>CHANGES.HTML</code> document included in the downloaded NDK
+package.
</p>
<dl>
<dt>General notes:</dt>
@@ -2703,35 +3063,46 @@
</ul>
</li>
- <li>Includes a new toolchain (based on GCC 4.4.3), which generates better code, and can also now
+ <li>Includes a new toolchain (based on GCC 4.4.3), which generates better code, and can
+also now
be used as a standalone cross-compiler, for people who want to build their stuff with
<code>./configure && make</code>. See
- docs/STANDALONE-TOOLCHAIN.html for the details. The binaries for GCC 4.4.0 are still provided,
+ docs/STANDALONE-TOOLCHAIN.html for the details. The binaries for GCC 4.4.0 are still
+provided,
but the 4.2.1 binaries were removed.</li>
- <li>Adds support for prebuilt static and shared libraries (docs/PREBUILTS.html) and module
+ <li>Adds support for prebuilt static and shared libraries (docs/PREBUILTS.html) and
+module
exports and imports to make sharing and reuse of third-party modules much easier
(docs/IMPORT-MODULE.html explains why).</li>
- <li>Provides a default C++ STL implementation (based on STLport) as a helper module. It can be used either
- as a static or shared library (details and usage examples are in sources/android/stlport/README). Prebuilt
- binaries for STLport (static or shared) and GNU libstdc++ (static only) are also provided if you choose to
+ <li>Provides a default C++ STL implementation (based on STLport) as a helper module. It
+can be used either
+ as a static or shared library (details and usage examples are in
+sources/android/stlport/README). Prebuilt
+ binaries for STLport (static or shared) and GNU libstdc++ (static only) are also
+provided if you choose to
compile against those libraries instead of the default C++ STL implementation.
- C++ Exceptions and RTTI are not supported in the default STL implementation. For more information, see
+ C++ Exceptions and RTTI are not supported in the default STL implementation. For more
+information, see
docs/CPLUSPLUS-SUPPORT.HTML.</li>
- <li>Includes improvements to the <code>cpufeatures</code> helper library that improves reporting
- of the CPU type (some devices previously reported ARMv7 CPU when the device really was an ARMv6). We
+ <li>Includes improvements to the <code>cpufeatures</code> helper library that improves
+reporting
+ of the CPU type (some devices previously reported ARMv7 CPU when the device really was
+an ARMv6). We
recommend developers that use this library to rebuild their applications then
upload to Google Play to benefit from the improvements.</li>
<li>Adds an EGL library that lets you create and manage OpenGL ES textures and
services.</li>
- <li>Adds new sample applications, <code>native-plasma</code> and <code>native-activity</code>,
+ <li>Adds new sample applications, <code>native-plasma</code> and
+<code>native-activity</code>,
to demonstrate how to write a native activity.</li>
- <li>Includes many bugfixes and other small improvements; see docs/CHANGES.html for a more
+ <li>Includes many bugfixes and other small improvements; see docs/CHANGES.html for a
+more
detailed list of changes.</li>
</ul>
</dd>
@@ -3043,7 +3414,8 @@
</table>
<p>For more information about API Level and its relationship to Android platform versions,
- see <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">Android API Levels</a>.</p>
+ see <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#ApiLevels">Android API
+Levels</a>.</p>
</li>
<li>Additionally, an application using the OpenGL ES APIs should declare a
@@ -3061,7 +3433,8 @@
</pre>
<p>For more information, see the <a href=
- "{@docRoot}guide/topics/manifest/uses-feature-element.html"><code><uses-feature></code></a>
+
+"{@docRoot}guide/topics/manifest/uses-feature-element.html"><code><uses-feature></code></a>
documentation.</p>
</li>
@@ -3104,7 +3477,8 @@
<p>Before you get started make sure that you have downloaded the latest <a href=
"{@docRoot}sdk/index.html">Android SDK</a> and upgraded your applications and environment as
- needed. The NDK is compatible with older platform versions but not older versions of the SDK tools.
+ needed. The NDK is compatible with older platform versions but not older versions of the SDK
+tools.
Also, take a moment to review the <a href="#Reqs">System and
Software Requirements</a>
for the NDK, if you haven't already.</p>
@@ -3178,7 +3552,8 @@
<p>Write a native activity, which allows you to implement the lifecycle callbacks in native
code. The Android SDK provides the {@link android.app.NativeActivity} class, which is a
convenience class that notifies your
- native code of any activity lifecycle callbacks (<code>onCreate()</code>, <code>onPause()</code>,
+ native code of any activity lifecycle callbacks (<code>onCreate()</code>,
+<code>onPause()</code>,
<code>onResume()</code>, etc). You can implement the callbacks in your native code to handle
these events when they occur. Applications that use native activities must be run on Android
2.3 (API Level 9) or later.</p>
@@ -3230,7 +3605,8 @@
difference between the two instruction sets is that ARMv7-A supports hardware FPU, Thumb-2, and
NEON instructions. You can target either or both of the instruction sets — ARMv5TE is the
default, but switching to ARMv7-A is as easy as adding a single line to the application's
- <code>Application.mk</code> file, without needing to change anything else in the file. You can also build for
+ <code>Application.mk</code> file, without needing to change anything else in the file. You can
+also build for
both architectures at the same time and have everything stored in the final <code>.apk</code>.
Complete information is provided in the CPU-ARCH-ABIS.HTML in the NDK package.</p>
@@ -3311,13 +3687,15 @@
<li>CHANGES.HTML — a complete list of changes to the NDK across all releases.</li>
- <li>DEVELOPMENT.HTML — describes how to modify the NDK and generate release packages for it</li>
+ <li>DEVELOPMENT.HTML — describes how to modify the NDK and generate release packages for
+it</li>
<li>HOWTO.HTML — information about common tasks associated with NDK development</li>
<li>IMPORT-MODULE.HTML — describes how to share and reuse modules</li>
- <li>LICENSES.HTML — information about the various open source licenses that govern the Android NDK</li>
+ <li>LICENSES.HTML — information about the various open source licenses that govern the
+Android NDK</li>
<li>NATIVE-ACTIVITY.HTML — describes how to implement native activities</li>
diff --git a/docs/html/training/wearables/data-layer/events.jd b/docs/html/training/wearables/data-layer/events.jd
index 0146c4e..a37afe0 100644
--- a/docs/html/training/wearables/data-layer/events.jd
+++ b/docs/html/training/wearables/data-layer/events.jd
@@ -43,7 +43,8 @@
@Override
public void onResult(final DataItemResult result) {
if(result.getStatus().isSuccess()) {
- Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
+ Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
+ }
}
});
</pre>
@@ -293,7 +294,7 @@
@Override
protected void onStop() {
if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
- Wearable.NodeApi.removeListener(mGoogleApiClient, this);
+ Wearable.DataApi.removeListener(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
super.onStop();
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 9561ac4..4b00e22 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -73,8 +73,8 @@
*/
private boolean mRequestPremultiplied;
- private byte[] mNinePatchChunk; // may be null
- private int[] mOpticalInsets; // may be null
+ private byte[] mNinePatchChunk; // may be null
+ private NinePatch.InsetStruct mNinePatchInsets; // may be null
private int mWidth;
private int mHeight;
private boolean mRecycled;
@@ -111,7 +111,7 @@
@SuppressWarnings({"UnusedDeclaration"}) // called from JNI
Bitmap(long nativeBitmap, byte[] buffer, int width, int height, int density,
boolean isMutable, boolean requestPremultiplied,
- byte[] ninePatchChunk, int[] opticalInsets) {
+ byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
if (nativeBitmap == 0) {
throw new RuntimeException("internal error: native bitmap is 0");
}
@@ -126,7 +126,7 @@
mFinalizer = new BitmapFinalizer(nativeBitmap);
mNinePatchChunk = ninePatchChunk;
- mOpticalInsets = opticalInsets;
+ mNinePatchInsets = ninePatchInsets;
if (density >= 0) {
mDensity = density;
}
@@ -946,16 +946,18 @@
* @hide
*/
public void getOpticalInsets(@NonNull Rect outInsets) {
- if (mOpticalInsets == null) {
+ if (mNinePatchInsets == null) {
outInsets.setEmpty();
} else {
- outInsets.left = mOpticalInsets[0];
- outInsets.top = mOpticalInsets[1];
- outInsets.right = mOpticalInsets[2];
- outInsets.bottom = mOpticalInsets[3];
+ outInsets.set(mNinePatchInsets.opticalRect);
}
}
+ /** @hide */
+ public NinePatch.InsetStruct getNinePatchInsets() {
+ return mNinePatchInsets;
+ }
+
/**
* Specifies the known formats a bitmap can be compressed into
*/
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 99596ef..ef4b260 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -158,7 +158,7 @@
if (nativeCanvas == 0) {
throw new IllegalStateException();
}
- mNativeCanvasWrapper = initCanvas(nativeCanvas);
+ mNativeCanvasWrapper = nativeCanvas;
mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper);
mDensity = Bitmap.getDefaultDensity();
}
@@ -237,6 +237,9 @@
*/
public void setViewport(int width, int height) {}
+ /** @hide */
+ public void setHighContrastText(boolean highContrastText) {}
+
/**
* @hide
*/
@@ -921,7 +924,7 @@
* @param b blue component (0..255) of the color to draw onto the canvas
*/
public void drawRGB(int r, int g, int b) {
- native_drawRGB(mNativeCanvasWrapper, r, g, b);
+ drawColor(Color.rgb(r, g, b));
}
/**
@@ -934,7 +937,7 @@
* @param b blue component (0..255) of the color to draw onto the canvas
*/
public void drawARGB(int a, int r, int g, int b) {
- native_drawARGB(mNativeCanvasWrapper, a, r, g, b);
+ drawColor(Color.argb(a, r, g, b));
}
/**
@@ -944,7 +947,7 @@
* @param color the color to draw onto the canvas
*/
public void drawColor(int color) {
- native_drawColor(mNativeCanvasWrapper, color);
+ native_drawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
}
/**
@@ -1298,13 +1301,28 @@
*/
public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
@Nullable Paint paint) {
- if (dst == null) {
- throw new NullPointerException();
- }
- throwIfCannotDraw(bitmap);
- native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), src, dst,
- paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
- }
+ if (dst == null) {
+ throw new NullPointerException();
+ }
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+
+ float left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
+ }
+
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+ bitmap.mDensity);
+ }
/**
* Draw the specified bitmap, scaling/translating automatically to fill
@@ -1334,8 +1352,23 @@
throw new NullPointerException();
}
throwIfCannotDraw(bitmap);
- native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), src, dst,
- paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+
+ int left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
+ }
+
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+ bitmap.mDensity);
}
/**
@@ -1863,7 +1896,6 @@
public static native void freeTextLayoutCaches();
private static native long initRaster(long nativeBitmapOrZero);
- private static native long initCanvas(long canvasHandle);
private static native void native_setBitmap(long canvasHandle,
long bitmapHandle,
boolean copyState);
@@ -1916,11 +1948,6 @@
private static native boolean native_quickReject(long nativeCanvas,
float left, float top,
float right, float bottom);
- private static native void native_drawRGB(long nativeCanvas, int r, int g,
- int b);
- private static native void native_drawARGB(long nativeCanvas, int a, int r,
- int g, int b);
- private static native void native_drawColor(long nativeCanvas, int color);
private static native void native_drawColor(long nativeCanvas, int color,
int mode);
private static native void native_drawPaint(long nativeCanvas,
@@ -1962,16 +1989,9 @@
int screenDensity,
int bitmapDensity);
private native void native_drawBitmap(long nativeCanvas, long nativeBitmap,
- Rect src, RectF dst,
- long nativePaintOrZero,
- int screenDensity,
- int bitmapDensity);
- private static native void native_drawBitmap(long nativeCanvas,
- long nativeBitmap,
- Rect src, Rect dst,
- long nativePaintOrZero,
- int screenDensity,
- int bitmapDensity);
+ float srcLeft, float srcTop, float srcRight, float srcBottom,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ long nativePaintOrZero, int screenDensity, int bitmapDensity);
private static native void native_drawBitmap(long nativeCanvas, int[] colors,
int offset, int stride, float x,
float y, int width, int height,
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 28fd7ba..ab4258d 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -54,9 +54,12 @@
* cr_offset = y_size
* cb_offset = y_size + c_size</pre>
*
- * <p>This format is guaranteed to be supported for camera preview images since
- * API level 12; for earlier API versions, check
- * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+ * <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
+ * recommended for YUV output instead.</p>
+ *
+ * <p>For the older camera API, this format is guaranteed to be supported for
+ * {@link android.hardware.Camera} preview images since API level 12; for earlier API versions,
+ * check {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
*
* <p>Note that for camera preview callback use (see
* {@link android.hardware.Camera#setPreviewCallback}), the
@@ -133,29 +136,47 @@
public static final int Y16 = 0x20363159;
/**
- * YCbCr format, used for video. Whether this format is supported by the
- * camera hardware can be determined by
- * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+ * YCbCr format, used for video.
+ *
+ * <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
+ * recommended for YUV output instead.</p>
+ *
+ * <p>Whether this format is supported by the old camera API can be determined by
+ * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.</p>
+ *
*/
public static final int NV16 = 0x10;
/**
- * YCrCb format used for images, which uses the NV21 encoding format. This
- * is the default format for camera preview images, when not otherwise set
- * with {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}.
+ * YCrCb format used for images, which uses the NV21 encoding format.
+ *
+ * <p>This is the default format
+ * for {@link android.hardware.Camera} preview images, when not otherwise set with
+ * {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}.</p>
+ *
+ * <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
+ * recommended for YUV output instead.</p>
*/
public static final int NV21 = 0x11;
/**
* YCbCr format used for images, which uses YUYV (YUY2) encoding format.
- * This is an alternative format for camera preview images. Whether this
- * format is supported by the camera hardware can be determined by
- * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
+ *
+ * <p>For the {@link android.hardware.camera2} API, the {@link #YUV_420_888} format is
+ * recommended for YUV output instead.</p>
+ *
+ * <p>This is an alternative format for {@link android.hardware.Camera} preview images. Whether
+ * this format is supported by the camera hardware can be determined by
+ * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.</p>
*/
public static final int YUY2 = 0x14;
/**
- * Encoded formats. These are not necessarily supported by the hardware.
+ * Compressed JPEG format.
+ *
+ * <p>This format is always supported as an output format for the
+ * {@link android.hardware.camera2} API, and as a picture format for the older
+ * {@link android.hardware.Camera} API</p>
*/
public static final int JPEG = 0x100;
@@ -332,16 +353,6 @@
public static final int RAW10 = 0x25;
/**
- * Raw bayer format used for images, which is 10 bit precision samples
- * stored in 16 bit words. The filter pattern is RGGB. Whether this format
- * is supported by the camera hardware can be determined by
- * {@link android.hardware.Camera.Parameters#getSupportedPreviewFormats()}.
- *
- * @hide
- */
- public static final int BAYER_RGGB = 0x200;
-
- /**
* Use this function to retrieve the number of bits per pixel of an
* ImageFormat.
*
@@ -369,8 +380,6 @@
return 12;
case RAW_SENSOR:
return 16;
- case BAYER_RGGB:
- return 16;
case RAW10:
return 10;
}
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index befac92..335bce0 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -16,7 +16,6 @@
package android.graphics;
-
/**
* The NinePatch class permits drawing a bitmap in nine or more sections.
* Essentially, it allows the creation of custom graphics that will scale the
@@ -32,6 +31,39 @@
* </p>
*/
public class NinePatch {
+ /**
+ * Struct of inset information attached to a 9 patch bitmap.
+ *
+ * Present on a 9 patch bitmap if it optical insets were manually included,
+ * or if outline insets were automatically included by aapt.
+ *
+ * @hide
+ */
+ public static class InsetStruct {
+ @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
+ InsetStruct(int opticalLeft, int opticalTop, int opticalRight, int opticalBottom,
+ int outlineLeft, int outlineTop, int outlineRight, int outlineBottom,
+ float outlineRadius, boolean outlineFilled, float decodeScale) {
+ opticalRect = new Rect(opticalLeft, opticalTop, opticalRight, opticalBottom);
+ outlineRect = new Rect(outlineLeft, outlineTop, outlineRight, outlineBottom);
+
+ if (decodeScale != 1.0f) {
+ // if bitmap was scaled when decoded, scale the insets from the metadata values
+ opticalRect.scale(decodeScale);
+
+ // round inward while scaling outline, as the outline should always be conservative
+ outlineRect.scaleRoundIn(decodeScale);
+ }
+ this.outlineRadius = outlineRadius * decodeScale;
+ this.outlineFilled = outlineFilled;
+ }
+
+ public final Rect opticalRect;
+ public final Rect outlineRect;
+ public final float outlineRadius;
+ public final boolean outlineFilled;
+ }
+
private final Bitmap mBitmap;
/**
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 437d2f4..a9a8f37 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -609,4 +609,17 @@
bottom = (int) (bottom * scale + 0.5f);
}
}
+
+ /**
+ * Scales up the rect by the given scale, rounding values toward the inside.
+ * @hide
+ */
+ public void scaleRoundIn(float scale) {
+ if (scale != 1.0f) {
+ left = (int) Math.ceil(left * scale);
+ top = (int) Math.ceil(top * scale);
+ right = (int) Math.floor(right * scale);
+ bottom = (int) Math.floor(bottom * scale);
+ }
+ }
}
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 17795f3..f52c661 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -27,14 +27,18 @@
/**
* Captures frames from an image stream as an OpenGL ES texture.
*
- * <p>The image stream may come from either camera preview or video decode. A SurfaceTexture
- * may be used in place of a SurfaceHolder when specifying the output destination of a
- * {@link android.hardware.Camera} or {@link android.media.MediaPlayer}
- * object. Doing so will cause all the frames from the image stream to be sent to the
- * SurfaceTexture object rather than to the device's display. When {@link #updateTexImage} is
- * called, the contents of the texture object specified when the SurfaceTexture was created are
- * updated to contain the most recent image from the image stream. This may cause some frames of
- * the stream to be skipped.
+ * <p>The image stream may come from either camera preview or video decode. A
+ * {@link android.view.Surface} created from a SurfaceTexture can be used as an output
+ * destination for the {@link android.hardware.camera2}, {@link android.media.MediaCodec},
+ * {@link android.media.MediaPlayer}, and {@link android.renderscript.Allocation} APIs.
+ * When {@link #updateTexImage} is called, the contents of the texture object specified
+ * when the SurfaceTexture was created are updated to contain the most recent image from the image
+ * stream. This may cause some frames of the stream to be skipped.
+ *
+ * <p>A SurfaceTexture may also be used in place of a SurfaceHolder when specifying the output
+ * destination of the older {@link android.hardware.Camera} API. Doing so will cause all the
+ * frames from the image stream to be sent to the SurfaceTexture object rather than to the device's
+ * display.
*
* <p>When sampling from the texture one should first transform the texture coordinates using the
* matrix queried via {@link #getTransformMatrix(float[])}. The transform matrix may change each
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 8483820..2cb7b03 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -16,8 +16,6 @@
package android.graphics.drawable;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.annotation.NonNull;
@@ -26,6 +24,7 @@
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.LongSparseLongArray;
import android.util.SparseIntArray;
import android.util.StateSet;
@@ -62,19 +61,21 @@
* @attr ref android.R.styleable#DrawableStates_state_pressed
*/
public class AnimatedStateListDrawable extends StateListDrawable {
+ private static final String LOGTAG = AnimatedStateListDrawable.class.getSimpleName();
+
private static final String ELEMENT_TRANSITION = "transition";
private static final String ELEMENT_ITEM = "item";
private AnimatedStateListState mState;
- /** The currently running animation, if any. */
- private ObjectAnimator mAnim;
+ /** The currently running transition, if any. */
+ private Transition mTransition;
- /** Index to be set after the animation ends. */
- private int mAnimToIndex = -1;
+ /** Index to be set after the transition ends. */
+ private int mTransitionToIndex = -1;
- /** Index away from which we are animating. */
- private int mAnimFromIndex = -1;
+ /** Index away from which we are transitioning. */
+ private int mTransitionFromIndex = -1;
private boolean mMutated;
@@ -84,20 +85,13 @@
@Override
public boolean setVisible(boolean visible, boolean restart) {
- // If we're relying on an Animatable transition, the super method
- // will handle visibility changes.
final boolean changed = super.setVisible(visible, restart);
- if (mAnim != null) {
+ if (mTransition != null && (changed || restart)) {
if (visible) {
- if (restart) {
- mAnim.cancel();
- mAnim.start();
- } else if (changed && mAnim.isPaused()) {
- mAnim.resume();
- }
- } else if (mAnim.isRunning()) {
- mAnim.pause();
+ mTransition.start();
+ } else {
+ mTransition.stop();
}
}
@@ -164,90 +158,193 @@
}
private boolean selectTransition(int toIndex) {
- if (toIndex == mAnimToIndex) {
- // Already animating to that keyframe.
- return true;
- }
-
- if (mAnim != null) {
- if (toIndex == mAnimToIndex) {
+ final int fromIndex;
+ final Transition currentTransition = mTransition;
+ if (currentTransition != null) {
+ if (toIndex == mTransitionToIndex) {
+ // Already animating to that keyframe.
return true;
- } else if (toIndex == mAnimFromIndex) {
+ } else if (toIndex == mTransitionFromIndex && currentTransition.canReverse()) {
// Reverse the current animation.
- mAnim.reverse();
- mAnimFromIndex = mAnimToIndex;
- mAnimToIndex = toIndex;
+ currentTransition.reverse();
+ mTransitionToIndex = mTransitionFromIndex;
+ mTransitionFromIndex = toIndex;
return true;
}
+ // Start the next transition from the end of the current one.
+ fromIndex = mTransitionToIndex;
+
// Changing animation, end the current animation.
- mAnim.cancel();
- mAnim = null;
+ currentTransition.stop();
+ } else {
+ fromIndex = getCurrentIndex();
}
// Reset state.
- mAnimFromIndex = -1;
- mAnimToIndex = -1;
+ mTransition = null;
+ mTransitionFromIndex = -1;
+ mTransitionToIndex = -1;
final AnimatedStateListState state = mState;
- final int fromIndex = getCurrentIndex();
final int fromId = state.getKeyframeIdAt(fromIndex);
final int toId = state.getKeyframeIdAt(toIndex);
-
if (toId == 0 || fromId == 0) {
// Missing a keyframe ID.
return false;
}
final int transitionIndex = state.indexOfTransition(fromId, toId);
- if (transitionIndex < 0 || !selectDrawable(transitionIndex)) {
+ if (transitionIndex < 0) {
// Couldn't select a transition.
return false;
}
+ // This may fail if we're already on the transition, but that's okay!
+ selectDrawable(transitionIndex);
+
+ final Transition transition;
final Drawable d = getCurrent();
if (d instanceof AnimationDrawable) {
- // We can support reverse() here.
- final boolean reversed = mState.isTransitionReversed(fromId, toId);
- mAnim = getAnimationDrawableAnimator((AnimationDrawable) d, reversed);
- mAnim.start();
+ final boolean reversed = state.isTransitionReversed(fromId, toId);
+ transition = new AnimationDrawableTransition((AnimationDrawable) d, reversed);
+ } else if (d instanceof AnimatedVectorDrawable) {
+ final boolean reversed = state.isTransitionReversed(fromId, toId);
+ transition = new AnimatedVectorDrawableTransition((AnimatedVectorDrawable) d, reversed);
} else if (d instanceof Animatable) {
- // Let the transition animate itself.
- ((Animatable) d).start();
+ transition = new AnimatableTransition((Animatable) d);
} else {
// We don't know how to animate this transition.
return false;
}
- mAnimFromIndex = fromIndex;
- mAnimToIndex = toIndex;
+ transition.start();
+
+ mTransition = transition;
+ mTransitionFromIndex = fromIndex;
+ mTransitionToIndex = toIndex;
return true;
}
- private ObjectAnimator getAnimationDrawableAnimator(@NonNull AnimationDrawable ad,
- boolean reversed) {
- final int frameCount = ad.getNumberOfFrames();
- final int fromFrame = reversed ? frameCount - 1 : 0;
- final int toFrame = reversed ? 0 : frameCount - 1;
- final FrameInterpolator interp = new FrameInterpolator(ad, reversed);
- final ObjectAnimator anim = ObjectAnimator.ofInt(ad, "currentIndex", fromFrame, toFrame);
- anim.setAutoCancel(true);
- anim.setDuration(interp.getTotalDuration());
- anim.addListener(mAnimListener);
- anim.setInterpolator(interp);
+ private static abstract class Transition {
+ public abstract void start();
+ public abstract void stop();
- return anim;
+ public void reverse() {
+ // Not supported by default.
+ }
+
+ public boolean canReverse() {
+ return false;
+ }
}
+ private static class AnimatableTransition extends Transition {
+ private final Animatable mA;
+
+ public AnimatableTransition(Animatable a) {
+ mA = a;
+ }
+
+ @Override
+ public void start() {
+ mA.start();
+ }
+
+ @Override
+ public void stop() {
+ mA.stop();
+ }
+ }
+
+
+ private static class AnimationDrawableTransition extends Transition {
+ private final ObjectAnimator mAnim;
+
+ public AnimationDrawableTransition(AnimationDrawable ad, boolean reversed) {
+ final int frameCount = ad.getNumberOfFrames();
+ final int fromFrame = reversed ? frameCount - 1 : 0;
+ final int toFrame = reversed ? 0 : frameCount - 1;
+ final FrameInterpolator interp = new FrameInterpolator(ad, reversed);
+ final ObjectAnimator anim = ObjectAnimator.ofInt(ad, "currentIndex", fromFrame, toFrame);
+ anim.setAutoCancel(true);
+ anim.setDuration(interp.getTotalDuration());
+ anim.setInterpolator(interp);
+
+ mAnim = anim;
+ }
+
+ @Override
+ public boolean canReverse() {
+ return true;
+ }
+
+ @Override
+ public void start() {
+ mAnim.start();
+ }
+
+ @Override
+ public void reverse() {
+ mAnim.reverse();
+ }
+
+ @Override
+ public void stop() {
+ mAnim.cancel();
+ }
+ }
+
+ private static class AnimatedVectorDrawableTransition extends Transition {
+ private final AnimatedVectorDrawable mAvd;
+ private final boolean mReversed;
+
+ public AnimatedVectorDrawableTransition(AnimatedVectorDrawable avd, boolean reversed) {
+ mAvd = avd;
+ mReversed = reversed;
+ }
+
+ @Override
+ public boolean canReverse() {
+ return mAvd.canReverse();
+ }
+
+ @Override
+ public void start() {
+ if (mReversed) {
+ reverse();
+ } else {
+ mAvd.start();
+ }
+ }
+
+ @Override
+ public void reverse() {
+ if (canReverse()) {
+ mAvd.reverse();
+ } else {
+ Log.w(LOGTAG, "Reverse() is called on a drawable can't reverse");
+ }
+ }
+
+ @Override
+ public void stop() {
+ mAvd.stop();
+ }
+ }
+
+
@Override
public void jumpToCurrentState() {
- // If we're relying on an Animatable transition, the super method
- // will handle jumping it to the current state.
super.jumpToCurrentState();
- if (mAnim != null) {
- mAnim.end();
- mAnim = null;
+ if (mTransition != null) {
+ mTransition.stop();
+ mTransition = null;
+
+ selectDrawable(mTransitionToIndex);
+ mTransitionToIndex = -1;
+ mTransitionFromIndex = -1;
}
}
@@ -404,17 +501,6 @@
return this;
}
- private final AnimatorListenerAdapter mAnimListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator anim) {
- selectDrawable(mAnimToIndex);
-
- mAnimToIndex = -1;
- mAnimFromIndex = -1;
- mAnim = null;
- }
- };
-
static class AnimatedStateListState extends StateListState {
private static final int REVERSE_SHIFT = 32;
private static final int REVERSE_MASK = 0x1;
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 1cecef3..11c2571 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -16,6 +16,7 @@
import android.animation.Animator;
import android.animation.AnimatorInflater;
+import android.animation.ValueAnimator;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
@@ -209,6 +210,7 @@
if (drawableRes != 0) {
mAnimatedVectorState.mVectorDrawable = (VectorDrawable) res.getDrawable(
drawableRes, theme).mutate();
+ mAnimatedVectorState.mVectorDrawable.setAllowCaching(false);
}
a.recycle();
} else if (TARGET.equals(tagName)) {
@@ -258,6 +260,7 @@
mChangingConfigurations = copy.mChangingConfigurations;
// TODO: Make sure the constant state are handled correctly.
mVectorDrawable = new VectorDrawable();
+ mVectorDrawable.setAllowCaching(false);
mAnimators = new ArrayList<Animator>();
}
}
@@ -329,4 +332,38 @@
animator.pause();
}
}
+
+ /**
+ * Reverses ongoing animations or starts pending animations in reverse.
+ * <p>
+ * NOTE: Only works of all animations are ValueAnimators.
+ * @hide
+ */
+ public void reverse() {
+ final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+ final int size = animators.size();
+ for (int i = 0; i < size; i++) {
+ final Animator animator = animators.get(i);
+ if (animator.canReverse()) {
+ animator.reverse();
+ } else {
+ Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
+ }
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public boolean canReverse() {
+ final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+ final int size = animators.size();
+ for (int i = 0; i < size; i++) {
+ final Animator animator = animators.get(i);
+ if (!animator.canReverse()) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index e7a073c..89236ad 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -516,6 +516,11 @@
*/
public void setHotspotBounds(int left, int top, int right, int bottom) {}
+ /** @hide For internal use only. Individual results may vary. */
+ public void getHotspotBounds(Rect outRect) {
+ outRect.set(getBounds());
+ }
+
/**
* Whether this drawable requests projection.
*
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index ed44cde..771322d 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -52,6 +52,7 @@
*/
private static final boolean DEFAULT_DITHER = true;
private DrawableContainerState mDrawableContainerState;
+ private Rect mHotspotBounds;
private Drawable mCurrDrawable;
private int mAlpha = 0xFF;
@@ -273,11 +274,27 @@
@Override
public void setHotspotBounds(int left, int top, int right, int bottom) {
+ if (mHotspotBounds == null) {
+ mHotspotBounds = new Rect(left, top, bottom, right);
+ } else {
+ mHotspotBounds.set(left, top, bottom, right);
+ }
+
if (mCurrDrawable != null) {
mCurrDrawable.setHotspotBounds(left, top, right, bottom);
}
}
+ /** @hide */
+ @Override
+ public void getHotspotBounds(Rect outRect) {
+ if (mHotspotBounds != null) {
+ outRect.set(mHotspotBounds);
+ } else {
+ super.getHotspotBounds(outRect);
+ }
+ }
+
@Override
protected boolean onStateChange(int[] state) {
if (mLastDrawable != null) {
@@ -430,6 +447,12 @@
d.setBounds(getBounds());
d.setLayoutDirection(getLayoutDirection());
d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
+
+ final Rect hotspotBounds = mHotspotBounds;
+ if (hotspotBounds != null) {
+ d.setHotspotBounds(hotspotBounds.left, hotspotBounds.top,
+ hotspotBounds.right, hotspotBounds.bottom);
+ }
}
} else {
mCurrDrawable = null;
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index d214a47..6db96b6 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -232,6 +232,12 @@
mInsetState.mDrawable.setHotspotBounds(left, top, right, bottom);
}
+ /** @hide */
+ @Override
+ public void getHotspotBounds(Rect outRect) {
+ mInsetState.mDrawable.getHotspotBounds(outRect);
+ }
+
@Override
public boolean setVisible(boolean visible, boolean restart) {
mInsetState.mDrawable.setVisible(visible, restart);
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index fa68bc5..8d83c74 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -80,6 +80,7 @@
private int[] mPaddingB;
private final Rect mTmpRect = new Rect();
+ private Rect mHotspotBounds;
private boolean mMutated;
/**
@@ -630,6 +631,22 @@
for (int i = 0; i < N; i++) {
array[i].mDrawable.setHotspotBounds(left, top, right, bottom);
}
+
+ if (mHotspotBounds == null) {
+ mHotspotBounds = new Rect(left, top, right, bottom);
+ } else {
+ mHotspotBounds.set(left, top, right, bottom);
+ }
+ }
+
+ /** @hide */
+ @Override
+ public void getHotspotBounds(Rect outRect) {
+ if (mHotspotBounds != null) {
+ outRect.set(mHotspotBounds);
+ } else {
+ super.getHotspotBounds(outRect);
+ }
}
@Override
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 24bbf7c..c0110c9 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -16,6 +16,7 @@
package android.graphics.drawable;
+import android.annotation.NonNull;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
@@ -26,6 +27,7 @@
import android.graphics.ColorFilter;
import android.graphics.Insets;
import android.graphics.NinePatch;
+import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
@@ -281,14 +283,35 @@
return false;
}
+ @Override
+ public boolean getOutline(@NonNull Outline outline) {
+ final Rect bounds = getBounds();
+ if (bounds.isEmpty()) return false;
+
+ if (mNinePatchState != null) {
+ NinePatch.InsetStruct insets = mNinePatchState.getBitmap().getNinePatchInsets();
+ if (insets != null) {
+ final Rect outlineInsets = insets.outlineRect;
+ outline.setRoundRect(bounds.left + outlineInsets.left,
+ bounds.top + outlineInsets.top,
+ bounds.right - outlineInsets.right,
+ bounds.bottom - outlineInsets.bottom,
+ insets.outlineRadius);
+ outline.setFilled(insets.outlineFilled);
+ return true;
+ }
+ }
+ return super.getOutline(outline);
+ }
+
/**
* @hide
*/
@Override
public Insets getOpticalInsets() {
if (needsMirroring()) {
- return Insets.of(mOpticalInsets.right, mOpticalInsets.top, mOpticalInsets.right,
- mOpticalInsets.bottom);
+ return Insets.of(mOpticalInsets.right, mOpticalInsets.top,
+ mOpticalInsets.left, mOpticalInsets.bottom);
} else {
return mOpticalInsets;
}
@@ -574,7 +597,7 @@
}
NinePatchState(NinePatch ninePatch, Rect padding) {
- this(ninePatch, padding, new Rect(), DEFAULT_DITHER, false);
+ this(ninePatch, padding, null, DEFAULT_DITHER, false);
}
NinePatchState(NinePatch ninePatch, Rect padding, Rect opticalInsets) {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 4f05313..f955f7c 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -471,6 +471,12 @@
onHotspotBoundsChanged();
}
+ /** @hide */
+ @Override
+ public void getHotspotBounds(Rect outRect) {
+ outRect.set(mHotspotBounds);
+ }
+
/**
* Notifies all the animating ripples that the hotspot bounds have changed.
*/
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 8783994..8c907b2 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -18,6 +18,7 @@
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
@@ -142,6 +143,10 @@
private boolean mMutated;
+ // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
+ // caching the bitmap by default is allowed.
+ private boolean mAllowCaching = true;
+
public VectorDrawable() {
mVectorState = new VectorDrawableState();
}
@@ -183,7 +188,23 @@
final int saveCount = canvas.save();
final Rect bounds = getBounds();
canvas.translate(bounds.left, bounds.top);
- mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height());
+
+ if (!mAllowCaching) {
+ mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height());
+ } else {
+ Bitmap bitmap = mVectorState.mCachedBitmap;
+ if (bitmap == null || !mVectorState.canReuseCache(bounds.width(),
+ bounds.height())) {
+ bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
+ Bitmap.Config.ARGB_8888);
+ Canvas tmpCanvas = new Canvas(bitmap);
+ mVectorState.mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height());
+ mVectorState.mCachedBitmap = bitmap;
+
+ mVectorState.updateCacheStates();
+ }
+ canvas.drawBitmap(bitmap, null, bounds, null);
+ }
canvas.restoreToCount(saveCount);
}
@@ -444,6 +465,10 @@
return super.getChangingConfigurations() | mVectorState.mChangingConfigurations;
}
+ void setAllowCaching(boolean allowCaching) {
+ mAllowCaching = allowCaching;
+ }
+
private static class VectorDrawableState extends ConstantState {
int[] mThemeAttrs;
int mChangingConfigurations;
@@ -451,6 +476,12 @@
ColorStateList mTint;
Mode mTintMode;
+ Bitmap mCachedBitmap;
+ int[] mCachedThemeAttrs;
+ ColorStateList mCachedTint;
+ Mode mCachedTintMode;
+ int mCachedRootAlpha;
+
// Deep copy for mutate() or implicitly mutate.
public VectorDrawableState(VectorDrawableState copy) {
if (copy != null) {
@@ -462,6 +493,27 @@
}
}
+ public boolean canReuseCache(int width, int height) {
+ if (mCachedThemeAttrs == mThemeAttrs
+ && mCachedTint == mTint
+ && mCachedTintMode == mTintMode
+ && width == mCachedBitmap.getWidth()
+ && height == mCachedBitmap.getHeight()
+ && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
+ return true;
+ }
+ return false;
+ }
+
+ public void updateCacheStates() {
+ // Use shallow copy here and shallow comparison in canReuseCache(),
+ // likely hit cache miss more, but practically not much difference.
+ mCachedThemeAttrs = mThemeAttrs;
+ mCachedTint = mTint;
+ mCachedTintMode = mTintMode;
+ mCachedRootAlpha = mVPathRenderer.getRootAlpha();
+ }
+
public VectorDrawableState() {
mVPathRenderer = new VPathRenderer();
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index ba5594a..c7dc29b 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -31,10 +31,14 @@
namespace android {
namespace uirenderer {
-DisplayListRenderer::DisplayListRenderer():
- mCaches(Caches::getInstance()), mDisplayListData(0),
- mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
- mRestoreSaveCount(-1) {
+DisplayListRenderer::DisplayListRenderer()
+ : mCaches(Caches::getInstance())
+ , mDisplayListData(0)
+ , mTranslateX(0.0f)
+ , mTranslateY(0.0f)
+ , mHasTranslate(false)
+ , mHighContrastText(false)
+ , mRestoreSaveCount(-1) {
}
DisplayListRenderer::~DisplayListRenderer() {
@@ -367,6 +371,16 @@
return DrawGlInfo::kStatusDone;
}
+static void simplifyPaint(int color, SkPaint* paint) {
+ paint->setColor(color);
+ paint->setShader(NULL);
+ paint->setColorFilter(NULL);
+ paint->setLooper(NULL);
+ paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
+ paint->setStrokeJoin(SkPaint::kRound_Join);
+ paint->setLooper(NULL);
+}
+
status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
float x, float y, const float* positions, const SkPaint* paint,
float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
@@ -375,11 +389,34 @@
text = refText(text, bytesCount);
positions = refBuffer<float>(positions, count * 2);
- paint = refPaint(paint);
- DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count,
- x, y, positions, paint, totalAdvance, bounds);
- addDrawOp(op);
+ if (CC_UNLIKELY(mHighContrastText)) {
+ // high contrast draw path
+ int color = paint->getColor();
+ int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
+ bool darken = channelSum < (128 * 3);
+
+ // outline
+ SkPaint* outlinePaint = copyPaint(paint);
+ simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, outlinePaint);
+ outlinePaint->setStyle(SkPaint::kStrokeAndFill_Style);
+ addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
+ x, y, positions, outlinePaint, totalAdvance, bounds)); // bounds?
+
+ // inner
+ SkPaint* innerPaint = copyPaint(paint);
+ simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, innerPaint);
+ innerPaint->setStyle(SkPaint::kFill_Style);
+ addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
+ x, y, positions, innerPaint, totalAdvance, bounds));
+ } else {
+ // standard draw path
+ paint = refPaint(paint);
+
+ DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count,
+ x, y, positions, paint, totalAdvance, bounds);
+ addDrawOp(op);
+ }
return DrawGlInfo::kStatusDone;
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 2b2d402..d1d8572 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -154,6 +154,9 @@
// TODO: rename for consistency
virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
+ void setHighContrastText(bool highContrastText) {
+ mHighContrastText = highContrastText;
+ }
private:
void insertRestoreToCount();
void insertTranslate();
@@ -201,9 +204,7 @@
}
inline const SkPaint* refPaint(const SkPaint* paint) {
- if (!paint) {
- return paint;
- }
+ if (!paint) return NULL;
const SkPaint* paintCopy = mPaintMap.valueFor(paint);
if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
@@ -216,6 +217,14 @@
return paintCopy;
}
+ inline SkPaint* copyPaint(const SkPaint* paint) {
+ if (!paint) return NULL;
+ SkPaint* paintCopy = new SkPaint(*paint);
+ mDisplayListData->paints.add(paintCopy);
+
+ return paintCopy;
+ }
+
inline const SkRegion* refRegion(const SkRegion* region) {
if (!region) {
return region;
@@ -271,6 +280,7 @@
float mTranslateX;
float mTranslateY;
bool mHasTranslate;
+ bool mHighContrastText;
int mRestoreSaveCount;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index c9f541b..7fa1975 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2351,7 +2351,8 @@
return DrawGlInfo::kStatusDone;
}
- const Rect& bounds = vertexBuffer.getBounds();
+ Rect bounds(vertexBuffer.getBounds());
+ bounds.translate(translateX, translateY);
dirtyLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, *currentTransform());
int color = paint->getColor();
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 54fa143..8cc65b2 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -173,9 +173,6 @@
// UI thread only!
ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
-protected:
- virtual void damageSelf(TreeInfo& info);
-
private:
typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
@@ -250,6 +247,7 @@
void prepareLayer(TreeInfo& info);
void pushLayerUpdate(TreeInfo& info);
void deleteDisplayListData();
+ void damageSelf(TreeInfo& info);
void incParentRefCount() { mParentCount++; }
void decParentRefCount();
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 57279b7..a4ac262 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -185,6 +185,11 @@
} else if (!mDirtyRegionsEnabled || mHaveNewSurface) {
dirty.setEmpty();
} else {
+ if (!dirty.intersect(0, 0, width, height)) {
+ ALOGW("Dirty " RECT_STRING " doesn't intersect with 0 0 %d %d ?",
+ SK_RECT_ARGS(dirty), width, height);
+ dirty.setEmpty();
+ }
profiler().unionDirty(&dirty);
}
diff --git a/media/java/android/media/AudioDevice.java b/media/java/android/media/AudioDevice.java
index 1fd27fe..96d6196 100644
--- a/media/java/android/media/AudioDevice.java
+++ b/media/java/android/media/AudioDevice.java
@@ -66,8 +66,20 @@
return mConfig.port().address();
}
+ /** @hide */
+ public static int convertDeviceTypeToInternalDevice(int deviceType) {
+ return EXT_TO_INT_DEVICE_MAPPING.get(deviceType, AudioSystem.DEVICE_NONE);
+ }
+
+ /** @hide */
+ public static int convertInternalDeviceToDeviceType(int intDevice) {
+ return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, DEVICE_TYPE_UNKNOWN);
+ }
+
private static final SparseIntArray INT_TO_EXT_DEVICE_MAPPING;
+ private static final SparseIntArray EXT_TO_INT_DEVICE_MAPPING;
+
static {
INT_TO_EXT_DEVICE_MAPPING = new SparseIntArray();
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, DEVICE_TYPE_BUILTIN_EARPIECE);
@@ -110,6 +122,27 @@
// not covered here, legacy
//AudioSystem.DEVICE_OUT_REMOTE_SUBMIX
//AudioSystem.DEVICE_IN_REMOTE_SUBMIX
+
+ // privileges mapping to output device
+ EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_EARPIECE, AudioSystem.DEVICE_OUT_EARPIECE);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_SPEAKER, AudioSystem.DEVICE_OUT_SPEAKER);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_WIRED_HEADSET, AudioSystem.DEVICE_OUT_WIRED_HEADSET);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_WIRED_HEADPHONES, AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_LINE_ANALOG, AudioSystem.DEVICE_OUT_LINE);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_LINE_DIGITAL, AudioSystem.DEVICE_OUT_SPDIF);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_OUT_BLUETOOTH_SCO);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_HDMI, AudioSystem.DEVICE_OUT_HDMI);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_HDMI_ARC, AudioSystem.DEVICE_OUT_HDMI_ARC);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_USB_DEVICE, AudioSystem.DEVICE_OUT_USB_DEVICE);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_USB_ACCESSORY, AudioSystem.DEVICE_OUT_USB_ACCESSORY);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_DOCK, AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_FM, AudioSystem.DEVICE_OUT_FM);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER);
+ EXT_TO_INT_DEVICE_MAPPING.put(DEVICE_TYPE_TELEPHONY, AudioSystem.DEVICE_OUT_TELEPHONY_TX);
}
}
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 025d354..79be108 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -78,9 +78,9 @@
public static final int CHANNEL_OUT_FRONT_LEFT_OF_CENTER = 0x100;
public static final int CHANNEL_OUT_FRONT_RIGHT_OF_CENTER = 0x200;
public static final int CHANNEL_OUT_BACK_CENTER = 0x400;
- /** @hide */
+ /** @hide CANDIDATE FOR PUBLIC API */
public static final int CHANNEL_OUT_SIDE_LEFT = 0x800;
- /** @hide */
+ /** @hide CANDIDATE FOR PUBLIC API */
public static final int CHANNEL_OUT_SIDE_RIGHT = 0x1000;
/** @hide */
public static final int CHANNEL_OUT_TOP_CENTER = 0x2000;
@@ -128,6 +128,35 @@
CHANNEL_OUT_LOW_FREQUENCY);
// CHANNEL_OUT_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_OUT_ALL
+ /**
+ * @hide
+ * Return the number of channels from an output channel mask
+ * @param mask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT
+ * @return number of channels for the mask
+ */
+ public static int channelCountFromOutChannelMask(int mask) {
+ return Integer.bitCount(mask);
+ }
+ /**
+ * @hide
+ * Return a channel mask ready to be used by native code
+ * @param mask a combination of the CHANNEL_OUT_* definitions, but not CHANNEL_OUT_DEFAULT
+ * @return a native channel mask
+ */
+ public static int convertChannelOutMaskToNativeMask(int javaMask) {
+ return (javaMask >> 2);
+ }
+
+ /**
+ * @hide
+ * Return a java output channel mask
+ * @param mask a native channel mask
+ * @return a combination of the CHANNEL_OUT_* definitions
+ */
+ public static int convertNativeChannelMaskToOutMask(int nativeMask) {
+ return (nativeMask << 2);
+ }
+
public static final int CHANNEL_IN_DEFAULT = 1;
// These directly match native
public static final int CHANNEL_IN_LEFT = 0x4;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index eb6bf2c..ef95c11 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2912,6 +2912,20 @@
}
/**
+ * Notify audio manager about volume controller visibility changes.
+ * Currently limited to SystemUI.
+ *
+ * @hide
+ */
+ public void notifyVolumeControllerVisible(IVolumeController controller, boolean visible) {
+ try {
+ getService().notifyVolumeControllerVisible(controller, visible);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error notifying about volume controller visibility", e);
+ }
+ }
+
+ /**
* Only useful for volume controllers.
* @hide
*/
@@ -2940,15 +2954,12 @@
* Set Hdmi Cec system audio mode.
*
* @param on whether to be on system audio mode
- * @param device out device type to be used for system audio mode.
- * Ignored if {@code on} is {@code false}
- * @param name name of system audio device
* @return output device type. 0 (DEVICE_NONE) if failed to set device.
* @hide
*/
- public int setHdmiSystemAudioSupported(boolean on, int device, String name) {
+ public int setHdmiSystemAudioSupported(boolean on) {
try {
- return getService().setHdmiSystemAudioSupported(on, device, name);
+ return getService().setHdmiSystemAudioSupported(on);
} catch (RemoteException e) {
Log.w(TAG, "Error setting system audio mode", e);
return AudioSystem.DEVICE_NONE;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index b08d631..9d5fe23 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -61,6 +61,7 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.Vibrator;
@@ -392,10 +393,16 @@
// Indicates the mode used for SCO audio connection. The mode is virtual call if the request
// originated from an app targeting an API version before JB MR2 and raw audio after that.
private int mScoAudioMode;
+ // SCO audio mode is undefined
+ private static final int SCO_MODE_UNDEFINED = -1;
// SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall())
private static final int SCO_MODE_VIRTUAL_CALL = 0;
// SCO audio mode is raw audio (BluetoothHeadset.connectAudio())
private static final int SCO_MODE_RAW = 1;
+ // SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition())
+ private static final int SCO_MODE_VR = 2;
+
+ private static final int SCO_MODE_MAX = 2;
// Current connection state indicated by bluetooth headset
private int mScoConnectionState;
@@ -810,6 +817,9 @@
// Restore the default media button receiver from the system settings
mMediaFocusControl.restoreMediaButtonReceiver();
+
+ // Load settings for the volume controller
+ mVolumeController.loadSettings(cr);
}
private int rescaleIndex(int index, int srcStream, int dstStream) {
@@ -851,14 +861,23 @@
} else {
streamType = getActiveStreamType(suggestedStreamType);
}
+ final int resolvedStream = mStreamVolumeAlias[streamType];
// Play sounds on STREAM_RING and STREAM_REMOTE_MUSIC only.
if ((streamType != STREAM_REMOTE_MUSIC) &&
(flags & AudioManager.FLAG_PLAY_SOUND) != 0 &&
- (mStreamVolumeAlias[streamType] != AudioSystem.STREAM_RING)) {
+ resolvedStream != AudioSystem.STREAM_RING) {
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}
+ // For notifications/ring, show the ui before making any adjustments
+ if (mVolumeController.suppressAdjustment(resolvedStream, flags)) {
+ direction = 0;
+ flags &= ~AudioManager.FLAG_PLAY_SOUND;
+ flags &= ~AudioManager.FLAG_VIBRATE;
+ if (DEBUG_VOL) Log.d(TAG, "Volume controller suppressed adjustment");
+ }
+
if (streamType == STREAM_REMOTE_MUSIC) {
// TODO bounce it to MediaSessionService to find an appropriate
// session
@@ -2104,7 +2123,7 @@
public void startBluetoothSco(IBinder cb, int targetSdkVersion) {
int scoAudioMode =
(targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
- SCO_MODE_VIRTUAL_CALL : SCO_MODE_RAW;
+ SCO_MODE_VIRTUAL_CALL : SCO_MODE_UNDEFINED;
startBluetoothScoInt(cb, scoAudioMode);
}
@@ -2259,14 +2278,28 @@
mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
if (mScoAudioState == SCO_STATE_INACTIVE) {
mScoAudioMode = scoAudioMode;
+ if (scoAudioMode == SCO_MODE_UNDEFINED) {
+ mScoAudioMode = new Integer(Settings.Global.getInt(
+ mContentResolver,
+ "bluetooth_sco_channel_"+
+ mBluetoothHeadsetDevice.getAddress(),
+ SCO_MODE_VIRTUAL_CALL));
+ if (mScoAudioMode > SCO_MODE_MAX || mScoAudioMode < 0) {
+ mScoAudioMode = SCO_MODE_VIRTUAL_CALL;
+ }
+ }
if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
- boolean status;
+ boolean status = false;
if (mScoAudioMode == SCO_MODE_RAW) {
status = mBluetoothHeadset.connectAudio();
- } else {
+ } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
mBluetoothHeadsetDevice);
+ } else if (mScoAudioMode == SCO_MODE_VR) {
+ status = mBluetoothHeadset.startVoiceRecognition(
+ mBluetoothHeadsetDevice);
}
+
if (status) {
mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
} else {
@@ -2289,13 +2322,17 @@
mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
- boolean status;
+ boolean status = false;
if (mScoAudioMode == SCO_MODE_RAW) {
status = mBluetoothHeadset.disconnectAudio();
- } else {
+ } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
mBluetoothHeadsetDevice);
+ } else if (mScoAudioMode == SCO_MODE_VR) {
+ status = mBluetoothHeadset.stopVoiceRecognition(
+ mBluetoothHeadsetDevice);
}
+
if (!status) {
mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(
@@ -2489,17 +2526,23 @@
mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
if (mScoAudioMode == SCO_MODE_RAW) {
status = mBluetoothHeadset.connectAudio();
- } else {
+ } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
mBluetoothHeadsetDevice);
+ } else if (mScoAudioMode == SCO_MODE_VR) {
+ status = mBluetoothHeadset.startVoiceRecognition(
+ mBluetoothHeadsetDevice);
}
break;
case SCO_STATE_DEACTIVATE_REQ:
if (mScoAudioMode == SCO_MODE_RAW) {
status = mBluetoothHeadset.disconnectAudio();
- } else {
+ } else if (mScoAudioMode == SCO_MODE_VIRTUAL_CALL) {
status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
mBluetoothHeadsetDevice);
+ } else if (mScoAudioMode == SCO_MODE_VR) {
+ status = mBluetoothHeadset.stopVoiceRecognition(
+ mBluetoothHeadsetDevice);
}
break;
case SCO_STATE_DEACTIVATE_EXT_REQ:
@@ -3779,8 +3822,7 @@
}
if (mHdmiTvClient != null) {
- setHdmiSystemAudioSupported(mHdmiSystemAudioSupported,
- mHdmiSystemAudioOutputDevice, "");
+ setHdmiSystemAudioSupported(mHdmiSystemAudioSupported);
}
// indicate the end of reconfiguration phase to audio HAL
@@ -4761,113 +4803,25 @@
private boolean mHdmiSystemAudioSupported = false;
// Set only when device is tv.
private HdmiTvClient mHdmiTvClient;
- private int mHdmiSystemAudioOutputDevice = AudioSystem.DEVICE_NONE;
- private int[] mSpeakerGains;
@Override
- public int setHdmiSystemAudioSupported(boolean on, int device, String name) {
+ public int setHdmiSystemAudioSupported(boolean on) {
if (mHdmiTvClient == null) {
Log.w(TAG, "Only Hdmi-Cec enabled TV device supports system audio mode.");
return AudioSystem.DEVICE_NONE;
}
- if (on && !checkHdmiSystemAudioOutput(device)) {
- return AudioSystem.DEVICE_NONE;
- }
-
synchronized (mHdmiTvClient) {
- if (on) {
- mHdmiSystemAudioOutputDevice = device;
- }
if (mHdmiSystemAudioSupported == on) {
return AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
}
mHdmiSystemAudioSupported = on;
- updateHdmiSystemAudioVolumeLocked(on);
+ AudioSystem.setForceUse(AudioSystem.FOR_HDMI_SYSTEM_AUDIO,
+ on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED : AudioSystem.FORCE_NONE);
}
return AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
}
- private boolean checkHdmiSystemAudioOutput(int device) {
- if ((device & AudioSystem.DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO) == 0) {
- Log.w(TAG, "Unsupported Hdmi-Cec system audio output:" + device);
- return false;
- }
-
- int streamDevice = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
- // If other devices except for system audio and speaker are available,
- // fails to start system audio mode.
- if ((streamDevice & ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER) != 0) {
- Log.w(TAG, "Should turn off other devices before starting system audio:"
- + streamDevice);
- return false;
- }
- if (AudioSystem.getDeviceConnectionState(device, "") !=
- AudioSystem.DEVICE_STATE_AVAILABLE) {
- Log.w(TAG, "Output device is not connected:" + device);
- return false;
- }
- return true;
- }
-
- private void updateHdmiSystemAudioVolumeLocked(boolean on) {
- AudioDevicePort speaker = findAudioDevicePort(AudioSystem.DEVICE_OUT_SPEAKER);
- if (speaker == null) {
- Log.w(TAG, "Has no speaker output.");
- return;
- }
-
- AudioPortConfig portConfig = speaker.activeConfig();
- AudioGainConfig gainConfig = portConfig.gain();
- int[] newGains;
- // When system audio is on, backup original gains and mute all channels of speaker by
- // setting gains to 0; otherwise, restore gains of speaker.
- if (on) {
- if (gainConfig == null) {
- Log.w(TAG, "Speaker has no gain control.");
- return;
- }
- // Back up original gains.
- mSpeakerGains = Arrays.copyOf(gainConfig.values(), gainConfig.values().length);
- // Set all gains to 0.
- newGains = new int[gainConfig.values().length];
- } else {
- if (mSpeakerGains == null) {
- Log.w(TAG, "mSpeakerGains should not be null.");
- return;
- }
- newGains = Arrays.copyOf(mSpeakerGains, mSpeakerGains.length);
- }
-
- gainConfig = gainConfig.mGain.buildConfig(gainConfig.mode(),
- gainConfig.channelMask(),
- newGains,
- gainConfig.rampDurationMs());
-
- AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- if (AudioSystem.SUCCESS != audioManager.setAudioPortGain(speaker, gainConfig)) {
- Log.w(TAG, "Failed to update audio port config.");
- }
- }
-
- private AudioDevicePort findAudioDevicePort(int type) {
- ArrayList<AudioPort> devicePorts = new ArrayList<>();
- AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
- int status = audioManager.listAudioDevicePorts(devicePorts);
- if (status != AudioSystem.SUCCESS) {
- Log.w(TAG, "Failed to list up all audio ports");
- return null;
- }
-
- for (AudioPort port : devicePorts) {
- AudioDevicePort devicePort = (AudioDevicePort) port;
- if (devicePort.type() == type) {
- return devicePort;
- }
- }
- return null;
- }
-
//==========================================================================================
// Camera shutter sound policy.
// config_camera_sound_forced configuration option in config.xml defines if the camera shutter
@@ -4955,15 +4909,65 @@
}
}
mVolumeController.setController(controller);
+ if (DEBUG_VOL) Log.d(TAG, "Volume controller: " + mVolumeController);
+ }
+
+ @Override
+ public void notifyVolumeControllerVisible(final IVolumeController controller, boolean visible) {
+ enforceSelfOrSystemUI("notify about volume controller visibility");
+
+ // return early if the controller is not current
+ if (!mVolumeController.isSameBinder(controller)) {
+ return;
+ }
+
+ mVolumeController.setVisible(visible);
+ if (DEBUG_VOL) Log.d(TAG, "Volume controller visible: " + visible);
}
public static class VolumeController {
private static final String TAG = "VolumeController";
private IVolumeController mController;
+ private boolean mVisible;
+ private long mNextLongPress;
+ private int mLongPressTimeout;
public void setController(IVolumeController controller) {
mController = controller;
+ mVisible = false;
+ }
+
+ public void loadSettings(ContentResolver cr) {
+ mLongPressTimeout = Settings.Secure.getIntForUser(cr,
+ Settings.Secure.LONG_PRESS_TIMEOUT, 500, UserHandle.USER_CURRENT);
+ }
+
+ public boolean suppressAdjustment(int resolvedStream, int flags) {
+ boolean suppress = false;
+ if (resolvedStream == AudioSystem.STREAM_RING && mController != null) {
+ final long now = SystemClock.uptimeMillis();
+ if ((flags & AudioManager.FLAG_SHOW_UI) != 0 && !mVisible) {
+ // ui will become visible
+ if (mNextLongPress < now) {
+ mNextLongPress = now + mLongPressTimeout;
+ }
+ suppress = true;
+ } else if (mNextLongPress > 0) { // in a long-press
+ if (now > mNextLongPress) {
+ // long press triggered, no more suppression
+ mNextLongPress = 0;
+ } else {
+ // keep suppressing until the long press triggers
+ suppress = true;
+ }
+ }
+ }
+ return suppress;
+ }
+
+ public void setVisible(boolean visible) {
+ mVisible = visible;
}
public boolean isSameBinder(IVolumeController controller) {
@@ -4980,7 +4984,7 @@
@Override
public String toString() {
- return "VolumeController(" + asBinder() + ")";
+ return "VolumeController(" + asBinder() + ",mVisible=" + mVisible + ")";
}
public void postDisplaySafeVolumeWarning(int flags) {
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 72367c8..8e2ca95 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -254,6 +254,7 @@
public static final int DEVICE_OUT_HDMI_ARC = 0x40000;
public static final int DEVICE_OUT_SPDIF = 0x80000;
public static final int DEVICE_OUT_FM = 0x100000;
+ public static final int DEVICE_OUT_AUX_LINE = 0x200000;
public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
@@ -278,6 +279,7 @@
DEVICE_OUT_HDMI_ARC |
DEVICE_OUT_SPDIF |
DEVICE_OUT_FM |
+ DEVICE_OUT_AUX_LINE |
DEVICE_OUT_DEFAULT);
public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -287,7 +289,7 @@
DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
DEVICE_OUT_USB_DEVICE);
- public static final int DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO = (DEVICE_OUT_LINE |
+ public static final int DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO = (DEVICE_OUT_AUX_LINE |
DEVICE_OUT_HDMI_ARC |
DEVICE_OUT_SPDIF);
public static final int DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER =
@@ -440,7 +442,8 @@
public static final int FORCE_DIGITAL_DOCK = 9;
public static final int FORCE_NO_BT_A2DP = 10;
public static final int FORCE_SYSTEM_ENFORCED = 11;
- private static final int NUM_FORCE_CONFIG = 12;
+ public static final int FORCE_HDMI_SYSTEM_AUDIO_ENFORCED = 12;
+ private static final int NUM_FORCE_CONFIG = 13;
public static final int FORCE_DEFAULT = FORCE_NONE;
// usage for setForceUse, must match AudioSystem::force_use
@@ -449,7 +452,8 @@
public static final int FOR_RECORD = 2;
public static final int FOR_DOCK = 3;
public static final int FOR_SYSTEM = 4;
- private static final int NUM_FORCE_USE = 5;
+ public static final int FOR_HDMI_SYSTEM_AUDIO = 5;
+ private static final int NUM_FORCE_USE = 6;
// usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t
public static final int SYNC_EVENT_NONE = 0;
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index e112a65..7318660 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -195,11 +195,13 @@
void setVolumeController(in IVolumeController controller);
+ void notifyVolumeControllerVisible(in IVolumeController controller, boolean visible);
+
boolean isStreamAffectedByRingerMode(int streamType);
void disableSafeMediaVolume();
- int setHdmiSystemAudioSupported(boolean on, int device, String name);
+ int setHdmiSystemAudioSupported(boolean on);
boolean registerAudioPolicy(in AudioPolicyConfig policyConfig, IBinder cb);
oneway void unregisterAudioPolicyAsync(in IBinder cb);
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index 7a520fe..2f4d136 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -24,13 +24,15 @@
* <p>A class for producing sounds that match those produced by various actions
* taken by the media and camera APIs. </p>
*
- * <p>Use this class to play an appropriate camera operation sound when
- * implementing a custom still or video recording mechanism (through the Camera
- * preview callbacks with {@link android.hardware.Camera#setPreviewCallback
- * Camera.setPreviewCallback}, or through GPU processing with {@link
- * android.hardware.Camera#setPreviewTexture Camera.setPreviewTexture}, for
- * example), or when implementing some other camera-like function in your
- * application.</p>
+ * <p>This class is recommended for use with the {@link android.hardware.camera2} API, since the
+ * camera2 API does not play any sounds on its own for any capture or video recording actions.</p>
+ *
+ * <p>With the older {@link android.hardware.Camera} API, use this class to play an appropriate
+ * camera operation sound when implementing a custom still or video recording mechanism (through the
+ * Camera preview callbacks with
+ * {@link android.hardware.Camera#setPreviewCallback Camera.setPreviewCallback}, or through GPU
+ * processing with {@link android.hardware.Camera#setPreviewTexture Camera.setPreviewTexture}, for
+ * example), or when implementing some other camera-like function in your application.</p>
*
* <p>There is no need to play sounds when using
* {@link android.hardware.Camera#takePicture Camera.takePicture} or
@@ -136,10 +138,12 @@
* {@link android.media.MediaRecorder#start MediaRecorder.start}, and
* {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
*
- * <p>Using this method makes it easy to match the default device sounds
- * when recording or capturing data through the preview callbacks, or when
- * implementing custom camera-like features in your
- * application.</p>
+ * <p>With the {@link android.hardware.camera2 camera2} API, this method can be used to play
+ * standard camera operation sounds with the appropriate system behavior for such sounds.</p>
+
+ * <p>With the older {@link android.hardware.Camera} API, using this method makes it easy to
+ * match the default device sounds when recording or capturing data through the preview
+ * callbacks, or when implementing custom camera-like features in your application.</p>
*
* <p>If the sound has not been loaded by {@link #load} before calling play,
* play will load the sound at the cost of some additional latency before
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index cb9776a..f84c383 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -136,14 +136,17 @@
* cycle is necessary.
*
* <p> During its life, a codec conceptually exists in one of the following states:
- * Initialized, Configured, Executing, Uninitialized, (omitting transitory states
+ * Initialized, Configured, Executing, Error, Uninitialized, (omitting transitory states
* between them). When created by one of the factory methods,
* the codec is in the Initialized state; {@link #configure} brings it to the
* Configured state; {@link #start} brings it to the Executing state.
* In the Executing state, decoding or encoding occurs through the buffer queue
* manipulation described above. The method {@link #stop}
* returns the codec to the Initialized state, whereupon it may be configured again,
- * and {@link #release} brings the codec to the terminal Uninitialized state.
+ * and {@link #release} brings the codec to the terminal Uninitialized state. When
+ * a codec error occurs, the codec moves to the Error state. Use {@link #reset} to
+ * bring the codec back to the Initialized state, or {@link #release} to move it
+ * to the Uninitialized state.
*
* <p> The factory methods
* {@link #createByCodecName},
@@ -170,7 +173,8 @@
* then resources are temporarily unavailable and the method may be retried at a later time.
* If both {@link MediaCodec.CodecException#isRecoverable}
* and {@link MediaCodec.CodecException#isTransient} return false,
- * then the {@link MediaCodec.CodecException} is fatal and the codec must be released.
+ * then the {@link MediaCodec.CodecException} is fatal and the codec must be
+ * {@link #reset reset} or {@link #release released}.
* Both {@link MediaCodec.CodecException#isRecoverable} and
* {@link MediaCodec.CodecException#isTransient} do not return true at the same time.
*/
@@ -429,6 +433,23 @@
}
/**
+ * Returns the codec to its initial (Initialized) state.
+ *
+ * Call this if an {@link MediaCodec.CodecException#isRecoverable unrecoverable}
+ * error has occured to reset the codec to its initial state after creation.
+ *
+ * @throws CodecException if an unrecoverable error has occured and the codec
+ * could not be reset.
+ * @throws IllegalStateException if in the Uninitialized state.
+ */
+ public final void reset() {
+ freeAllTrackedBuffers(); // free buffers first
+ native_reset();
+ }
+
+ private native final void native_reset();
+
+ /**
* Make sure you call this when you're done to free up any opened
* component instance instead of relying on the garbage collector
* to do this for you at some point in the future.
@@ -646,9 +667,10 @@
/**
* After filling a range of the input buffer at the specified index
* submit it to the component. Once an input buffer is queued to
- * the codec, it MUST not be used until it is later retrieved by
- * {#getInputBuffer} in response to a {#dequeueInputBuffer}
- * response.
+ * the codec, it MUST NOT be used until it is later retrieved by
+ * {@link #getInputBuffer} in response to a {@link #dequeueInputBuffer}
+ * return value or a {@link Callback#onInputBufferAvailable}
+ * callback.
* <p>
* Many decoders require the actual compressed data stream to be
* preceded by "codec specific data", i.e. setup data used to initialize
@@ -905,9 +927,10 @@
* the codec. If you previously specified a surface when configuring this
* video decoder you can optionally render the buffer.
*
- * Once an output buffer is released to the codec, it MUST not
- * be used until it is later retrieved by {#getOutputBuffer} in
- * response to a {#dequeueOutputBuffer} response
+ * Once an output buffer is released to the codec, it MUST NOT
+ * be used until it is later retrieved by {@link #getOutputBuffer} in response
+ * to a {@link #dequeueOutputBuffer} return value or a
+ * {@link Callback#onOutputBufferAvailable} callback.
*
* @param index The index of a client-owned output buffer previously returned
* from a call to {@link #dequeueOutputBuffer}.
@@ -961,9 +984,10 @@
* </td></tr>
* </table>
*
- * Once an output buffer is released to the codec, it MUST not
- * be used until it is later retrieved by {#getOutputBuffer} in
- * response to a {#dequeueOutputBuffer} response
+ * Once an output buffer is released to the codec, it MUST NOT
+ * be used until it is later retrieved by {@link #getOutputBuffer} in response
+ * to a {@link #dequeueOutputBuffer} return value or a
+ * {@link Callback#onOutputBufferAvailable} callback.
*
* @param index The index of a client-owned output buffer previously returned
* from a call to {@link #dequeueOutputBuffer}.
@@ -1157,6 +1181,9 @@
* @deprecated Use the new {@link #getInputBuffer} method instead
* each time an input buffer is dequeued.
*
+ * <b>Note:</b>As of API 21, dequeued input buffers are
+ * automatically {@link java.nio.Buffer#clear cleared}.
+ *
* @throws IllegalStateException if not in the Executing state.
* @throws MediaCodec.CodecException upon codec error.
*/
@@ -1180,6 +1207,10 @@
* each time an output buffer is dequeued. This method is not
* supported if codec is configured in asynchronous mode.
*
+ * <b>Note:</b>As of API 21, the position and limit of output
+ * buffers that are dequeued will be set to the valid data
+ * range.
+ *
* @throws IllegalStateException if not in the Executing state,
* or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
@@ -1213,8 +1244,8 @@
}
/**
- * Returns a cleared, writable ByteBuffer object for a dequeued
- * input buffer index to contain the input data.
+ * Returns a {@link java.nio.Buffer#clear cleared}, writable ByteBuffer
+ * object for a dequeued input buffer index to contain the input data.
*
* After calling this method any ByteBuffer or Image object
* previously returned for the same input index MUST no longer
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index f2753ee..b23b540 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -297,8 +297,12 @@
/**
* Retrieve the current encoded sample and store it in the byte buffer
- * starting at the given offset. Returns the sample size (or -1 if
- * no more samples are available).
+ * starting at the given offset.
+ * <p>
+ * <b>Note:</b>As of API 21, on success the position and limit of
+ * {@code byteBuf} is updated to point to the data just read.
+ * @param byteBuf the destination byte buffer
+ * @return the sample size (or -1 if no more samples are available).
*/
public native int readSampleData(ByteBuffer byteBuf, int offset);
@@ -316,7 +320,10 @@
// Keep these in sync with their equivalents in NuMediaExtractor.h
/**
- * The sample is a sync sample
+ * The sample is a sync sample (or in {@link MediaCodec}'s terminology
+ * it is a key frame.)
+ *
+ * @see MediaCodec#BUFFER_FLAG_KEY_FRAME
*/
public static final int SAMPLE_FLAG_SYNC = 1;
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index ab65ba0..b15bd69 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -378,6 +378,13 @@
* <td>Successful invoke of this method in a valid state does not change
* the state. Calling this method in an invalid state transfers the
* object to the <em>Error</em> state. </p></td></tr>
+ * <tr><td>setAudioAttributes </p></td>
+ * <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
+ * PlaybackCompleted}</p></td>
+ * <td>{Error}</p></td>
+ * <td>Successful invoke of this method does not change the state. In order for the
+ * target audio attributes type to become effective, this method must be called before
+ * prepare() or prepareAsync().</p></td></tr>
* <tr><td>setAudioSessionId </p></td>
* <td>{Idle} </p></td>
* <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted,
@@ -787,6 +794,10 @@
* <p>When done with the MediaPlayer, you should call {@link #release()},
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
+ * <p>Note that since {@link #prepare()} is called automatically in this method,
+ * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * session ID (see {@link #setAudioSessionId(int)}) or audio attributes
+ * (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
* @param context the Context to use
* @param uri the Uri from which to get the datasource
@@ -802,6 +813,10 @@
* <p>When done with the MediaPlayer, you should call {@link #release()},
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
+ * <p>Note that since {@link #prepare()} is called automatically in this method,
+ * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * session ID (see {@link #setAudioSessionId(int)}) or audio attributes
+ * (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
* @param context the Context to use
* @param uri the Uri from which to get the datasource
@@ -809,9 +824,30 @@
* @return a MediaPlayer object, or null if creation failed
*/
public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder) {
+ int s = AudioSystem.newAudioSessionId();
+ return create(context, uri, holder, null, s > 0 ? s : 0);
+ }
+
+ /**
+ * Same factory method as {@link #create(Context, Uri, SurfaceHolder)} but that lets you specify
+ * the audio attributes and session ID to be used by the new MediaPlayer instance.
+ * @param context the Context to use
+ * @param uri the Uri from which to get the datasource
+ * @param holder the SurfaceHolder to use for displaying the video, may be null.
+ * @param audioAttributes the {@link AudioAttributes} to be used by the media player.
+ * @param audioSessionId the audio session ID to be used by the media player,
+ * see {@link AudioManager#allocateAudioSessionId()} to obtain a new session.
+ * @return a MediaPlayer object, or null if creation failed
+ */
+ public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder,
+ AudioAttributes audioAttributes, int audioSessionId) {
try {
MediaPlayer mp = new MediaPlayer();
+ final AudioAttributes aa = audioAttributes != null ? audioAttributes :
+ new AudioAttributes.Builder().build();
+ mp.setAudioAttributes(aa);
+ mp.setAudioSessionId(audioSessionId);
mp.setDataSource(context, uri);
if (holder != null) {
mp.setDisplay(holder);
@@ -840,6 +876,10 @@
* <p>When done with the MediaPlayer, you should call {@link #release()},
* to free the resources. If not released, too many MediaPlayer instances will
* result in an exception.</p>
+ * <p>Note that since {@link #prepare()} is called automatically in this method,
+ * you cannot change the audio stream type (see {@link #setAudioStreamType(int)}), audio
+ * session ID (see {@link #setAudioSessionId(int)}) or audio attributes
+ * (see {@link #setAudioAttributes(AudioAttributes)} of the new MediaPlayer.</p>
*
* @param context the Context to use
* @param resid the raw resource id (<var>R.raw.<something></var>) for
@@ -847,11 +887,34 @@
* @return a MediaPlayer object, or null if creation failed
*/
public static MediaPlayer create(Context context, int resid) {
+ int s = AudioSystem.newAudioSessionId();
+ return create(context, resid, null, s > 0 ? s : 0);
+ }
+
+ /**
+ * Same factory method as {@link #create(Context, int)} but that lets you specify the audio
+ * attributes and session ID to be used by the new MediaPlayer instance.
+ * @param context the Context to use
+ * @param resid the raw resource id (<var>R.raw.<something></var>) for
+ * the resource to use as the datasource
+ * @param audioAttributes the {@link AudioAttributes} to be used by the media player.
+ * @param audioSessionId the audio session ID to be used by the media player,
+ * see {@link AudioManager#allocateAudioSessionId()} to obtain a new session.
+ * @return a MediaPlayer object, or null if creation failed
+ */
+ public static MediaPlayer create(Context context, int resid,
+ AudioAttributes audioAttributes, int audioSessionId) {
try {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
if (afd == null) return null;
MediaPlayer mp = new MediaPlayer();
+
+ final AudioAttributes aa = audioAttributes != null ? audioAttributes :
+ new AudioAttributes.Builder().build();
+ mp.setAudioAttributes(aa);
+ mp.setAudioSessionId(audioSessionId);
+
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
mp.prepare();
@@ -1454,16 +1517,15 @@
private native boolean setParameter(int key, Parcel value);
/**
- * @hide
- * CANDIDATE FOR PUBLIC API
- * Must call this method before prepare() or
- * prepareAsync() in order for the audio attributes to become effective
- * thereafter.
+ * Sets the audio attributes for this MediaPlayer.
+ * See {@link AudioAttributes} for how to build and configure an instance of this class.
+ * You must call this method before {@link #prepare()} or {@link #prepareAsync()} in order
+ * for the audio attributes to become effective thereafter.
* @param attributes a non-null set of audio attributes
*/
public void setAudioAttributes(AudioAttributes attributes) throws IllegalArgumentException {
if (attributes == null) {
- final String msg = "Cannot set audio attributes to null";
+ final String msg = "Cannot set AudioAttributes to null";
throw new IllegalArgumentException(msg);
}
Parcel pattributes = Parcel.obtain();
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index f8c0494..59307d0 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -114,23 +114,26 @@
}
/**
- * Sets a Camera to use for recording. Use this function to switch
- * quickly between preview and capture mode without a teardown of
- * the camera object. {@link android.hardware.Camera#unlock()} should be
- * called before this. Must call before prepare().
+ * Sets a {@link android.hardware.Camera} to use for recording.
+ *
+ * <p>Use this function to switch quickly between preview and capture mode without a teardown of
+ * the camera object. {@link android.hardware.Camera#unlock()} should be called before
+ * this. Must call before {@link #prepare}.</p>
*
* @param c the Camera to use for recording
+ * @deprecated Use {@link #getSurface} and the {@link android.hardware.camera2} API instead.
*/
+ @Deprecated
public native void setCamera(Camera c);
/**
* Gets the surface to record from when using SURFACE video source.
- * <p>
- * Should only be called after prepare(). Frames rendered before start()
- * will be discarded.
- * </p>
- * @throws IllegalStateException if it is called before prepare(), after
- * stop() or is called when VideoSource is not set to SURFACE.
+ *
+ * <p> May only be called after {@link #prepare}. Frames rendered to the Surface before
+ * {@link #start} will be discarded.</p>
+ *
+ * @throws IllegalStateException if it is called before {@link #prepare}, after
+ * {@link #stop}, or is called when VideoSource is not set to SURFACE.
* @see android.media.MediaRecorder.VideoSource
*/
public native Surface getSurface();
@@ -239,7 +242,7 @@
public static final int DEFAULT = 0;
/** Camera video source
* <p>
- * Using android.hardware.Camera as video source.
+ * Using the {@link android.hardware.Camera} API as video source.
* </p>
*/
public static final int CAMERA = 1;
@@ -248,7 +251,7 @@
* Using a Surface as video source.
* </p><p>
* This flag must be used when recording from an
- * android.hardware.camera2.CameraDevice source.
+ * {@link android.hardware.camera2} API source.
* </p><p>
* When using this video source type, use {@link MediaRecorder#getSurface()}
* to retrieve the surface created by MediaRecorder.
@@ -296,6 +299,9 @@
/** @hide H.264/AAC data encapsulated in MPEG2/TS */
public static final int OUTPUT_FORMAT_MPEG2TS = 8;
+
+ /** VP8/VORBIS data in a WEBM container */
+ public static final int WEBM = 9;
};
/**
@@ -318,6 +324,8 @@
public static final int HE_AAC = 4;
/** Enhanced Low Delay AAC (AAC-ELD) audio codec */
public static final int AAC_ELD = 5;
+ /** Ogg Vorbis audio codec */
+ public static final int VORBIS = 6;
}
/**
@@ -333,6 +341,7 @@
public static final int H263 = 1;
public static final int H264 = 2;
public static final int MPEG_4_SP = 3;
+ public static final int VP8 = 4;
}
/**
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 3336694..7d1de24 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -2249,12 +2249,12 @@
}
@Override
- public void onAdjustVolumeBy(final int delta) {
+ public void onAdjustVolume(final int direction) {
sStatic.mHandler.post(new Runnable() {
@Override
public void run() {
if (mVcb != null) {
- mVcb.vcb.onVolumeUpdateRequest(mVcb.route, delta);
+ mVcb.vcb.onVolumeUpdateRequest(mVcb.route, direction);
}
}
});
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 73bc61a..740a9d3 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -682,9 +682,13 @@
// USE_SESSIONS
if (mSession != null) {
int pbState = PlaybackState.getStateFromRccState(state);
- mSessionPlaybackState.setState(pbState, hasPosition ?
- mPlaybackPositionMs : PlaybackState.PLAYBACK_POSITION_UNKNOWN,
- playbackSpeed);
+ long position = hasPosition ? mPlaybackPositionMs
+ : PlaybackState.PLAYBACK_POSITION_UNKNOWN;
+
+ PlaybackState.Builder bob = new PlaybackState.Builder(mSessionPlaybackState);
+ bob.setState(pbState, position, playbackSpeed, SystemClock.elapsedRealtime());
+ bob.setErrorMessage(null);
+ mSessionPlaybackState = bob.build();
mSession.setPlaybackState(mSessionPlaybackState);
}
}
@@ -745,8 +749,9 @@
// USE_SESSIONS
if (mSession != null) {
- mSessionPlaybackState.setActions(PlaybackState
- .getActionsFromRccControlFlags(transportControlFlags));
+ PlaybackState.Builder bob = new PlaybackState.Builder(mSessionPlaybackState);
+ bob.setActions(PlaybackState.getActionsFromRccControlFlags(transportControlFlags));
+ mSessionPlaybackState = bob.build();
mSession.setPlaybackState(mSessionPlaybackState);
}
}
@@ -946,7 +951,7 @@
/**
* Cache for the current playback state using Session APIs.
*/
- private final PlaybackState mSessionPlaybackState = new PlaybackState();
+ private PlaybackState mSessionPlaybackState = null;
/**
* Cache for metadata using Session APIs. This is re-initialized in apply().
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 1f5b216..9ea3f26 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -1020,7 +1020,7 @@
l.onClientPlaybackStateUpdate(playstate);
} else {
l.onClientPlaybackStateUpdate(playstate, state.getLastPositionUpdateTime(),
- state.getPosition(), state.getPlaybackRate());
+ state.getPosition(), state.getPlaybackSpeed());
}
if (state != null) {
l.onClientTransportControlUpdate(PlaybackState.getRccControlFlagsFromActions(state
diff --git a/media/java/android/media/VolumeProvider.java b/media/java/android/media/VolumeProvider.java
index d151e66..9bda1d4 100644
--- a/media/java/android/media/VolumeProvider.java
+++ b/media/java/android/media/VolumeProvider.java
@@ -32,14 +32,14 @@
/**
* The volume control uses relative adjustment via
- * {@link #onAdjustVolumeBy(int)}. Attempts to set the volume to a specific
+ * {@link #onAdjustVolume(int)}. Attempts to set the volume to a specific
* value should be ignored.
*/
public static final int VOLUME_CONTROL_RELATIVE = 1;
/**
* The volume control uses an absolute value. It may be adjusted using
- * {@link #onAdjustVolumeBy(int)} or set directly using
+ * {@link #onAdjustVolume(int)} or set directly using
* {@link #onSetVolumeTo(int)}.
*/
public static final int VOLUME_CONTROL_ABSOLUTE = 2;
@@ -104,12 +104,13 @@
}
/**
- * Override to handle requests to adjust the volume of the current
- * output.
- *
- * @param delta The amount to change the volume
+ * Override to handle requests to adjust the volume of the current output.
+ * Direction will be one of {@link AudioManager#ADJUST_LOWER},
+ * {@link AudioManager#ADJUST_RAISE}, {@link AudioManager#ADJUST_SAME}.
+ *
+ * @param direction The direction to change the volume in.
*/
- public void onAdjustVolumeBy(int delta) {
+ public void onAdjustVolume(int direction) {
}
/**
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 9b381cc..9fa3f50 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -1282,7 +1282,7 @@
/**
* @hide
*/
- public int byteArrayToInt(byte[] valueBuf) {
+ public static int byteArrayToInt(byte[] valueBuf) {
return byteArrayToInt(valueBuf, 0);
}
@@ -1290,7 +1290,7 @@
/**
* @hide
*/
- public int byteArrayToInt(byte[] valueBuf, int offset) {
+ public static int byteArrayToInt(byte[] valueBuf, int offset) {
ByteBuffer converter = ByteBuffer.wrap(valueBuf);
converter.order(ByteOrder.nativeOrder());
return converter.getInt(offset);
@@ -1300,7 +1300,7 @@
/**
* @hide
*/
- public byte[] intToByteArray(int value) {
+ public static byte[] intToByteArray(int value) {
ByteBuffer converter = ByteBuffer.allocate(4);
converter.order(ByteOrder.nativeOrder());
converter.putInt(value);
@@ -1310,14 +1310,14 @@
/**
* @hide
*/
- public short byteArrayToShort(byte[] valueBuf) {
+ public static short byteArrayToShort(byte[] valueBuf) {
return byteArrayToShort(valueBuf, 0);
}
/**
* @hide
*/
- public short byteArrayToShort(byte[] valueBuf, int offset) {
+ public static short byteArrayToShort(byte[] valueBuf, int offset) {
ByteBuffer converter = ByteBuffer.wrap(valueBuf);
converter.order(ByteOrder.nativeOrder());
return converter.getShort(offset);
@@ -1327,7 +1327,7 @@
/**
* @hide
*/
- public byte[] shortToByteArray(short value) {
+ public static byte[] shortToByteArray(short value) {
ByteBuffer converter = ByteBuffer.allocate(2);
converter.order(ByteOrder.nativeOrder());
short sValue = (short) value;
@@ -1338,7 +1338,7 @@
/**
* @hide
*/
- public byte[] concatArrays(byte[]... arrays) {
+ public static byte[] concatArrays(byte[]... arrays) {
int len = 0;
for (byte[] a : arrays) {
len += a.length;
diff --git a/media/java/android/media/audiofx/Virtualizer.java b/media/java/android/media/audiofx/Virtualizer.java
index 6b20006..136761b 100644
--- a/media/java/android/media/audiofx/Virtualizer.java
+++ b/media/java/android/media/audiofx/Virtualizer.java
@@ -16,9 +16,13 @@
package android.media.audiofx;
+import android.media.AudioDevice;
+import android.media.AudioFormat;
import android.media.audiofx.AudioEffect;
import android.util.Log;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.util.StringTokenizer;
@@ -44,8 +48,10 @@
public class Virtualizer extends AudioEffect {
private final static String TAG = "Virtualizer";
+ private final static boolean DEBUG = false;
- // These constants must be synchronized with those in frameworks/base/include/media/EffectVirtualizerApi.h
+ // These constants must be synchronized with those in
+ // system/media/audio_effects/include/audio_effects/effect_virtualizer.h
/**
* Is strength parameter supported by virtualizer engine. Parameter ID for getParameter().
*/
@@ -55,6 +61,21 @@
* {@link android.media.audiofx.Virtualizer.OnParameterChangeListener}
*/
public static final int PARAM_STRENGTH = 1;
+ /**
+ * @hide
+ * Parameter ID to query the virtual speaker angles for a channel mask / device configuration.
+ */
+ public static final int PARAM_VIRTUAL_SPEAKER_ANGLES = 2;
+ /**
+ * @hide
+ * Parameter ID to force the virtualization mode to be that of a specific device
+ */
+ public static final int PARAM_FORCE_VIRTUALIZATION_MODE = 3;
+ /**
+ * @hide
+ * Parameter ID to query the current virtualization mode.
+ */
+ public static final int PARAM_VIRTUALIZATION_MODE = 4;
/**
* Indicates if strength parameter is supported by the virtualizer engine
@@ -145,6 +166,223 @@
}
/**
+ * Checks if a configuration is supported, and query the virtual speaker angles.
+ * @param inputChannelMask
+ * @param deviceType
+ * @param angles if non-null: array in which the angles will be written. If null, no angles
+ * are returned
+ * @return true if the combination of channel mask and output device type is supported, false
+ * otherwise
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ * @throws UnsupportedOperationException
+ */
+ private boolean getAnglesInt(int inputChannelMask, int deviceType, int[] angles)
+ throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
+ // parameter check
+ if (inputChannelMask == AudioFormat.CHANNEL_INVALID) {
+ throw (new IllegalArgumentException(
+ "Virtualizer: illegal CHANNEL_INVALID channel mask"));
+ }
+ int channelMask = inputChannelMask == AudioFormat.CHANNEL_OUT_DEFAULT ?
+ AudioFormat.CHANNEL_OUT_STEREO : inputChannelMask;
+ int nbChannels = AudioFormat.channelCountFromOutChannelMask(channelMask);
+ if ((angles != null) && (angles.length < (nbChannels * 3))) {
+ Log.e(TAG, "Size of array for angles cannot accomodate number of channels in mask ("
+ + nbChannels + ")");
+ throw (new IllegalArgumentException(
+ "Virtualizer: array for channel / angle pairs is too small: is " + angles.length
+ + ", should be " + (nbChannels * 3)));
+ }
+
+ ByteBuffer paramsConverter = ByteBuffer.allocate(3 /* param + mask + device*/ * 4);
+ paramsConverter.order(ByteOrder.nativeOrder());
+ paramsConverter.putInt(PARAM_VIRTUAL_SPEAKER_ANGLES);
+ // convert channel mask to internal native representation
+ paramsConverter.putInt(AudioFormat.convertChannelOutMaskToNativeMask(channelMask));
+ // convert Java device type to internal representation
+ paramsConverter.putInt(AudioDevice.convertDeviceTypeToInternalDevice(deviceType));
+ // allocate an array to store the results
+ byte[] result = new byte[nbChannels * 4/*int to byte*/ * 3/*for mask, azimuth, elevation*/];
+
+ // call into the effect framework
+ int status = getParameter(paramsConverter.array(), result);
+ if (DEBUG) {
+ Log.v(TAG, "getAngles(0x" + Integer.toHexString(inputChannelMask) + ", 0x"
+ + Integer.toHexString(deviceType) + ") returns " + status);
+ }
+
+ if (status >= 0) {
+ if (angles != null) {
+ // convert and copy the results
+ ByteBuffer resultConverter = ByteBuffer.wrap(result);
+ resultConverter.order(ByteOrder.nativeOrder());
+ for (int i = 0 ; i < nbChannels ; i++) {
+ // write the channel mask
+ angles[3 * i] = AudioFormat.convertNativeChannelMaskToOutMask(
+ resultConverter.getInt((i * 4 * 3)));
+ // write the azimuth
+ angles[3 * i + 1] = resultConverter.getInt(i * 4 * 3 + 4);
+ // write the elevation
+ angles[3 * i + 2] = resultConverter.getInt(i * 4 * 3 + 8);
+ if (DEBUG) {
+ Log.v(TAG, "channel 0x" + Integer.toHexString(angles[3*i]).toUpperCase()
+ + " at az=" + angles[3*i+1] + "deg"
+ + " elev=" + angles[3*i+2] + "deg");
+ }
+ }
+ }
+ return true;
+ } else if (status == AudioEffect.ERROR_BAD_VALUE) {
+ // a BAD_VALUE return from getParameter indicates the configuration is not supported
+ // don't throw an exception, just return false
+ return false;
+ } else {
+ // something wrong may have happened
+ checkStatus(status);
+ }
+ // unexpected virtualizer behavior
+ Log.e(TAG, "unexpected status code " + status
+ + " after getParameter(PARAM_VIRTUAL_SPEAKER_ANGLES)");
+ return false;
+ }
+
+ /**
+ * @hide
+ * CANDIDATE FOR PUBLIC API
+ * Checks if the combination of a channel mask and device type is supported by this virtualizer.
+ * Some virtualizer implementations may only support binaural processing (i.e. only support
+ * headphone output), some may support transaural processing (i.e. for speaker output) for the
+ * built-in speakers. Use this method to query the virtualizer implementation capabilities.
+ * @param inputChannelMask the channel mask of the content to virtualize.
+ * @param deviceType the device type for which virtualization processing is to be performed.
+ * Valid values are the device types defined in {@link AudioDevice}.
+ * @return true if the combination of channel mask and output device type is supported, false
+ * otherwise.
+ * <br>An indication that a certain channel mask is not supported doesn't necessarily mean
+ * you cannot play content with that channel mask, it more likely implies the content will
+ * be downmixed before being virtualized. For instance a virtualizer that only supports a
+ * mask such as {@link AudioFormat#CHANNEL_OUT_STEREO}
+ * will still be able to process content with a mask of
+ * {@link AudioFormat#CHANNEL_OUT_5POINT1}, but will downmix the content to stereo first, and
+ * then will virtualize, as opposed to virtualizing each channel individually.
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ * @throws UnsupportedOperationException
+ */
+ public boolean canVirtualize(int inputChannelMask, int deviceType)
+ throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
+ return getAnglesInt(inputChannelMask, deviceType, null);
+ }
+
+ /**
+ * @hide
+ * CANDIDATE FOR PUBLIC API
+ * Queries the virtual speaker angles (azimuth and elevation) for a combination of a channel
+ * mask and device type.
+ * If the virtualization configuration (mask and device) is supported (see
+ * {@link #canVirtualize(int, int)}, the array angles will contain upon return the
+ * definition of each virtual speaker and its azimuth and elevation angles relative to the
+ * listener.
+ * <br>Note that in some virtualizer implementations, the angles may be strength-dependent.
+ * @param inputChannelMask the channel mask of the content to virtualize.
+ * @param deviceType the device type for which virtualization processing is to be performed.
+ * Valid values are the device types defined in {@link AudioDevice}.
+ * @param angles a non-null array whose length is 3 times the number of channels in the channel
+ * mask.
+ * If the method indicates the configuration is supported, the array will contain upon return
+ * triplets of values: for each channel <code>i</code> among the channels of the mask:
+ * <ul>
+ * <li>the element at index <code>3*i</code> in the array contains the speaker
+ * identification (e.g. {@link AudioFormat#CHANNEL_OUT_FRONT_LEFT}),</li>
+ * <li>the element at index <code>3*i+1</code> contains its corresponding azimuth angle
+ * expressed in degrees, where 0 is the direction the listener faces, 180 is behind
+ * the listener, and -90 is to her/his left,</li>
+ * <li>the element at index <code>3*i+2</code> contains its corresponding elevation angle
+ * where +90 is directly above the listener, 0 is the horizontal plane, and -90 is
+ * directly below the listener.</li>
+ * @return true if the combination of channel mask and output device type is supported, false
+ * otherwise.
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ * @throws UnsupportedOperationException
+ */
+ public boolean getSpeakerAngles(int inputChannelMask, int deviceType, int[] angles)
+ throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
+ if (angles == null) {
+ throw (new IllegalArgumentException(
+ "Virtualizer: illegal null channel / angle array"));
+ }
+
+ return getAnglesInt(inputChannelMask, deviceType, angles);
+ }
+
+ /**
+ * @hide
+ * CANDIDATE FOR PUBLIC API
+ * Forces the virtualizer effect to use the processing mode used for the given device type.
+ * The effect must be enabled for the forced mode to be applied.
+ * @param deviceType one of the device types defined in {@link AudioDevice}.
+ * Use {@link AudioDevice#DEVICE_TYPE_UNKNOWN} to return to the non-forced mode.
+ * @return true if the processing mode for the device type is supported, and it is successfully
+ * set, or forcing was successfully disabled with {@link AudioDevice#DEVICE_TYPE_UNKNOWN},
+ * false otherwise.
+ * @throws IllegalStateException
+ * @throws IllegalArgumentException
+ * @throws UnsupportedOperationException
+ */
+ public boolean forceVirtualizationMode(int deviceType)
+ throws IllegalStateException, IllegalArgumentException, UnsupportedOperationException {
+ // convert Java device type to internal representation
+ int internalDevice = AudioDevice.convertDeviceTypeToInternalDevice(deviceType);
+
+ int status = setParameter(PARAM_FORCE_VIRTUALIZATION_MODE, internalDevice);
+
+ if (status >= 0) {
+ return true;
+ } else if (status == AudioEffect.ERROR_BAD_VALUE) {
+ // a BAD_VALUE return from setParameter indicates the mode can't be forced to that
+ // of this device, don't throw an exception, just return false
+ return false;
+ } else {
+ // something wrong may have happened
+ checkStatus(status);
+ }
+ // unexpected virtualizer behavior
+ Log.e(TAG, "unexpected status code " + status
+ + " after setParameter(PARAM_FORCE_VIRTUALIZATION_MODE)");
+ return false;
+ }
+
+ /**
+ * @hide
+ * CANDIDATE FOR PUBLIC API
+ * Return the device type which reflects the virtualization mode being used, if any.
+ * @return a device type (as defined in {@link AudioDevice}) which reflects the virtualization
+ * mode being used.
+ * If virtualization is not active, the device type will be
+ * {@link AudioDevice#DEVICE_TYPE_UNKNOWN}. Virtualization may not be active either because
+ * the effect is not enabled or because the current output device is not compatible with
+ * this virtualization implementation.
+ */
+ public int getVirtualizationMode() {
+ int[] value = new int[1];
+ int status = getParameter(PARAM_VIRTUALIZATION_MODE, value);
+ if (status >= 0) {
+ return AudioDevice.convertInternalDeviceToDeviceType(value[0]);
+ } else if (status == AudioEffect.ERROR_BAD_VALUE) {
+ return AudioDevice.DEVICE_TYPE_UNKNOWN;
+ } else {
+ // something wrong may have happened
+ checkStatus(status);
+ }
+ // unexpected virtualizer behavior
+ Log.e(TAG, "unexpected status code " + status
+ + " after getParameter(PARAM_VIRTUALIZATION_MODE)");
+ return AudioDevice.DEVICE_TYPE_UNKNOWN;
+ }
+
+ /**
* The OnParameterChangeListener interface defines a method called by the Virtualizer when a
* parameter value has changed.
*/
diff --git a/media/java/android/media/routeprovider/IRouteConnection.aidl b/media/java/android/media/routeprovider/IRouteConnection.aidl
deleted file mode 100644
index 15c8039..0000000
--- a/media/java/android/media/routeprovider/IRouteConnection.aidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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.
- */
-
-package android.media.routeprovider;
-
-import android.media.session.RouteCommand;
-import android.os.ResultReceiver;
-
-/**
- * Interface for a specific connected route.
- * @hide
- */
-oneway interface IRouteConnection {
- void onCommand(in RouteCommand command, in ResultReceiver cb);
- void disconnect();
-}
\ No newline at end of file
diff --git a/media/java/android/media/routeprovider/IRouteProvider.aidl b/media/java/android/media/routeprovider/IRouteProvider.aidl
deleted file mode 100644
index c36f6a7..0000000
--- a/media/java/android/media/routeprovider/IRouteProvider.aidl
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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.
- */
-
-package android.media.routeprovider;
-
-import android.media.routeprovider.IRouteConnection;
-import android.media.routeprovider.IRouteProviderCallback;
-import android.media.routeprovider.RouteRequest;
-import android.media.session.RouteInfo;
-import android.os.Bundle;
-import android.os.ResultReceiver;
-
-/**
- * Interface to an app's RouteProviderService.
- * @hide
- */
-oneway interface IRouteProvider {
- void registerCallback(in IRouteProviderCallback cb);
- void unregisterCallback(in IRouteProviderCallback cb);
- void updateDiscoveryRequests(in List<RouteRequest> requests);
-
- void getAvailableRoutes(in List<RouteRequest> requests, in ResultReceiver cb);
- void connect(in RouteInfo route, in RouteRequest request, in ResultReceiver cb);
-}
\ No newline at end of file
diff --git a/media/java/android/media/routeprovider/IRouteProviderCallback.aidl b/media/java/android/media/routeprovider/IRouteProviderCallback.aidl
deleted file mode 100644
index 9185347..0000000
--- a/media/java/android/media/routeprovider/IRouteProviderCallback.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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.
- */
-
-package android.media.routeprovider;
-
-import android.media.routeprovider.IRouteConnection;
-import android.media.session.RouteEvent;
-import android.os.Bundle;
-import android.os.ResultReceiver;
-
-/**
- * System's provider callback interface.
- * @hide
- */
-oneway interface IRouteProviderCallback {
- void onRoutesChanged();
- void onConnectionStateChanged(in IRouteConnection connection, int state);
- void onConnectionTerminated(in IRouteConnection connection);
- void onRouteEvent(in RouteEvent event);
-}
\ No newline at end of file
diff --git a/media/java/android/media/routeprovider/RouteConnection.java b/media/java/android/media/routeprovider/RouteConnection.java
deleted file mode 100644
index 43692c1..0000000
--- a/media/java/android/media/routeprovider/RouteConnection.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.
- */
-package android.media.routeprovider;
-
-import android.media.routeprovider.IRouteConnection;
-import android.media.session.RouteCommand;
-import android.media.session.RouteEvent;
-import android.media.session.RouteInfo;
-import android.media.session.RouteInterface;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Represents an ongoing connection between an application and a media route
- * offered by a media route provider.
- * <p>
- * The media route provider should add interfaces to the connection before
- * returning it to the system in order to receive commands from clients on those
- * interfaces. Use {@link #addRouteInterface(String)} to add an interface and
- * {@link #getRouteInterface(String)} to retrieve the interface's handle anytime
- * after it has been added.
- * @hide
- */
-public final class RouteConnection {
- private static final String TAG = "RouteConnection";
- private final ConnectionStub mBinder;
- private final ArrayList<String> mIfaceNames = new ArrayList<String>();
- private final ArrayMap<String, RouteInterfaceHandler> mIfaces
- = new ArrayMap<String, RouteInterfaceHandler>();
- private final RouteProviderService mProvider;
- private final RouteInfo mRoute;
-
- private boolean mPublished;
-
- /**
- * Create a new connection for the given Provider and Route.
- *
- * @param provider The provider this route is associated with.
- * @param route The route this is a connection to.
- */
- public RouteConnection(RouteProviderService provider, RouteInfo route) {
- if (provider == null) {
- throw new IllegalArgumentException("provider may not be null.");
- }
- if (route == null) {
- throw new IllegalArgumentException("route may not be null.");
- }
- mBinder = new ConnectionStub(this);
- mProvider = provider;
- mRoute = route;
- }
-
- /**
- * Add an interface to this route connection. All interfaces must be added
- * to the connection before the connection is returned to the system.
- *
- * @param ifaceName The name of the interface to add
- * @return The route interface that was registered
- */
- public RouteInterfaceHandler addRouteInterface(String ifaceName) {
- if (TextUtils.isEmpty(ifaceName)) {
- throw new IllegalArgumentException("The interface's name may not be empty");
- }
- if (mPublished) {
- throw new IllegalStateException(
- "Connection has already been published to the system.");
- }
- RouteInterfaceHandler iface = mIfaces.get(ifaceName);
- if (iface == null) {
- iface = new RouteInterfaceHandler(this, ifaceName);
- mIfaceNames.add(ifaceName);
- mIfaces.put(ifaceName, iface);
- } else {
- Log.w(TAG, "Attempted to add an interface that already exists");
- }
- return iface;
- }
-
- /**
- * Get the interface instance for the specified interface name. If the
- * interface was not added to this connection null will be returned.
- *
- * @param ifaceName The name of the interface to get.
- * @return The route interface with that name or null.
- */
- public RouteInterfaceHandler getRouteInterface(String ifaceName) {
- return mIfaces.get(ifaceName);
- }
-
- /**
- * Close the connection and inform the system that it may no longer be used.
- */
- public void shutDown() {
- mProvider.disconnect(this);
- }
-
- /**
- * @hide
- */
- public void sendEvent(String iface, String event, Bundle extras) {
- RouteEvent e = new RouteEvent(mBinder, iface, event, extras);
- mProvider.sendRouteEvent(e);
- }
-
- /**
- * @hide
- */
- IRouteConnection.Stub getBinder() {
- return mBinder;
- }
-
- /**
- * @hide
- */
- void publish() {
- mPublished = true;
- }
-
- private static class ConnectionStub extends IRouteConnection.Stub {
- private final WeakReference<RouteConnection> mConnection;
-
- public ConnectionStub(RouteConnection connection) {
- mConnection = new WeakReference<RouteConnection>(connection);
- }
-
- @Override
- public void onCommand(RouteCommand command, ResultReceiver cb) {
- RouteConnection connection = mConnection.get();
- if (connection != null) {
- RouteInterfaceHandler iface = connection.mIfaces.get(command.getIface());
- if (iface != null) {
- iface.onCommand(command.getEvent(), command.getExtras(), cb);
- } else if (cb != null) {
- cb.send(RouteInterface.RESULT_INTERFACE_NOT_SUPPORTED, null);
- }
- }
- }
-
- @Override
- public void disconnect() {
- // TODO
- }
- }
-}
diff --git a/media/java/android/media/routeprovider/RouteInterfaceHandler.java b/media/java/android/media/routeprovider/RouteInterfaceHandler.java
deleted file mode 100644
index e7f8bbf..0000000
--- a/media/java/android/media/routeprovider/RouteInterfaceHandler.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * 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.
- */
-package android.media.routeprovider;
-
-import android.media.session.Route;
-import android.media.session.MediaSession;
-import android.media.session.RouteInterface;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.ResultReceiver;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.ArrayList;
-
-/**
- * Represents an interface that an application may use to send requests to a
- * connected media route.
- * <p>
- * A {@link RouteProviderService} may expose multiple interfaces on a
- * {@link RouteConnection} for a {@link MediaSession} to interact with. A
- * provider creates an interface with
- * {@link RouteConnection#addRouteInterface(String)} to allow messages to be
- * routed appropriately. Events are then sent through a specific interface and
- * all commands being sent on the interface will be sent to any registered
- * {@link CommandListener}s.
- * <p>
- * An interface instance can only be registered on one {@link RouteConnection}.
- * To use the same interface on multiple connections a new instance must be
- * created for each connection.
- * <p>
- * It is recommended you wrap this interface with a standard implementation to
- * avoid errors, but for simple interfaces this class may be used directly. TODO
- * add link to sample code.
- * @hide
- */
-public final class RouteInterfaceHandler {
- private static final String TAG = "RouteInterfaceHandler";
-
- private final Object mLock = new Object();
- private final RouteConnection mConnection;
- private final String mName;
-
- private ArrayList<MessageHandler> mListeners = new ArrayList<MessageHandler>();
-
- /**
- * Create a new RouteInterface for a given connection. This can be used to
- * send events on the given interface and register listeners for commands
- * from the connected session.
- *
- * @param connection The connection this interface sends events on
- * @param ifaceName The name of this interface
- * @hide
- */
- public RouteInterfaceHandler(RouteConnection connection, String ifaceName) {
- if (connection == null) {
- throw new IllegalArgumentException("connection may not be null");
- }
- if (TextUtils.isEmpty(ifaceName)) {
- throw new IllegalArgumentException("ifaceName can not be empty");
- }
- mConnection = connection;
- mName = ifaceName;
- }
-
- /**
- * Send an event on this interface to the connected session.
- *
- * @param event The event to send
- * @param extras Any extras for the event
- */
- public void sendEvent(String event, Bundle extras) {
- mConnection.sendEvent(mName, event, extras);
- }
-
- /**
- * Send a result from a command to the specified callback. The result codes
- * in {@link RouteInterface} must be used. More information
- * about the result, whether successful or an error, should be included in
- * the extras.
- *
- * @param cb The callback to send the result to
- * @param resultCode The result code for the call
- * @param extras Any extras to include
- */
- public static void sendResult(ResultReceiver cb, int resultCode, Bundle extras) {
- if (cb != null) {
- cb.send(resultCode, extras);
- }
- }
-
- /**
- * Add a listener for this interface. If a handler is specified callbacks
- * will be performed on the handler's thread, otherwise the callers thread
- * will be used.
- *
- * @param listener The listener to receive calls on.
- * @param handler The handler whose thread to post calls on or null.
- */
- public void addListener(CommandListener listener, Handler handler) {
- if (listener == null) {
- throw new IllegalArgumentException("listener may not be null");
- }
- Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
- synchronized (mLock) {
- if (findIndexOfListenerLocked(listener) != -1) {
- Log.d(TAG, "Listener is already added, ignoring");
- return;
- }
- mListeners.add(new MessageHandler(looper, listener));
- }
- }
-
- /**
- * Remove a listener from this interface.
- *
- * @param listener The listener to stop receiving commands on.
- */
- public void removeListener(CommandListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener may not be null");
- }
- synchronized (mLock) {
- int index = findIndexOfListenerLocked(listener);
- if (index != -1) {
- mListeners.remove(index);
- }
- }
- }
-
- /**
- * @hide
- */
- public void onCommand(String command, Bundle args, ResultReceiver cb) {
- synchronized (mLock) {
- Command cmd = new Command(command, args, cb);
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- mListeners.get(i).post(MessageHandler.MSG_COMMAND, cmd);
- }
- }
- }
-
- /**
- * Get the interface name.
- *
- * @return The name of this interface
- */
- public String getName() {
- return mName;
- }
-
- private int findIndexOfListenerLocked(CommandListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("Callback cannot be null");
- }
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- MessageHandler handler = mListeners.get(i);
- if (listener == handler.mListener) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Handles commands sent to the interface.
- * <p>
- * Register an InterfaceListener using {@link #addListener}.
- */
- public abstract static class CommandListener {
- /**
- * This is called when a command is received that matches this
- * interface. Commands are sent by a {@link MediaSession} that is
- * connected to the route this interface is registered with.
- *
- * @param iface The interface the command was received on.
- * @param command The command or method to invoke.
- * @param args Any args that were included with the command. May be
- * null.
- * @param cb The callback provided to send a response on. May be null.
- * @return true if the command was handled, false otherwise. If the
- * command was not handled an error will be sent automatically.
- * true may be returned if the command will be handled
- * asynchronously.
- * @see Route
- * @see MediaSession
- */
- public abstract boolean onCommand(RouteInterfaceHandler iface, String command, Bundle args,
- ResultReceiver cb);
- }
-
- private class MessageHandler extends Handler {
- private static final int MSG_COMMAND = 1;
-
- private final CommandListener mListener;
-
- public MessageHandler(Looper looper, CommandListener listener) {
- super(looper, null, true /* async */);
- mListener = listener;
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_COMMAND:
- Command cmd = (Command) msg.obj;
- if (!mListener.onCommand(RouteInterfaceHandler.this, cmd.command, cmd.args, cmd.cb)) {
- sendResult(cmd.cb, RouteInterface.RESULT_COMMAND_NOT_SUPPORTED,
- null);
- }
- break;
- }
- }
-
- public void post(int what, Object obj) {
- obtainMessage(what, obj).sendToTarget();
- }
- }
-
- private final static class Command {
- public final String command;
- public final Bundle args;
- public final ResultReceiver cb;
-
- public Command(String command, Bundle args, ResultReceiver cb) {
- this.command = command;
- this.args = args;
- this.cb = cb;
- }
- }
-}
diff --git a/media/java/android/media/routeprovider/RoutePlaybackControlsHandler.java b/media/java/android/media/routeprovider/RoutePlaybackControlsHandler.java
deleted file mode 100644
index f2c40d2..0000000
--- a/media/java/android/media/routeprovider/RoutePlaybackControlsHandler.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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.
- */
-package android.media.routeprovider;
-
-import android.media.session.RoutePlaybackControls;
-import android.media.session.RouteInterface;
-import android.media.session.PlaybackState;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * Standard wrapper for using playback controls over a {@link RouteInterfaceHandler}.
- * This is the provider half of the interface. Sessions should use
- * {@link RoutePlaybackControls} to interact with this interface.
- * @hide
- */
-public final class RoutePlaybackControlsHandler {
- private static final String TAG = "RoutePlaybackControls";
-
- private final RouteInterfaceHandler mIface;
-
- private RoutePlaybackControlsHandler(RouteInterfaceHandler iface) {
- mIface = iface;
- }
-
- /**
- * Add this interface to the specified route and return a handle for
- * communicating on the interface.
- *
- * @param connection The connection to register this interface on.
- * @return A handle for communicating on this interface.
- */
- public static RoutePlaybackControlsHandler addTo(RouteConnection connection) {
- if (connection == null) {
- throw new IllegalArgumentException("connection may not be null");
- }
- RouteInterfaceHandler iface = connection
- .addRouteInterface(RoutePlaybackControls.NAME);
-
- return new RoutePlaybackControlsHandler(iface);
- }
-
- /**
- * Add a {@link Listener} to this interface. The listener will receive
- * commands on the caller's thread.
- *
- * @param listener The listener to send commands to.
- */
- public void addListener(Listener listener) {
- addListener(listener, null);
- }
-
- /**
- * Add a {@link Listener} to this interface. The listener will receive
- * updates on the handler's thread. If no handler is specified the caller's
- * thread will be used instead.
- *
- * @param listener The listener to send commands to.
- * @param handler The handler whose thread calls should be posted on. May be
- * null.
- */
- public void addListener(Listener listener, Handler handler) {
- mIface.addListener(listener, handler);
- }
-
- /**
- * Remove a {@link Listener} from this interface.
- *
- * @param listener The Listener to remove.
- */
- public void removeListener(Listener listener) {
- mIface.removeListener(listener);
- }
-
- /**
- * Publish the current playback state to the system and any controllers.
- * Valid values are defined in {@link PlaybackState}. TODO create
- * RoutePlaybackState.
- *
- * @param state
- */
- public void sendPlaybackChangeEvent(int state) {
- Bundle extras = new Bundle();
- extras.putInt(RoutePlaybackControls.KEY_VALUE1, state);
- mIface.sendEvent(RoutePlaybackControls.EVENT_PLAYSTATE_CHANGE, extras);
- }
-
- /**
- * Command handler for the RoutePlaybackControls interface. You can add a
- * Listener to the interface using {@link #addListener}.
- */
- public static abstract class Listener extends RouteInterfaceHandler.CommandListener {
-
- @Override
- public final boolean onCommand(RouteInterfaceHandler iface, String method, Bundle extras,
- ResultReceiver cb) {
- if (RoutePlaybackControls.CMD_FAST_FORWARD.equals(method)) {
- boolean success = fastForward();
- // TODO specify type of error
- RouteInterfaceHandler.sendResult(cb, success
- ? RouteInterface.RESULT_SUCCESS
- : RouteInterface.RESULT_ERROR, null);
- return true;
- } else if (RoutePlaybackControls.CMD_GET_CURRENT_POSITION.equals(method)) {
- Bundle result = new Bundle();
- result.putLong(RoutePlaybackControls.KEY_VALUE1, getCurrentPosition());
- RouteInterfaceHandler.sendResult(cb, RouteInterface.RESULT_SUCCESS,
- result);
- return true;
- } else if (RoutePlaybackControls.CMD_GET_CAPABILITIES.equals(method)) {
- Bundle result = new Bundle();
- result.putLong(RoutePlaybackControls.KEY_VALUE1, getCapabilities());
- RouteInterfaceHandler.sendResult(cb, RouteInterface.RESULT_SUCCESS,
- result);
- return true;
- } else if (RoutePlaybackControls.CMD_PLAY_NOW.equals(method)) {
- playNow(extras.getString(RoutePlaybackControls.KEY_VALUE1, null), cb);
- return true;
- } else if (RoutePlaybackControls.CMD_RESUME.equals(method)) {
- boolean success = resume();
- RouteInterfaceHandler.sendResult(cb, success
- ? RouteInterface.RESULT_SUCCESS
- : RouteInterface.RESULT_ERROR, null);
- return true;
- } else if (RoutePlaybackControls.CMD_PAUSE.equals(method)) {
- boolean success = pause();
- RouteInterfaceHandler.sendResult(cb, success
- ? RouteInterface.RESULT_SUCCESS
- : RouteInterface.RESULT_ERROR, null);
- return true;
- } else {
- // The command wasn't recognized
- }
- return false;
- }
-
- /**
- * Override to handle fast forwarding.
- *
- * @return true if the request succeeded, false otherwise
- */
- public boolean fastForward() {
- Log.w(TAG, "fastForward is not supported.");
- return false;
- }
-
- /**
- * Override to handle getting the current position of playback in
- * millis.
- *
- * @return The current position in millis or -1
- */
- public long getCurrentPosition() {
- Log.w(TAG, "getCurrentPosition is not supported");
- return -1;
- }
-
- /**
- * Override to handle getting the set of capabilities currently
- * available.
- *
- * @return A bit mask of the supported capabilities
- */
- public long getCapabilities() {
- Log.w(TAG, "getCapabilities is not supported");
- return 0;
- }
-
- /**
- * Override to handle play now requests.
- *
- * @param content The uri of the item to play.
- * @param cb The callback to send the result to.
- */
- public void playNow(String content, ResultReceiver cb) {
- Log.w(TAG, "playNow is not supported");
- if (cb != null) {
- // We do this directly since we don't have a reference to the
- // iface
- cb.send(RouteInterface.RESULT_COMMAND_NOT_SUPPORTED, null);
- }
- }
-
- /**
- * Override to handle resume requests. Return true if the call was
- * handled, even if it was a no-op.
- *
- * @return true if the call was handled.
- */
- public boolean resume() {
- Log.w(TAG, "resume is not supported");
- return false;
- }
-
- /**
- * Override to handle pause requests. Return true if the call was
- * handled, even if it was a no-op.
- *
- * @return true if the call was handled.
- */
- public boolean pause() {
- Log.w(TAG, "pause is not supported");
- return false;
- }
- }
-}
diff --git a/media/java/android/media/routeprovider/RouteProviderService.java b/media/java/android/media/routeprovider/RouteProviderService.java
deleted file mode 100644
index a6ef0bb..0000000
--- a/media/java/android/media/routeprovider/RouteProviderService.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * 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.
- */
-package android.media.routeprovider;
-
-import android.app.Service;
-import android.content.Intent;
-import android.media.routeprovider.IRouteProvider;
-import android.media.routeprovider.IRouteProviderCallback;
-import android.media.session.RouteEvent;
-import android.media.session.RouteInfo;
-import android.media.session.RouteOptions;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Base class for defining a route provider service.
- * <p>
- * A route provider offers media routes which represent destinations to which
- * applications may connect, control, and send content. This provides a means
- * for Android applications to interact with a variety of media streaming
- * devices such as speakers or television sets.
- * <p>
- * The system will bind to your provider when an active app is interested in
- * routes that may be discovered through your provider. After binding, the
- * system will send updates on which routes to discover through
- * {@link #updateDiscoveryRequests(List)}. The system will call
- * {@link #getMatchingRoutes(List)} with a subset of filters when a route is
- * needed for a specific app.
- * <p>
- * TODO add documentation for how the sytem knows an app is interested. Maybe
- * interface declarations in the manifest.
- * <p>
- * The system will only start a provider when an app may discover routes through
- * it. If your service needs to run at other times you are responsible for
- * managing its lifecycle.
- * <p>
- * Declare your route provider service in your application manifest like this:
- * <p>
- *
- * <pre>
- * <service android:name=".MyRouteProviderService"
- * android:label="@string/my_route_provider_service">
- * <intent-filter>
- * <action android:name="com.android.media.session.MediaRouteProvider" />
- * </intent-filter>
- * </service>
- * </pre>
- * @hide
- */
-public abstract class RouteProviderService extends Service {
- private static final String TAG = "RouteProvider";
- /**
- * A service that implements a RouteProvider must declare that it handles
- * this action in its AndroidManifest.
- */
- public static final String SERVICE_INTERFACE =
- "com.android.media.session.MediaRouteProvider";
-
- /**
- * @hide
- */
- public static final String KEY_ROUTES = "routes";
- /**
- * @hide
- */
- public static final String KEY_CONNECTION = "connection";
- /**
- * @hide
- */
- public static final int RESULT_FAILURE = -1;
- /**
- * @hide
- */
- public static final int RESULT_SUCCESS = 0;
-
- // The system's callback once it has bound to the service
- private IRouteProviderCallback mCb;
-
- /**
- * If your service overrides onBind it must return super.onBind() in
- * response to the {@link #SERVICE_INTERFACE} action.
- */
- @Override
- public IBinder onBind(Intent intent) {
- if (intent != null && RouteProviderService.SERVICE_INTERFACE.equals(intent.getAction())) {
- return mBinder;
- }
- return null;
- }
-
- /**
- * Disconnect the specified RouteConnection. The system will stop sending
- * commands to this connection.
- *
- * @param connection The connection to disconnect.
- * @hide
- */
- public final void disconnect(RouteConnection connection) {
- if (mCb != null) {
- try {
- mCb.onConnectionTerminated(connection.getBinder());
- } catch (RemoteException e) {
- Log.wtf(TAG, "Error in disconnect.", e);
- }
- }
- }
-
- /**
- * @hide
- */
- public final void sendRouteEvent(RouteEvent event) {
- if (mCb != null) {
- try {
- mCb.onRouteEvent(event);
- } catch (RemoteException e) {
- Log.wtf(TAG, "Unable to send MediaRouteEvent to system", e);
- }
- }
- }
-
- /**
- * Override to handle updates to the routes that are of interest. Each
- * {@link RouteRequest} will specify if it is an active or passive request.
- * Route discovery may perform more aggressive discovery on behalf of active
- * requests but should use low power discovery methods otherwise.
- * <p>
- * A single app may have more than one request. Your provider is responsible
- * for deciding the set of features that are important for discovery given
- * the set of requests. If your provider only has one method of discovery it
- * may simply verify that one or more requests are valid before starting
- * discovery.
- *
- * @param requests The route requests that are currently relevant.
- */
- public void updateDiscoveryRequests(List<RouteRequest> requests) {
- }
-
- /**
- * Return a list of matching routes for the given set of requests. Returning
- * null or an empty list indicates there are no matches. A route is
- * considered matching if it supports one or more of the
- * {@link RouteOptions} specified. Each returned {@link RouteInfo}
- * should include all the requested connections that it supports.
- *
- * @param options The set of requests for routes
- * @return The routes that this caller may connect to using one or more of
- * the route options.
- */
- public abstract List<RouteInfo> getMatchingRoutes(List<RouteRequest> options);
-
- /**
- * Handle a request to connect to a specific route with a specific request.
- * The {@link RouteConnection} must be fully defined before being returned,
- * though the actual connection to the route may be performed in the
- * background.
- *
- * @param route The route to connect to
- * @param request The connection request parameters
- * @return A MediaRouteConnection representing the connection to the route
- */
- public abstract RouteConnection connect(RouteInfo route, RouteRequest request);
-
- private IRouteProvider.Stub mBinder = new IRouteProvider.Stub() {
-
- @Override
- public void registerCallback(IRouteProviderCallback cb) throws RemoteException {
- mCb = cb;
- }
-
- @Override
- public void unregisterCallback(IRouteProviderCallback cb) throws RemoteException {
- mCb = null;
- }
-
- @Override
- public void updateDiscoveryRequests(List<RouteRequest> requests)
- throws RemoteException {
- RouteProviderService.this.updateDiscoveryRequests(requests);
- }
-
- @Override
- public void getAvailableRoutes(List<RouteRequest> requests, ResultReceiver cb)
- throws RemoteException {
- List<RouteInfo> routes = RouteProviderService.this.getMatchingRoutes(requests);
- ArrayList<RouteInfo> routesArray;
- if (routes instanceof ArrayList) {
- routesArray = (ArrayList<RouteInfo>) routes;
- } else {
- routesArray = new ArrayList<RouteInfo>(routes);
- }
- Bundle resultData = new Bundle();
- resultData.putParcelableArrayList(KEY_ROUTES, routesArray);
- cb.send(routes == null ? RESULT_FAILURE : RESULT_SUCCESS, resultData);
- }
-
- @Override
- public void connect(RouteInfo route, RouteRequest request, ResultReceiver cb)
- throws RemoteException {
- RouteConnection connection = RouteProviderService.this.connect(route, request);
- Bundle resultData = new Bundle();
- if (connection != null) {
- connection.publish();
- resultData.putBinder(KEY_CONNECTION, connection.getBinder());
- }
-
- cb.send(connection == null ? RESULT_FAILURE : RESULT_SUCCESS, resultData);
- }
- };
-}
diff --git a/media/java/android/media/routeprovider/RouteRequest.aidl b/media/java/android/media/routeprovider/RouteRequest.aidl
deleted file mode 100644
index 7bc5722..0000000
--- a/media/java/android/media/routeprovider/RouteRequest.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 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.
-*/
-
-package android.media.routeprovider;
-
-parcelable RouteRequest;
diff --git a/media/java/android/media/routeprovider/RouteRequest.java b/media/java/android/media/routeprovider/RouteRequest.java
deleted file mode 100644
index 2ba75de..0000000
--- a/media/java/android/media/routeprovider/RouteRequest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.
- */
-package android.media.routeprovider;
-
-import android.media.session.RouteOptions;
-import android.media.session.MediaSessionInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.io.PrintWriter;
-
-/**
- * A request to connect or discover routes with certain capabilities.
- * <p>
- * Passed to a {@link RouteProviderService} when a request for discovery or to
- * connect to a route is made. This identifies the app making the request and
- * provides the full set of connection parameters they would like to use for a
- * connection. An app that can connect in multiple ways will be represented by
- * multiple requests.
- * @hide
- */
-public final class RouteRequest implements Parcelable {
- private final MediaSessionInfo mSessionInfo;
- private final RouteOptions mOptions;
- private final boolean mActive;
-
- /**
- * @hide
- */
- public RouteRequest(MediaSessionInfo info, RouteOptions connRequest,
- boolean active) {
- mSessionInfo = info;
- mOptions = connRequest;
- mActive = active;
- }
-
- private RouteRequest(Parcel in) {
- mSessionInfo = MediaSessionInfo.CREATOR.createFromParcel(in);
- mOptions = RouteOptions.CREATOR.createFromParcel(in);
- mActive = in.readInt() != 0;
- }
-
- /**
- * Get information about the session making the request.
- *
- * @return Info on the session making the request
- */
- public MediaSessionInfo getSessionInfo() {
- return mSessionInfo;
- }
-
- /**
- * Get the connection options, which includes the interfaces and other
- * connection params the session wants to use with a route.
- *
- * @return The connection options
- */
- public RouteOptions getConnectionOptions() {
- return mOptions;
- }
-
- @Override
- public String toString() {
- StringBuilder bob = new StringBuilder();
- bob.append("RouteRequest {");
- bob.append("active=").append(mActive);
- bob.append(", info=").append(mSessionInfo.toString());
- bob.append(", options=").append(mOptions.toString());
- bob.append("}");
- return bob.toString();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- mSessionInfo.writeToParcel(dest, flags);
- mOptions.writeToParcel(dest, flags);
- dest.writeInt(mActive ? 1 : 0);
- }
-
- public static final Parcelable.Creator<RouteRequest> CREATOR
- = new Parcelable.Creator<RouteRequest>() {
- @Override
- public RouteRequest createFromParcel(Parcel in) {
- return new RouteRequest(in);
- }
-
- @Override
- public RouteRequest[] newArray(int size) {
- return new RouteRequest[size];
- }
- };
-}
diff --git a/media/java/android/media/routing/IMediaRouteClientCallback.aidl b/media/java/android/media/routing/IMediaRouteClientCallback.aidl
new file mode 100644
index 0000000..d90ea3b
--- /dev/null
+++ b/media/java/android/media/routing/IMediaRouteClientCallback.aidl
@@ -0,0 +1,41 @@
+/* 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.
+ */
+
+package android.media.routing;
+
+import android.media.routing.MediaRouteSelector;
+import android.media.routing.ParcelableConnectionInfo;
+import android.media.routing.ParcelableDestinationInfo;
+import android.media.routing.ParcelableRouteInfo;
+import android.os.IBinder;
+import android.os.Bundle;
+
+/**
+ * @hide
+ */
+oneway interface IMediaRouteClientCallback {
+ void onDestinationFound(int seq, in ParcelableDestinationInfo destination,
+ in ParcelableRouteInfo[] routes);
+
+ void onDestinationLost(int seq, String id);
+
+ void onDiscoveryFailed(int seq, int error, in CharSequence message, in Bundle extras);
+
+ void onConnected(int seq, in ParcelableConnectionInfo connection);
+
+ void onDisconnected(int seq);
+
+ void onConnectionFailed(int seq, int error, in CharSequence message, in Bundle extras);
+}
diff --git a/media/java/android/media/routing/IMediaRouteService.aidl b/media/java/android/media/routing/IMediaRouteService.aidl
new file mode 100644
index 0000000..493ab6d
--- /dev/null
+++ b/media/java/android/media/routing/IMediaRouteService.aidl
@@ -0,0 +1,46 @@
+/* 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.
+ */
+
+package android.media.routing;
+
+import android.media.routing.IMediaRouteClientCallback;
+import android.media.routing.MediaRouteSelector;
+import android.os.Bundle;
+
+/**
+ * Interface to an app's MediaRouteService.
+ * @hide
+ */
+oneway interface IMediaRouteService {
+ void registerClient(int clientUid, String clientPackageName,
+ in IMediaRouteClientCallback callback);
+
+ void unregisterClient(in IMediaRouteClientCallback callback);
+
+ void startDiscovery(in IMediaRouteClientCallback callback, int seq,
+ in List<MediaRouteSelector> selectors, int flags);
+
+ void stopDiscovery(in IMediaRouteClientCallback callback);
+
+ void connect(in IMediaRouteClientCallback callback, int seq,
+ String destinationId, String routeId, int flags, in Bundle extras);
+
+ void disconnect(in IMediaRouteClientCallback callback);
+
+ void pauseStream(in IMediaRouteClientCallback callback);
+
+ void resumeStream(in IMediaRouteClientCallback callback);
+}
+
diff --git a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl b/media/java/android/media/routing/IMediaRouter.aidl
similarity index 73%
copy from telecomm/java/android/telecomm/CallServiceDescriptor.aidl
copy to media/java/android/media/routing/IMediaRouter.aidl
index f517c73..0abb258 100644
--- a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl
+++ b/media/java/android/media/routing/IMediaRouter.aidl
@@ -1,11 +1,10 @@
-/*
- * Copyright 2014, The Android Open Source Project
+/* 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
+ * 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,
@@ -14,6 +13,10 @@
* limitations under the License.
*/
-package android.telecomm;
+package android.media.routing;
-parcelable CallServiceDescriptor;
+/** @hide */
+interface IMediaRouter {
+
+}
+
diff --git a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl b/media/java/android/media/routing/IMediaRouterDelegate.aidl
similarity index 72%
copy from telecomm/java/android/telecomm/CallServiceDescriptor.aidl
copy to media/java/android/media/routing/IMediaRouterDelegate.aidl
index f517c73..35f84c8 100644
--- a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl
+++ b/media/java/android/media/routing/IMediaRouterDelegate.aidl
@@ -1,11 +1,10 @@
-/*
- * Copyright 2014, The Android Open Source Project
+/* 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
+ * 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,
@@ -14,6 +13,10 @@
* limitations under the License.
*/
-package android.telecomm;
+package android.media.routing;
-parcelable CallServiceDescriptor;
+/** @hide */
+interface IMediaRouterDelegate {
+
+}
+
diff --git a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl b/media/java/android/media/routing/IMediaRouterRoutingCallback.aidl
similarity index 72%
copy from telecomm/java/android/telecomm/CallServiceDescriptor.aidl
copy to media/java/android/media/routing/IMediaRouterRoutingCallback.aidl
index f517c73..173ae55 100644
--- a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl
+++ b/media/java/android/media/routing/IMediaRouterRoutingCallback.aidl
@@ -1,11 +1,10 @@
-/*
- * Copyright 2014, The Android Open Source Project
+/* 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
+ * 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,
@@ -14,6 +13,10 @@
* limitations under the License.
*/
-package android.telecomm;
+package android.media.routing;
-parcelable CallServiceDescriptor;
+/** @hide */
+interface IMediaRouterRoutingCallback {
+
+}
+
diff --git a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl b/media/java/android/media/routing/IMediaRouterStateCallback.aidl
similarity index 72%
copy from telecomm/java/android/telecomm/CallServiceDescriptor.aidl
copy to media/java/android/media/routing/IMediaRouterStateCallback.aidl
index f517c73..0299904 100644
--- a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl
+++ b/media/java/android/media/routing/IMediaRouterStateCallback.aidl
@@ -1,11 +1,10 @@
-/*
- * Copyright 2014, The Android Open Source Project
+/* 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
+ * 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,
@@ -14,6 +13,10 @@
* limitations under the License.
*/
-package android.telecomm;
+package android.media.routing;
-parcelable CallServiceDescriptor;
+/** @hide */
+interface IMediaRouterStateCallback {
+
+}
+
diff --git a/media/java/android/media/session/RouteEvent.aidl b/media/java/android/media/routing/MediaRouteSelector.aidl
similarity index 90%
rename from media/java/android/media/session/RouteEvent.aidl
rename to media/java/android/media/routing/MediaRouteSelector.aidl
index 6966207..37bfa4a 100644
--- a/media/java/android/media/session/RouteEvent.aidl
+++ b/media/java/android/media/routing/MediaRouteSelector.aidl
@@ -13,6 +13,6 @@
** limitations under the License.
*/
-package android.media.session;
+package android.media.routing;
-parcelable RouteEvent;
+parcelable MediaRouteSelector;
diff --git a/media/java/android/media/routing/MediaRouteSelector.java b/media/java/android/media/routing/MediaRouteSelector.java
new file mode 100644
index 0000000..26a9b1c
--- /dev/null
+++ b/media/java/android/media/routing/MediaRouteSelector.java
@@ -0,0 +1,357 @@
+/*
+ * 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.
+ */
+package android.media.routing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.routing.MediaRouter.RouteFeatures;
+import android.os.Bundle;
+import android.os.IInterface;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A media route selector consists of a set of constraints that are used to select
+ * the routes to which an application would like to connect. The constraints consist
+ * of a set of required or optional features and protocols. The constraints may also
+ * require the use of a specific media route service package or additional characteristics
+ * that are described by a bundle of extra parameters.
+ * <p>
+ * The application will typically create several different selectors that express
+ * various combinations of characteristics that it would like to use together when
+ * it connects to a destination media device. For each destination that is discovered,
+ * media route services will publish some number of routes and include information
+ * about which selector each route matches. The application will then choose among
+ * these routes to determine which best satisfies its desired purpose and connect to it.
+ * </p>
+ */
+public final class MediaRouteSelector implements Parcelable {
+ private final int mRequiredFeatures;
+ private final int mOptionalFeatures;
+ private final List<String> mRequiredProtocols;
+ private final List<String> mOptionalProtocols;
+ private final String mServicePackageName;
+ private final Bundle mExtras;
+
+ MediaRouteSelector(int requiredFeatures, int optionalFeatures,
+ List<String> requiredProtocols, List<String> optionalProtocols,
+ String servicePackageName, Bundle extras) {
+ mRequiredFeatures = requiredFeatures;
+ mOptionalFeatures = optionalFeatures;
+ mRequiredProtocols = requiredProtocols;
+ mOptionalProtocols = optionalProtocols;
+ mServicePackageName = servicePackageName;
+ mExtras = extras;
+ }
+
+ /**
+ * Gets the set of required route features.
+ *
+ * @return A set of required route feature flags.
+ */
+ public @RouteFeatures int getRequiredFeatures() {
+ return mRequiredFeatures;
+ }
+
+ /**
+ * Gets the set of optional route features.
+ *
+ * @return A set of optional route feature flags.
+ */
+ public @RouteFeatures int getOptionalFeatures() {
+ return mOptionalFeatures;
+ }
+
+ /**
+ * Gets the list of route protocols that a route must support in order to be selected.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ *
+ * @return The list of fully qualified route protocol names.
+ */
+ public @NonNull List<String> getRequiredProtocols() {
+ return mRequiredProtocols;
+ }
+
+ /**
+ * Gets the list of optional route protocols that a client may use if they are available.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ *
+ * @return The list of optional fully qualified route protocol names.
+ */
+ public @NonNull List<String> getOptionalProtocols() {
+ return mOptionalProtocols;
+ }
+
+ /**
+ * Returns true if the selector includes a required or optional request for
+ * the specified protocol using its fully qualified class name.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ *
+ * @param clazz The protocol class.
+ * @return True if the protocol was requested.
+ */
+ public boolean containsProtocol(@NonNull Class<?> clazz) {
+ return containsProtocol(clazz.getName());
+ }
+
+ /**
+ * Returns true if the selector includes a required or optional request for
+ * the specified protocol.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ *
+ * @param name The name of the protocol.
+ * @return True if the protocol was requested.
+ */
+ public boolean containsProtocol(@NonNull String name) {
+ return mRequiredProtocols.contains(name)
+ || mOptionalProtocols.contains(name);
+ }
+
+ /**
+ * Gets the package name of a specific media route service that this route selector
+ * requires.
+ *
+ * @return The required media route service package name, or null if none.
+ */
+ public @Nullable String getServicePackageName() {
+ return mServicePackageName;
+ }
+
+ /**
+ * Gets optional extras that may be used to select or configure routes for a
+ * particular purpose. Some extras may be used by media route services to apply
+ * additional constraints or parameters for the routes to be discovered.
+ *
+ * @return The optional extras, or null if none.
+ */
+ public @Nullable Bundle getExtras() {
+ return mExtras;
+ }
+
+ @Override
+ public String toString() {
+ return "MediaRouteSelector{ "
+ + ", requiredFeatures=0x" + Integer.toHexString(mRequiredFeatures)
+ + ", optionalFeatures=0x" + Integer.toHexString(mOptionalFeatures)
+ + ", requiredProtocols=" + mRequiredProtocols
+ + ", optionalProtocols=" + mOptionalProtocols
+ + ", servicePackageName=" + mServicePackageName
+ + ", extras=" + mExtras + " }";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mRequiredFeatures);
+ dest.writeInt(mOptionalFeatures);
+ dest.writeStringList(mRequiredProtocols);
+ dest.writeStringList(mOptionalProtocols);
+ dest.writeString(mServicePackageName);
+ dest.writeBundle(mExtras);
+ }
+
+ public static final Parcelable.Creator<MediaRouteSelector> CREATOR =
+ new Parcelable.Creator<MediaRouteSelector>() {
+ @Override
+ public MediaRouteSelector createFromParcel(Parcel source) {
+ int requiredFeatures = source.readInt();
+ int optionalFeatures = source.readInt();
+ ArrayList<String> requiredProtocols = new ArrayList<String>();
+ ArrayList<String> optionalProtocols = new ArrayList<String>();
+ source.readStringList(requiredProtocols);
+ source.readStringList(optionalProtocols);
+ return new MediaRouteSelector(requiredFeatures, optionalFeatures,
+ requiredProtocols, optionalProtocols,
+ source.readString(), source.readBundle());
+ }
+
+ @Override
+ public MediaRouteSelector[] newArray(int size) {
+ return new MediaRouteSelector[size];
+ }
+ };
+
+ /**
+ * Builder for {@link MediaRouteSelector} objects.
+ */
+ public static final class Builder {
+ private int mRequiredFeatures;
+ private int mOptionalFeatures;
+ private final ArrayList<String> mRequiredProtocols = new ArrayList<String>();
+ private final ArrayList<String> mOptionalProtocols = new ArrayList<String>();
+ private String mServicePackageName;
+ private Bundle mExtras;
+
+ /**
+ * Creates an initially empty selector builder.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Sets the set of required route features.
+ *
+ * @param features A set of required route feature flags.
+ */
+ public @NonNull Builder setRequiredFeatures(@RouteFeatures int features) {
+ mRequiredFeatures = features;
+ return this;
+ }
+
+ /**
+ * Sets the set of optional route features.
+ *
+ * @param features A set of optional route feature flags.
+ */
+ public @NonNull Builder setOptionalFeatures(@RouteFeatures int features) {
+ mOptionalFeatures = features;
+ return this;
+ }
+
+ /**
+ * Adds a route protocol that a route must support in order to be selected
+ * using its fully qualified class name.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ *
+ * @param clazz The protocol class.
+ * @return this
+ */
+ public @NonNull Builder addRequiredProtocol(@NonNull Class<?> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("clazz must not be null");
+ }
+ return addRequiredProtocol(clazz.getName());
+ }
+
+ /**
+ * Adds a route protocol that a route must support in order to be selected.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ *
+ * @param name The fully qualified name of the required protocol.
+ * @return this
+ */
+ public @NonNull Builder addRequiredProtocol(@NonNull String name) {
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name must not be null or empty");
+ }
+ mRequiredProtocols.add(name);
+ return this;
+ }
+
+ /**
+ * Adds an optional route protocol that a client may use if available
+ * using its fully qualified class name.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ *
+ * @param clazz The protocol class.
+ * @return this
+ */
+ public @NonNull Builder addOptionalProtocol(@NonNull Class<?> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("clazz must not be null");
+ }
+ return addOptionalProtocol(clazz.getName());
+ }
+
+ /**
+ * Adds an optional route protocol that a client may use if available.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ *
+ * @param name The fully qualified name of the optional protocol.
+ * @return this
+ */
+ public @NonNull Builder addOptionalProtocol(@NonNull String name) {
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name must not be null or empty");
+ }
+ mOptionalProtocols.add(name);
+ return this;
+ }
+
+ /**
+ * Sets the package name of the media route service to which this selector
+ * appertains.
+ * <p>
+ * If a package name is specified here then this selector will only be
+ * passed to media route services from that package. This has the effect
+ * of restricting the set of matching routes to just those that are offered
+ * by that package.
+ * </p>
+ *
+ * @param packageName The required service package name, or null if none.
+ * @return this
+ */
+ public @NonNull Builder setServicePackageName(@Nullable String packageName) {
+ mServicePackageName = packageName;
+ return this;
+ }
+
+ /**
+ * Sets optional extras that may be used to select or configure routes for a
+ * particular purpose. Some extras may be used by route services to specify
+ * additional constraints or parameters for the routes to be discovered.
+ *
+ * @param extras The optional extras, or null if none.
+ * @return this
+ */
+ public @NonNull Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
+ * Builds the {@link MediaRouteSelector} object.
+ *
+ * @return The new media route selector instance.
+ */
+ public @NonNull MediaRouteSelector build() {
+ return new MediaRouteSelector(mRequiredFeatures, mOptionalFeatures,
+ mRequiredProtocols, mOptionalProtocols, mServicePackageName, mExtras);
+ }
+ }
+}
diff --git a/media/java/android/media/routing/MediaRouteService.java b/media/java/android/media/routing/MediaRouteService.java
new file mode 100644
index 0000000..4d5a8a9
--- /dev/null
+++ b/media/java/android/media/routing/MediaRouteService.java
@@ -0,0 +1,1023 @@
+/*
+ * 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.
+ */
+package android.media.routing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.media.routing.MediaRouter.ConnectionError;
+import android.media.routing.MediaRouter.ConnectionInfo;
+import android.media.routing.MediaRouter.ConnectionRequest;
+import android.media.routing.MediaRouter.DestinationInfo;
+import android.media.routing.MediaRouter.DiscoveryError;
+import android.media.routing.MediaRouter.DiscoveryRequest;
+import android.media.routing.MediaRouter.RouteInfo;
+import android.media.routing.MediaRouter.ServiceMetadata;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Media route services implement strategies for discovering
+ * and establishing connections to media devices and their routes. These services
+ * are also known as media route providers.
+ * <p>
+ * Each media route service subclass is responsible for enabling applications
+ * and the system to interact with media devices of some kind.
+ * For example, one particular media route service implementation might
+ * offer support for discovering nearby wireless display devices and streaming
+ * video contents to them; another media route service implementation might
+ * offer support for discovering nearby speakers and streaming media appliances
+ * and sending commands to play content on request.
+ * </p><p>
+ * Subclasses must override the {@link #onCreateClientSession} method to return
+ * a {@link ClientSession} object that implements the {@link ClientSession#onStartDiscovery},
+ * {@link ClientSession#onStopDiscovery}, and {@link ClientSession#onConnect} methods
+ * to allow clients to discover and connect to media devices.
+ * </p><p>
+ * This object is not thread-safe. All callbacks are invoked on the main looper.
+ * </p>
+ *
+ * <h3>Clients</h3>
+ * <p>
+ * The clients of this API are media applications that would like to discover
+ * and connect to media devices. The client may also be the system, such as
+ * when the user initiates display mirroring via the Cast Screen function.
+ * </p><p>
+ * There may be multiple client sessions active at the same time. Each client
+ * session can request discovery and connect to routes independently of any
+ * other client. It is the responsibility of the media route service to maintain
+ * separate state for each client session and to ensure that clients cannot interfere
+ * with one another in harmful ways.
+ * </p><p>
+ * Notwithstanding the requirement to support any number of concurrent client
+ * sessions, the media route service may impose constraints on how many clients
+ * can connect to the same media device in a particular mode at the same time.
+ * In some cases, media devices may support connections from an arbitrary number
+ * of clients simultaneously but often it may be necessary to ensure that only
+ * one client is in control. When this happens, the media route service should
+ * report a connection error unless the connection request specifies that the
+ * client should take control of the media device (and forcibly disconnect other
+ * clients that may be using it).
+ * </p>
+ *
+ * <h3>Destinations</h3>
+ * <p>
+ * The media devices to which an application may send media content are referred
+ * to in the API as destinations. Each destination therefore represents a single
+ * independent device such as a speaker or TV set. Destinations are given meaningful
+ * names and descriptions to help the user associate them with devices in their
+ * environment.
+ * </p><p>
+ * Destinations may be local or remote and may be accessed through various means,
+ * often wirelessly. The user may install media route services to enable
+ * media applications to connect to a variety of destinations with different
+ * capabilities.
+ * </p>
+ *
+ * <h3>Routes</h3>
+ * <p>
+ * Routes represent possible usages or means of reaching and interacting with
+ * a destination. Since destinations may support many different features, they may
+ * each offer multiple routes for applications to choose from based on their needs.
+ * For example, one route might express the ability to stream locally rendered audio
+ * and video to the device; another route might express the ability to send a URL for
+ * the destination to download from the network and play all by itself.
+ * </p><p>
+ * Routes are discovered according to the set of capabilities that
+ * an application or the system is seeking to use at a particular time. For example,
+ * if an application wants to stream music to a destination then it will ask the
+ * {@link MediaRouter} to find routes to destinations can stream music and ignore
+ * all other destinations that cannot.
+ * </p><p>
+ * In general, the application will inspect the set of routes that have been
+ * offered then connect to the most appropriate route for its desired purpose.
+ * </p>
+ *
+ * <h3>Discovery</h3>
+ * <p>
+ * Discovery is the process of finding destinations based on a description of the
+ * kinds of routes that an application or the system would like to use.
+ * </p><p>
+ * Discovery begins when {@link ClientSession#onStartDiscovery} is called and ends when
+ * {@link ClientSession#onStopDiscovery} is called. There may be multiple simultaneous
+ * discovery requests in progress at the same time from different clients. It is up to
+ * the media route service to perform these requests in parallel or multiplex them
+ * as required.
+ * </p><p>
+ * Media route services are <em>strongly encouraged</em> to use the information
+ * in the discovery request to optimize discovery and avoid redundant work.
+ * In the case where no media device supported by the media route service
+ * could possibly offer the requested capabilities, the
+ * {@link ClientSession#onStartDiscovery} method should return <code>false</code> to
+ * let the system know that it can unbind from the media route service and
+ * release its resources.
+ * </p>
+ *
+ * <h3>Settings</h3>
+ * <p>
+ * Many kinds of devices can be discovered on demand simply by scanning the local network
+ * or using wireless protocols such as Bluetooth to find them. However, in some cases
+ * it may be necessary for the user to manually configure destinations before they
+ * can be used (or to adjust settings later). Actual user configuration of destinations
+ * is beyond the scope of this API but media route services may specify an activity
+ * in their manifest that the user can launch to perform these tasks.
+ * </p><p>
+ * Note that media route services that are installed from the store must be enabled
+ * by the user before they become available for applications to use.
+ * The {@link android.provider.Settings#ACTION_CAST_SETTINGS Settings.ACTION_CAST_SETTINGS}
+ * settings activity provides the ability for the user to configure media route services.
+ * </p>
+ *
+ * <h3>Manifest Declaration</h3>
+ * <p>
+ * Media route services must be declared in the manifest along with meta-data
+ * about the kinds of routes that they are capable of discovering. The system
+ * uses this information to optimize the set of services to which it binds in
+ * order to satisfy a particular discovery request.
+ * </p><p>
+ * To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_MEDIA_ROUTE_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. You must
+ * also add meta-data to describe the kinds of routes that your service is capable
+ * of discovering.
+ * </p><p>
+ * For example:
+ * </p><pre>
+ * <service android:name=".MediaRouteProvider"
+ * android:label="@string/service_name"
+ * android:permission="android.permission.BIND_MEDIA_ROUTE_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.media.routing.MediaRouteService" />
+ * </intent-filter>
+ *
+ * TODO: INSERT METADATA DECLARATIONS HERE
+ *
+ * </service>
+ * </pre>
+ */
+public abstract class MediaRouteService extends Service {
+ private static final String TAG = "MediaRouteService";
+
+ private static final boolean DEBUG = true;
+
+ private final Handler mHandler;
+ private final BinderService mService;
+ private final ArrayMap<IBinder, ClientRecord> mClientRecords =
+ new ArrayMap<IBinder, ClientRecord>();
+
+ private ServiceMetadata mMetadata;
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE =
+ "android.media.routing.MediaRouteService";
+
+ /**
+ * Creates a media route service.
+ */
+ public MediaRouteService() {
+ mHandler = new Handler(true);
+ mService = new BinderService();
+ }
+
+ @Override
+ public @Nullable IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction())) {
+ return mService;
+ }
+ return null;
+ }
+
+ /**
+ * Creates a new client session on behalf of a client.
+ * <p>
+ * The implementation should return a {@link ClientSession} for the client
+ * to use. The media route service must take care to manage the state of
+ * each client session independently from any others that might also be
+ * in use at the same time.
+ * </p>
+ *
+ * @param client Information about the client.
+ * @return The client session object, or null if the client is not allowed
+ * to interact with this media route service.
+ */
+ public abstract @Nullable ClientSession onCreateClientSession(@NonNull ClientInfo client);
+
+ /**
+ * Gets metadata about this service.
+ * <p>
+ * Use this method to obtain a {@link ServiceMetadata} object to provide when creating
+ * a {@link android.media.routing.MediaRouter.DestinationInfo.Builder}.
+ * </p>
+ *
+ * @return Metadata about this service.
+ */
+ public @NonNull ServiceMetadata getServiceMetadata() {
+ if (mMetadata == null) {
+ try {
+ mMetadata = new ServiceMetadata(this);
+ } catch (NameNotFoundException ex) {
+ Log.wtf(TAG, "Could not retrieve own service metadata!");
+ }
+ }
+ return mMetadata;
+ }
+
+ /**
+ * Enables a single client to access the functionality of the media route service.
+ */
+ public static abstract class ClientSession {
+ /**
+ * Starts discovery.
+ * <p>
+ * If the media route service is capable of discovering routes that satisfy
+ * the request then this method should start discovery and return true.
+ * Otherwise, this method should return false. If false is returned,
+ * then the framework will not call {@link #onStopDiscovery} since discovery
+ * was never actually started.
+ * </p><p>
+ * There may already be other discovery requests in progress at the same time
+ * for other clients; the media route service must keep track of them all.
+ * </p>
+ *
+ * @param req The discovery request to start.
+ * @param callback A callback to receive discovery events related to this
+ * particular request. The events that the service sends to this callback
+ * will be sent to the client that initiated the discovery request.
+ * @return True if discovery has started. False if the media route service
+ * is unable to discover routes that satisfy the request.
+ */
+ public abstract boolean onStartDiscovery(@NonNull DiscoveryRequest req,
+ @NonNull DiscoveryCallback callback);
+
+ /**
+ * Stops discovery.
+ * <p>
+ * If {@link #onStartDiscovery} returned true, then this method will eventually
+ * be called when the framework no longer requires this discovery request
+ * to be performed.
+ * </p><p>
+ * There may still be other discovery requests in progress for other clients;
+ * they must keep working until they have each been stopped by their client.
+ * </p>
+ */
+ public abstract void onStopDiscovery();
+
+ /**
+ * Starts connecting to a route.
+ *
+ * @param req The connection request.
+ * @param callback A callback to receive events connection events related
+ * to this particular request. The events that the service sends to this callback
+ * will be sent to the client that initiated the discovery request.
+ * @return True if the connection is in progress, or false if the client
+ * unable to connect to the requested route.
+ */
+ public abstract boolean onConnect(@NonNull ConnectionRequest req,
+ @NonNull ConnectionCallback callback);
+
+ /**
+ * Called when the client requests to disconnect from the route
+ * or abort a connection attempt in progress.
+ */
+ public abstract void onDisconnect();
+
+ /**
+ * Called when the client requests to pause streaming of content to
+ * live audio/video routes such as when it goes into the background.
+ * <p>
+ * The default implementation does nothing.
+ * </p>
+ */
+ public void onPauseStream() { }
+
+ /**
+ * Called when the application requests to resume streaming of content to
+ * live audio/video routes such as when it returns to the foreground.
+ * <p>
+ * The default implementation does nothing.
+ * </p>
+ */
+ public void onResumeStream() { }
+
+ /**
+ * Called when the client is releasing the session.
+ * <p>
+ * The framework automatically takes care of stopping discovery and
+ * terminating the connection politely before calling this method to release
+ * the session.
+ * </p><p>
+ * The default implementation does nothing.
+ * </p>
+ */
+ public void onRelease() { }
+ }
+
+ /**
+ * Provides events in response to a discovery request.
+ */
+ public final class DiscoveryCallback {
+ private final ClientRecord mRecord;
+
+ DiscoveryCallback(ClientRecord record) {
+ mRecord = record;
+ }
+
+ /**
+ * Called by the service when a destination is found that
+ * offers one or more routes that satisfy the discovery request.
+ * <p>
+ * This method should be called whenever the list of available routes
+ * at a destination changes or whenever the properties of the destination
+ * itself change.
+ * </p>
+ *
+ * @param destination The destination that was found.
+ * @param routes The list of that destination's routes that satisfy the
+ * discovery request.
+ */
+ public void onDestinationFound(final @NonNull DestinationInfo destination,
+ final @NonNull List<RouteInfo> routes) {
+ if (destination == null) {
+ throw new IllegalArgumentException("destination must not be null");
+ }
+ if (routes == null) {
+ throw new IllegalArgumentException("routes must not be null");
+ }
+ for (int i = 0; i < routes.size(); i++) {
+ if (routes.get(i).getDestination() != destination) {
+ throw new IllegalArgumentException("routes must refer to the "
+ + "destination");
+ }
+ }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mRecord.dispatchDestinationFound(DiscoveryCallback.this,
+ destination, routes);
+ }
+ });
+ }
+
+ /**
+ * Called by the service when a destination is no longer
+ * reachable or is no longer offering any routes that satisfy
+ * the discovery request.
+ *
+ * @param destination The destination that went away.
+ */
+ public void onDestinationLost(final @NonNull DestinationInfo destination) {
+ if (destination == null) {
+ throw new IllegalArgumentException("destination must not be null");
+ }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mRecord.dispatchDestinationLost(DiscoveryCallback.this, destination);
+ }
+ });
+ }
+
+ /**
+ * Called by the service when a discovery has failed in a non-recoverable manner.
+ *
+ * @param error The error code: one of
+ * {@link MediaRouter#DISCOVERY_ERROR_UNKNOWN},
+ * {@link MediaRouter#DISCOVERY_ERROR_ABORTED},
+ * or {@link MediaRouter#DISCOVERY_ERROR_NO_CONNECTIVITY}.
+ * @param message The localized error message, or null if none. This message
+ * may be shown to the user.
+ * @param extras Additional information about the error which a client
+ * may use, or null if none.
+ */
+ public void onDiscoveryFailed(final @DiscoveryError int error,
+ final @Nullable CharSequence message, final @Nullable Bundle extras) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mRecord.dispatchDiscoveryFailed(DiscoveryCallback.this,
+ error, message, extras);
+ }
+ });
+ }
+ }
+
+ /**
+ * Provides events in response to a connection request.
+ */
+ public final class ConnectionCallback {
+ private final ClientRecord mRecord;
+
+ ConnectionCallback(ClientRecord record) {
+ mRecord = record;
+ }
+
+ /**
+ * Called by the service when the connection succeeds.
+ *
+ * @param connection Immutable information about the connection.
+ */
+ public void onConnected(final @NonNull ConnectionInfo connection) {
+ if (connection == null) {
+ throw new IllegalArgumentException("connection must not be null");
+ }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mRecord.dispatchConnected(ConnectionCallback.this, connection);
+ }
+ });
+ }
+
+ /**
+ * Called by the service when the connection is terminated normally.
+ * <p>
+ * Abnormal termination is reported via {@link #onConnectionFailed}.
+ * </p>
+ */
+ public void onDisconnected() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mRecord.dispatchDisconnected(ConnectionCallback.this);
+ }
+ });
+ }
+
+ /**
+ * Called by the service when a connection attempt or connection in
+ * progress has failed in a non-recoverable manner.
+ *
+ * @param error The error code: one of
+ * {@link MediaRouter#CONNECTION_ERROR_ABORTED},
+ * {@link MediaRouter#CONNECTION_ERROR_UNAUTHORIZED},
+ * {@link MediaRouter#CONNECTION_ERROR_UNREACHABLE},
+ * {@link MediaRouter#CONNECTION_ERROR_BUSY},
+ * {@link MediaRouter#CONNECTION_ERROR_TIMEOUT},
+ * {@link MediaRouter#CONNECTION_ERROR_BROKEN},
+ * or {@link MediaRouter#CONNECTION_ERROR_BARGED}.
+ * @param message The localized error message, or null if none. This message
+ * may be shown to the user.
+ * @param extras Additional information about the error which a client
+ * may use, or null if none.
+ */
+ public void onConnectionFailed(final @ConnectionError int error,
+ final @Nullable CharSequence message, final @Nullable Bundle extras) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mRecord.dispatchConnectionFailed(ConnectionCallback.this,
+ error, message, extras);
+ }
+ });
+ }
+ }
+
+ /**
+ * Identifies a client of the media route service.
+ */
+ public static final class ClientInfo {
+ private final int mUid;
+ private final String mPackageName;
+
+ ClientInfo(int uid, String packageName) {
+ mUid = uid;
+ mPackageName = packageName;
+ }
+
+ /**
+ * Gets the UID of the client application.
+ */
+ public int getUid() {
+ return mUid;
+ }
+
+ /**
+ * Gets the package name of the client application.
+ */
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
+
+ @Override
+ public @NonNull String toString() {
+ return "ClientInfo{ uid=" + mUid + ", package=" + mPackageName + " }";
+ }
+ }
+
+ private final class BinderService extends IMediaRouteService.Stub {
+ @Override
+ public void registerClient(final int clientUid, final String clientPackageName,
+ final IMediaRouteClientCallback callback) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ClientInfo client = new ClientInfo(clientUid, clientPackageName);
+ if (DEBUG) {
+ Log.d(TAG, "registerClient: client=" + client);
+ }
+
+ ClientSession session = onCreateClientSession(client);
+ if (session == null) {
+ // request refused by service
+ Log.w(TAG, "Media route service refused to create session for client: "
+ + "client=" + client);
+ return;
+ }
+
+ ClientRecord record = new ClientRecord(callback, client, session);
+ try {
+ callback.asBinder().linkToDeath(record, 0);
+ } catch (RemoteException ex) {
+ // client died prematurely
+ Log.w(TAG, "Client died prematurely while creating session: "
+ + "client=" + client);
+ record.release();
+ return;
+ }
+
+ mClientRecords.put(callback.asBinder(), record);
+ }
+ });
+ }
+
+ @Override
+ public void unregisterClient(IMediaRouteClientCallback callback) {
+ unregisterClient(callback, false);
+ }
+
+ void unregisterClient(final IMediaRouteClientCallback callback,
+ final boolean died) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ClientRecord record = mClientRecords.remove(callback.asBinder());
+ if (record == null) {
+ return; // spurious
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "unregisterClient: client=" + record.getClientInfo()
+ + ", died=" + died);
+ }
+
+ record.release();
+ callback.asBinder().unlinkToDeath(record, 0);
+ }
+ });
+ }
+
+ @Override
+ public void startDiscovery(final IMediaRouteClientCallback callback,
+ final int seq, final List<MediaRouteSelector> selectors,
+ final int flags) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ClientRecord record = mClientRecords.get(callback.asBinder());
+ if (record == null) {
+ return; // spurious
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "startDiscovery: client=" + record.getClientInfo()
+ + ", seq=" + seq + ", selectors=" + selectors
+ + ", flags=0x" + Integer.toHexString(flags));
+ }
+ record.startDiscovery(seq, selectors, flags);
+ }
+ });
+ }
+
+ @Override
+ public void stopDiscovery(final IMediaRouteClientCallback callback) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ClientRecord record = mClientRecords.get(callback.asBinder());
+ if (record == null) {
+ return; // spurious
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "stopDiscovery: client=" + record.getClientInfo());
+ }
+ record.stopDiscovery();
+ }
+ });
+ }
+
+ @Override
+ public void connect(final IMediaRouteClientCallback callback,
+ final int seq, final String destinationId, final String routeId,
+ final int flags, final Bundle extras) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ClientRecord record = mClientRecords.get(callback.asBinder());
+ if (record == null) {
+ return; // spurious
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "connect: client=" + record.getClientInfo()
+ + ", seq=" + seq + ", destinationId=" + destinationId
+ + ", routeId=" + routeId
+ + ", flags=0x" + Integer.toHexString(flags)
+ + ", extras=" + extras);
+ }
+ record.connect(seq, destinationId, routeId, flags, extras);
+ }
+ });
+ }
+
+ @Override
+ public void disconnect(final IMediaRouteClientCallback callback) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ClientRecord record = mClientRecords.get(callback.asBinder());
+ if (record == null) {
+ return; // spurious
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "disconnect: client=" + record.getClientInfo());
+ }
+ record.disconnect();
+ }
+ });
+ }
+
+ @Override
+ public void pauseStream(final IMediaRouteClientCallback callback) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ClientRecord record = mClientRecords.get(callback.asBinder());
+ if (record == null) {
+ return; // spurious
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "pauseStream: client=" + record.getClientInfo());
+ }
+ record.pauseStream();
+ }
+ });
+ }
+
+ @Override
+ public void resumeStream(final IMediaRouteClientCallback callback) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ClientRecord record = mClientRecords.get(callback.asBinder());
+ if (record == null) {
+ return; // spurious
+ }
+
+ if (DEBUG) {
+ Log.d(TAG, "resumeStream: client=" + record.getClientInfo());
+ }
+ record.resumeStream();
+ }
+ });
+ }
+ }
+
+ // Must be accessed on handler
+ private final class ClientRecord implements IBinder.DeathRecipient {
+ private final IMediaRouteClientCallback mClientCallback;
+ private final ClientInfo mClient;
+ private final ClientSession mSession;
+
+ private int mDiscoverySeq;
+ private DiscoveryRequest mDiscoveryRequest;
+ private DiscoveryCallback mDiscoveryCallback;
+ private final ArrayMap<String, DestinationRecord> mDestinations =
+ new ArrayMap<String, DestinationRecord>();
+
+ private int mConnectionSeq;
+ private ConnectionRequest mConnectionRequest;
+ private ConnectionCallback mConnectionCallback;
+ private ConnectionInfo mConnection;
+ private boolean mConnectionPaused;
+
+ public ClientRecord(IMediaRouteClientCallback callback,
+ ClientInfo client, ClientSession session) {
+ mClientCallback = callback;
+ mClient = client;
+ mSession = session;
+ }
+
+ // Invoked on binder thread unlike all other methods in this class.
+ @Override
+ public void binderDied() {
+ mService.unregisterClient(mClientCallback, true);
+ }
+
+ public ClientInfo getClientInfo() {
+ return mClient;
+ }
+
+ public void release() {
+ stopDiscovery();
+ disconnect();
+ }
+
+ public void startDiscovery(int seq, List<MediaRouteSelector> selectors,
+ int flags) {
+ stopDiscovery();
+
+ mDiscoverySeq = seq;
+ mDiscoveryRequest = new DiscoveryRequest(selectors);
+ mDiscoveryRequest.setFlags(flags);
+ mDiscoveryCallback = new DiscoveryCallback(this);
+ boolean started = mSession.onStartDiscovery(mDiscoveryRequest, mDiscoveryCallback);
+ if (!started) {
+ dispatchDiscoveryFailed(mDiscoveryCallback,
+ MediaRouter.DISCOVERY_ERROR_ABORTED, null, null);
+ clearDiscovery();
+ }
+ }
+
+ public void stopDiscovery() {
+ if (mDiscoveryRequest != null) {
+ mSession.onStopDiscovery();
+ clearDiscovery();
+ }
+ }
+
+ private void clearDiscovery() {
+ mDestinations.clear();
+ mDiscoveryRequest = null;
+ mDiscoveryCallback = null;
+ }
+
+ public void connect(int seq, String destinationId, String routeId,
+ int flags, Bundle extras) {
+ disconnect();
+
+ mConnectionSeq = seq;
+ mConnectionCallback = new ConnectionCallback(this);
+
+ DestinationRecord destinationRecord = mDestinations.get(destinationId);
+ if (destinationRecord == null) {
+ Log.w(TAG, "Aborting connection to route since no matching destination "
+ + "was found in the list of known destinations: "
+ + "destinationId=" + destinationId);
+ dispatchConnectionFailed(mConnectionCallback,
+ MediaRouter.CONNECTION_ERROR_ABORTED, null, null);
+ clearConnection();
+ return;
+ }
+
+ RouteInfo route = destinationRecord.getRoute(routeId);
+ if (route == null) {
+ Log.w(TAG, "Aborting connection to route since no matching route "
+ + "was found in the list of known routes: "
+ + "destination=" + destinationRecord.destination
+ + ", routeId=" + routeId);
+ dispatchConnectionFailed(mConnectionCallback,
+ MediaRouter.CONNECTION_ERROR_ABORTED, null, null);
+ clearConnection();
+ return;
+ }
+
+ mConnectionRequest = new ConnectionRequest(route);
+ mConnectionRequest.setFlags(flags);
+ mConnectionRequest.setExtras(extras);
+ boolean started = mSession.onConnect(mConnectionRequest, mConnectionCallback);
+ if (!started) {
+ dispatchConnectionFailed(mConnectionCallback,
+ MediaRouter.CONNECTION_ERROR_ABORTED, null, null);
+ clearConnection();
+ }
+ }
+
+ public void disconnect() {
+ if (mConnectionRequest != null) {
+ mSession.onDisconnect();
+ clearConnection();
+ }
+ }
+
+ private void clearConnection() {
+ mConnectionRequest = null;
+ mConnectionCallback = null;
+ if (mConnection != null) {
+ mConnection.close();
+ mConnection = null;
+ }
+ mConnectionPaused = false;
+ }
+
+ public void pauseStream() {
+ if (mConnectionRequest != null && !mConnectionPaused) {
+ mConnectionPaused = true;
+ mSession.onPauseStream();
+ }
+ }
+
+ public void resumeStream() {
+ if (mConnectionRequest != null && mConnectionPaused) {
+ mConnectionPaused = false;
+ mSession.onResumeStream();
+ }
+ }
+
+ public void dispatchDestinationFound(DiscoveryCallback callback,
+ DestinationInfo destination, List<RouteInfo> routes) {
+ if (callback == mDiscoveryCallback) {
+ if (DEBUG) {
+ Log.d(TAG, "destinationFound: destination=" + destination
+ + ", routes=" + routes);
+ }
+ mDestinations.put(destination.getId(),
+ new DestinationRecord(destination, routes));
+
+ ParcelableDestinationInfo pdi = new ParcelableDestinationInfo();
+ pdi.id = destination.getId();
+ pdi.name = destination.getName();
+ pdi.description = destination.getDescription();
+ pdi.iconResourceId = destination.getIconResourceId();
+ pdi.extras = destination.getExtras();
+ ArrayList<ParcelableRouteInfo> pris = new ArrayList<ParcelableRouteInfo>();
+ for (RouteInfo route : routes) {
+ int selectorIndex = mDiscoveryRequest.getSelectors().indexOf(
+ route.getSelector());
+ if (selectorIndex < 0) {
+ Log.w(TAG, "Ignoring route because the selector does not match "
+ + "any of those that were originally supplied by the "
+ + "client's discovery request: destination=" + destination
+ + ", route=" + route);
+ continue;
+ }
+
+ ParcelableRouteInfo pri = new ParcelableRouteInfo();
+ pri.id = route.getId();
+ pri.selectorIndex = selectorIndex;
+ pri.features = route.getFeatures();
+ pri.protocols = route.getProtocols().toArray(
+ new String[route.getProtocols().size()]);
+ pri.extras = route.getExtras();
+ pris.add(pri);
+ }
+ try {
+ mClientCallback.onDestinationFound(mDiscoverySeq, pdi,
+ pris.toArray(new ParcelableRouteInfo[pris.size()]));
+ } catch (RemoteException ex) {
+ // binder death handled elsewhere
+ }
+ }
+ }
+
+ public void dispatchDestinationLost(DiscoveryCallback callback,
+ DestinationInfo destination) {
+ if (callback == mDiscoveryCallback) {
+ if (DEBUG) {
+ Log.d(TAG, "destinationLost: destination=" + destination);
+ }
+
+ if (mDestinations.get(destination.getId()).destination == destination) {
+ mDestinations.remove(destination.getId());
+ try {
+ mClientCallback.onDestinationLost(mDiscoverySeq, destination.getId());
+ } catch (RemoteException ex) {
+ // binder death handled elsewhere
+ }
+ }
+ }
+ }
+
+ public void dispatchDiscoveryFailed(DiscoveryCallback callback,
+ int error, CharSequence message, Bundle extras) {
+ if (callback == mDiscoveryCallback) {
+ if (DEBUG) {
+ Log.d(TAG, "discoveryFailed: error=" + error + ", message=" + message
+ + ", extras=" + extras);
+ }
+
+ try {
+ mClientCallback.onDiscoveryFailed(mDiscoverySeq, error, message, extras);
+ } catch (RemoteException ex) {
+ // binder death handled elsewhere
+ }
+ }
+ }
+
+ public void dispatchConnected(ConnectionCallback callback, ConnectionInfo connection) {
+ if (callback == mConnectionCallback) {
+ if (DEBUG) {
+ Log.d(TAG, "connected: connection=" + connection);
+ }
+ if (mConnection == null) {
+ mConnection = connection;
+
+ ParcelableConnectionInfo pci = new ParcelableConnectionInfo();
+ pci.audioAttributes = connection.getAudioAttributes();
+ pci.presentationDisplayId = connection.getPresentationDisplay() != null ?
+ connection.getPresentationDisplay().getDisplayId() : -1;
+ pci.protocolBinders = new IBinder[connection.getProtocols().size()];
+ for (int i = 0; i < pci.protocolBinders.length; i++) {
+ pci.protocolBinders[i] = connection.getProtocolBinder(i);
+ }
+ pci.extras = connection.getExtras();
+ try {
+ mClientCallback.onConnected(mConnectionSeq, pci);
+ } catch (RemoteException ex) {
+ // binder death handled elsewhere
+ }
+ } else {
+ Log.w(TAG, "Media route service called onConnected() while already "
+ + "connected.");
+ }
+ }
+ }
+
+ public void dispatchDisconnected(ConnectionCallback callback) {
+ if (callback == mConnectionCallback) {
+ if (DEBUG) {
+ Log.d(TAG, "disconnected");
+ }
+
+ if (mConnection != null) {
+ mConnection.close();
+ mConnection = null;
+
+ try {
+ mClientCallback.onDisconnected(mConnectionSeq);
+ } catch (RemoteException ex) {
+ // binder death handled elsewhere
+ }
+ }
+ }
+ }
+
+ public void dispatchConnectionFailed(ConnectionCallback callback,
+ int error, CharSequence message, Bundle extras) {
+ if (callback == mConnectionCallback) {
+ if (DEBUG) {
+ Log.d(TAG, "connectionFailed: error=" + error + ", message=" + message
+ + ", extras=" + extras);
+ }
+
+ try {
+ mClientCallback.onConnectionFailed(mConnectionSeq, error, message, extras);
+ } catch (RemoteException ex) {
+ // binder death handled elsewhere
+ }
+ }
+ }
+ }
+
+ private static final class DestinationRecord {
+ public final DestinationInfo destination;
+ public final List<RouteInfo> routes;
+
+ public DestinationRecord(DestinationInfo destination, List<RouteInfo> routes) {
+ this.destination = destination;
+ this.routes = routes;
+ }
+
+ public RouteInfo getRoute(String routeId) {
+ final int count = routes.size();
+ for (int i = 0; i < count; i++) {
+ RouteInfo route = routes.get(i);
+ if (route.getId().equals(routeId)) {
+ return route;
+ }
+ }
+ return null;
+ }
+ }
+}
diff --git a/media/java/android/media/routing/MediaRouter.java b/media/java/android/media/routing/MediaRouter.java
new file mode 100644
index 0000000..4f6d324
--- /dev/null
+++ b/media/java/android/media/routing/MediaRouter.java
@@ -0,0 +1,1886 @@
+/*
+ * 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.
+ */
+package android.media.routing;
+
+import android.annotation.DrawableRes;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Presentation;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
+import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.media.VolumeProvider;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.view.Display;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Media router allows applications to discover, connect to, control,
+ * and send content to nearby media devices known as destinations.
+ * <p>
+ * There are generally two participants involved in media routing: an
+ * application that wants to send media content to a destination and a
+ * {@link MediaRouteService media route service} that provides the
+ * service of transporting that content where it needs to go on behalf of the
+ * application.
+ * </p><p>
+ * To send media content to a destination, the application must ask the system
+ * to discover available routes to destinations that provide certain capabilities,
+ * establish a connection to a route, then send messages through the connection to
+ * control the routing of audio and video streams, launch remote applications,
+ * and invoke other functions of the destination.
+ * </p><p>
+ * Media router objects are thread-safe.
+ * </p>
+ *
+ * <h3>Destinations</h3>
+ * <p>
+ * The media devices to which an application may send media content are referred
+ * to in the API as destinations. Each destination therefore represents a single
+ * independent device such as a speaker or TV set. Destinations are given meaningful
+ * names and descriptions to help the user associate them with devices in their
+ * environment.
+ * </p><p>
+ * Destinations may be local or remote and may be accessed through various means,
+ * often wirelessly. The user may install media route services to enable
+ * media applications to connect to a variety of destinations with different
+ * capabilities.
+ * </p>
+ *
+ * <h3>Routes</h3>
+ * <p>
+ * Routes represent possible usages or means of reaching and interacting with
+ * a destination. Since destinations may support many different features, they may
+ * each offer multiple routes for applications to choose from based on their needs.
+ * For example, one route might express the ability to stream locally rendered audio
+ * and video to the device; another route might express the ability to send a URL for
+ * the destination to download from the network and play all by itself.
+ * </p><p>
+ * Routes are discovered according to the set of capabilities that
+ * an application or the system is seeking to use at a particular time. For example,
+ * if an application wants to stream music to a destination then it will ask the
+ * {@link MediaRouter} to find routes to destinations can stream music and ignore
+ * all other destinations that cannot.
+ * </p><p>
+ * In general, the application will inspect the set of routes that have been
+ * offered then connect to the most appropriate route for its desired purpose.
+ * </p>
+ *
+ * <h3>Route Selection</h3>
+ * <p>
+ * When the user open the media route chooser activity, the system will display
+ * a list of nearby media destinations which have been discovered. After the
+ * choice is made the application may connect to one of the routes offered by
+ * this destination and begin communicating with the destination.
+ * </p><p>
+ * Destinations are located through a process called discovery. During discovery,
+ * the system will start installed {@link MediaRouteService media route services}
+ * to scan the network for nearby devices that offer the kinds of capabilities that the
+ * application is seeking to use. The application specifies the capabilities it requires by
+ * adding {@link MediaRouteSelector media route selectors} to the media router
+ * using the {@link #addSelector} method. Only destinations that provide routes
+ * which satisfy at least one of these media route selectors will be discovered.
+ * </p><p>
+ * Once the user has selected a destination, the application will be given a chance
+ * to choose one of the routes to which it would like to connect. The application
+ * may switch to a different route from the same destination at a later time but
+ * in order to connect to a new destination, the application must once again launch
+ * the media route chooser activity to ask the user to choose a destination.
+ * </p>
+ *
+ * <h3>Route Protocols</h3>
+ * <p>
+ * Route protocols express capabilities offered by routes. Each media route selector
+ * must specify at least one required protocol by which the routes will be selected.
+ * </p><p>
+ * The framework provides several predefined <code>MediaRouteProtocols</code> which are
+ * defined in the <code>android-support-media-protocols.jar</code> support library.
+ * Applications must statically link this library to make use of these protocols.
+ * </p><p>
+ * The static library approach is used to enable ongoing extension and refinement
+ * of protocols in the SDK and interoperability with the media router implementation
+ * for older platform versions which is offered by the framework support library.
+ * </p><p>
+ * Media route services may also define custom media route protocols of their own
+ * to enable applications to access specialized capabilities of certain destinations
+ * assuming they have linked in the required protocol code.
+ * </p><p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code> for more information.
+ * </p>
+ *
+ * <h3>Connections</h3>
+ * <p>
+ * After connecting to a media route, the application can send commands to
+ * the route using any of the protocols that it requested. If the route supports live
+ * audio or video streaming then the application can create an {@link AudioTrack} or
+ * {@link Presentation} to route locally generated content to the destination.
+ * </p>
+ *
+ * <h3>Delegation</h3>
+ * <p>
+ * The creator of the media router is responsible for establishing the policy for
+ * discovering and connecting to destinations. UI components may observe the state
+ * of the media router by {@link #createDelegate creating} a {@link Delegate}.
+ * </p><p>
+ * The media router should also be attached to the {@link MediaSession media session}
+ * that is handling media playback lifecycle. This will allow
+ * authorized {@link MediaController media controllers}, possibly running in other
+ * processes, to provide UI to examine and change the media destination by
+ * {@link MediaController#createMediaRouterDelegate creating} a {@link Delegate}
+ * for the media router associated with the session.
+ * </p>
+ */
+public final class MediaRouter {
+ private final DisplayManager mDisplayManager;
+
+ private final Object mLock = new Object();
+
+ private RoutingCallback mRoutingCallback;
+ private Handler mRoutingCallbackHandler;
+
+ private boolean mReleased;
+ private int mDiscoveryState;
+ private int mConnectionState;
+ private final ArrayList<MediaRouteSelector> mSelectors =
+ new ArrayList<MediaRouteSelector>();
+ private final ArrayMap<DestinationInfo, List<RouteInfo>> mDiscoveredDestinations =
+ new ArrayMap<DestinationInfo, List<RouteInfo>>();
+ private RouteInfo mSelectedRoute;
+ private ConnectionInfo mConnection;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = { DISCOVERY_STATE_STOPPED, DISCOVERY_STATE_STARTED })
+ public @interface DiscoveryState { }
+
+ /**
+ * Discovery state: Discovery is not currently in progress.
+ */
+ public static final int DISCOVERY_STATE_STOPPED = 0;
+
+ /**
+ * Discovery state: Discovery is being performed.
+ */
+ public static final int DISCOVERY_STATE_STARTED = 1;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = { DISCOVERY_FLAG_BACKGROUND })
+ public @interface DiscoveryFlags { }
+
+ /**
+ * Discovery flag: Indicates that the client has requested passive discovery in
+ * the background. The media route service should try to use less power and rely
+ * more on its internal caches to minimize its impact.
+ */
+ public static final int DISCOVERY_FLAG_BACKGROUND = 1 << 0;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = { DISCOVERY_ERROR_UNKNOWN, DISCOVERY_ERROR_ABORTED,
+ DISCOVERY_ERROR_NO_CONNECTIVITY })
+ public @interface DiscoveryError { }
+
+ /**
+ * Discovery error: Unknown error; refer to the error message for details.
+ */
+ public static final int DISCOVERY_ERROR_UNKNOWN = 0;
+
+ /**
+ * Discovery error: The media router or media route service has decided not to
+ * handle the discovery request for some reason.
+ */
+ public static final int DISCOVERY_ERROR_ABORTED = 1;
+
+ /**
+ * Discovery error: The media route service is unable to perform discovery
+ * due to a lack of connectivity such as because the radio is disabled.
+ */
+ public static final int DISCOVERY_ERROR_NO_CONNECTIVITY = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = { CONNECTION_STATE_DISCONNECTED, CONNECTION_STATE_CONNECTING,
+ CONNECTION_STATE_CONNECTED })
+ public @interface ConnectionState { }
+
+ /**
+ * Connection state: No destination has been selected. Media content should
+ * be sent to the default output.
+ */
+ public static final int CONNECTION_STATE_DISCONNECTED = 0;
+
+ /**
+ * Connection state: The application is in the process of connecting to
+ * a route offered by the selected destination.
+ */
+ public static final int CONNECTION_STATE_CONNECTING = 1;
+
+ /**
+ * Connection state: The application has connected to a route offered by
+ * the selected destination.
+ */
+ public static final int CONNECTION_STATE_CONNECTED = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = { CONNECTION_FLAG_BARGE })
+ public @interface ConnectionFlags { }
+
+ /**
+ * Connection flag: Indicates that the client has requested to barge in and evict
+ * other clients that might have already connected to the destination and that
+ * would otherwise prevent this client from connecting. When this flag is not
+ * set, the media route service should be polite and report
+ * {@link MediaRouter#CONNECTION_ERROR_BUSY} in case the destination is
+ * already occupied and cannot accept additional connections.
+ */
+ public static final int CONNECTION_FLAG_BARGE = 1 << 0;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = { CONNECTION_ERROR_UNKNOWN, CONNECTION_ERROR_ABORTED,
+ CONNECTION_ERROR_UNAUTHORIZED, CONNECTION_ERROR_UNAUTHORIZED,
+ CONNECTION_ERROR_BUSY, CONNECTION_ERROR_TIMEOUT, CONNECTION_ERROR_BROKEN })
+ public @interface ConnectionError { }
+
+ /**
+ * Connection error: Unknown error; refer to the error message for details.
+ */
+ public static final int CONNECTION_ERROR_UNKNOWN = 0;
+
+ /**
+ * Connection error: The media router or media route service has decided not to
+ * handle the connection request for some reason.
+ */
+ public static final int CONNECTION_ERROR_ABORTED = 1;
+
+ /**
+ * Connection error: The device has refused the connection from this client.
+ * This error should be avoided because the media route service should attempt
+ * to filter out devices that the client cannot access as it performs discovery
+ * on behalf of that client.
+ */
+ public static final int CONNECTION_ERROR_UNAUTHORIZED = 2;
+
+ /**
+ * Connection error: The device is unreachable over the network.
+ */
+ public static final int CONNECTION_ERROR_UNREACHABLE = 3;
+
+ /**
+ * Connection error: The device is already busy serving another client and
+ * the connection request did not ask to barge in.
+ */
+ public static final int CONNECTION_ERROR_BUSY = 4;
+
+ /**
+ * Connection error: A timeout occurred during connection.
+ */
+ public static final int CONNECTION_ERROR_TIMEOUT = 5;
+
+ /**
+ * Connection error: The connection to the device was severed unexpectedly.
+ */
+ public static final int CONNECTION_ERROR_BROKEN = 6;
+
+ /**
+ * Connection error: The connection was terminated because a different client barged
+ * in and took control of the destination.
+ */
+ public static final int CONNECTION_ERROR_BARGED = 7;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = { DISCONNECTION_REASON_APPLICATION_REQUEST,
+ DISCONNECTION_REASON_USER_REQUEST, DISCONNECTION_REASON_ERROR })
+ public @interface DisconnectionReason { }
+
+ /**
+ * Disconnection reason: The application requested disconnection itself.
+ */
+ public static final int DISCONNECTION_REASON_APPLICATION_REQUEST = 0;
+
+ /**
+ * Disconnection reason: The user requested disconnection.
+ */
+ public static final int DISCONNECTION_REASON_USER_REQUEST = 1;
+
+ /**
+ * Disconnection reason: An error occurred.
+ */
+ public static final int DISCONNECTION_REASON_ERROR = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = { ROUTE_FEATURE_LIVE_AUDIO, ROUTE_FEATURE_LIVE_VIDEO })
+ public @interface RouteFeatures { }
+
+ /**
+ * Route feature: Live audio.
+ * <p>
+ * A route that supports live audio streams audio rendered by the application
+ * to the destination.
+ * </p><p>
+ * To take advantage of live audio routing, the application must render its
+ * media using the audio attributes specified by {@link #getPreferredAudioAttributes}.
+ * </p>
+ *
+ * @see #getPreferredAudioAttributes
+ * @see android.media.AudioAttributes
+ */
+ public static final int ROUTE_FEATURE_LIVE_AUDIO = 1 << 0;
+
+ /**
+ * Route feature: Live video.
+ * <p>
+ * A route that supports live video streams video rendered by the application
+ * to the destination.
+ * </p><p>
+ * To take advantage of live video routing, the application must render its
+ * media to a {@link android.app.Presentation presentation window} on the
+ * display specified by {@link #getPreferredPresentationDisplay}.
+ * </p>
+ *
+ * @see #getPreferredPresentationDisplay
+ * @see android.app.Presentation
+ */
+ public static final int ROUTE_FEATURE_LIVE_VIDEO = 1 << 1;
+
+ /**
+ * Creates a media router.
+ *
+ * @param context The context with which the router is associated.
+ */
+ public MediaRouter(@NonNull Context context) {
+ if (context == null) {
+ throw new IllegalArgumentException("context must not be null");
+ }
+
+ mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+ }
+
+ /** @hide */
+ public IMediaRouter getBinder() {
+ // todo
+ return null;
+ }
+
+ /**
+ * Disconnects from the selected destination and releases the media router.
+ * <p>
+ * This method should be called by the application when it no longer requires
+ * the media router to ensure that all bound resources may be cleaned up.
+ * </p>
+ */
+ public void release() {
+ synchronized (mLock) {
+ mReleased = true;
+ // todo
+ }
+ }
+
+ /**
+ * Returns true if the media router has been released.
+ */
+ public boolean isReleased() {
+ synchronized (mLock) {
+ return mReleased;
+ }
+ }
+
+ /**
+ * Gets the current route discovery state.
+ *
+ * @return The current discovery state: one of {@link #DISCOVERY_STATE_STOPPED},
+ * {@link #DISCOVERY_STATE_STARTED}.
+ */
+ public @DiscoveryState int getDiscoveryState() {
+ synchronized (mLock) {
+ return mDiscoveryState;
+ }
+ }
+
+ /**
+ * Gets the current route connection state.
+ *
+ * @return The current state: one of {@link #CONNECTION_STATE_DISCONNECTED},
+ * {@link #CONNECTION_STATE_CONNECTING} or {@link #CONNECTION_STATE_CONNECTED}.
+ */
+ public @ConnectionState int getConnectionState() {
+ synchronized (mLock) {
+ return mConnectionState;
+ }
+ }
+
+ /**
+ * Creates a media router delegate through which the destination of the media
+ * router may be controlled.
+ * <p>
+ * This is the point of entry for UI code that initiates discovery and
+ * connection to routes.
+ * </p>
+ */
+ public @NonNull Delegate createDelegate() {
+ return null; // todo
+ }
+
+ /**
+ * Sets a callback to participate in route discovery, filtering, and connection
+ * establishment.
+ *
+ * @param callback The callback to set, or null if none.
+ * @param handler The handler to receive callbacks, or null to use the current thread.
+ */
+ public void setRoutingCallback(@Nullable RoutingCallback callback,
+ @Nullable Handler handler) {
+ synchronized (mLock) {
+ if (callback == null) {
+ mRoutingCallback = null;
+ mRoutingCallbackHandler = null;
+ } else {
+ mRoutingCallback = callback;
+ mRoutingCallbackHandler = handler != null ? handler : new Handler();
+ }
+ }
+ }
+
+ /**
+ * Adds a media route selector to use to find destinations that have
+ * routes with the specified capabilities during route discovery.
+ */
+ public void addSelector(@NonNull MediaRouteSelector selector) {
+ if (selector == null) {
+ throw new IllegalArgumentException("selector must not be null");
+ }
+
+ synchronized (mLock) {
+ if (!mSelectors.contains(selector)) {
+ mSelectors.add(selector);
+ // todo
+ }
+ }
+ }
+
+ /**
+ * Removes a media route selector.
+ */
+ public void removeSelector(@NonNull MediaRouteSelector selector) {
+ if (selector == null) {
+ throw new IllegalArgumentException("selector must not be null");
+ }
+
+ synchronized (mLock) {
+ if (mSelectors.remove(selector)) {
+ // todo
+ }
+ }
+ }
+
+ /**
+ * Removes all media route selectors.
+ * <p>
+ * Note that at least one selector must be added in order to perform discovery.
+ * </p>
+ */
+ public void clearSelectors() {
+ synchronized (mLock) {
+ if (!mSelectors.isEmpty()) {
+ mSelectors.clear();
+ // todo
+ }
+ }
+ }
+
+ /**
+ * Gets a list of all media route selectors to consider during discovery.
+ */
+ public @NonNull List<MediaRouteSelector> getSelectors() {
+ synchronized (mLock) {
+ return new ArrayList<MediaRouteSelector>(mSelectors);
+ }
+ }
+
+ /**
+ * Gets the connection to the currently selected route.
+ *
+ * @return The connection to the currently selected route, or null if not connected.
+ */
+ public @NonNull ConnectionInfo getConnection() {
+ synchronized (mLock) {
+ return mConnection;
+ }
+ }
+
+ /**
+ * Gets the list of discovered destinations.
+ * <p>
+ * This list is only valid while discovery is running and is null otherwise.
+ * </p>
+ *
+ * @return The list of discovered destinations, or null if discovery is not running.
+ */
+ public @NonNull List<DestinationInfo> getDiscoveredDestinations() {
+ synchronized (mLock) {
+ if (mDiscoveryState == DISCOVERY_STATE_STARTED) {
+ return new ArrayList<DestinationInfo>(mDiscoveredDestinations.keySet());
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Gets the list of discovered routes for a particular destination.
+ * <p>
+ * This list is only valid while discovery is running and is null otherwise.
+ * </p>
+ *
+ * @param destination The destination for which to get the list of discovered routes.
+ * @return The list of discovered routes for the destination, or null if discovery
+ * is not running.
+ */
+ public @NonNull List<RouteInfo> getDiscoveredRoutes(@NonNull DestinationInfo destination) {
+ if (destination == null) {
+ throw new IllegalArgumentException("destination must not be null");
+ }
+ synchronized (mLock) {
+ if (mDiscoveryState == DISCOVERY_STATE_STARTED) {
+ List<RouteInfo> routes = mDiscoveredDestinations.get(destination);
+ if (routes != null) {
+ return new ArrayList<RouteInfo>(routes);
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Gets the destination that has been selected.
+ *
+ * @return The selected destination, or null if disconnected.
+ */
+ public @Nullable DestinationInfo getSelectedDestination() {
+ synchronized (mLock) {
+ return mSelectedRoute != null ? mSelectedRoute.getDestination() : null;
+ }
+ }
+
+ /**
+ * Gets the route that has been selected.
+ *
+ * @return The selected destination, or null if disconnected.
+ */
+ public @Nullable RouteInfo getSelectedRoute() {
+ synchronized (mLock) {
+ return mSelectedRoute;
+ }
+ }
+
+ /**
+ * Gets the preferred audio attributes that should be used to stream live audio content
+ * based on the connected route.
+ * <p>
+ * Use an {@link AudioTrack} to send audio content to the destination with these
+ * audio attributes.
+ * </p><p>
+ * The preferred audio attributes may change when a connection is established but it
+ * will remain constant until disconnected.
+ * </p>
+ *
+ * @return The preferred audio attributes to use. When connected, returns the
+ * route's audio attributes or null if it does not support live audio streaming.
+ * Otherwise returns audio attributes associated with {@link AudioAttributes#USAGE_MEDIA}.
+ */
+ public @Nullable AudioAttributes getPreferredAudioAttributes() {
+ synchronized (mLock) {
+ if (mConnection != null) {
+ return mConnection.getAudioAttributes();
+ }
+ return new AudioAttributes.Builder()
+ .setLegacyStreamType(AudioManager.STREAM_MUSIC)
+ .build();
+ }
+ }
+
+ /**
+ * Gets the preferred presentation display that should be used to stream live video content
+ * based on the connected route.
+ * <p>
+ * Use a {@link Presentation} to send video content to the destination with this display.
+ * </p><p>
+ * The preferred presentation display may change when a connection is established but it
+ * will remain constant until disconnected.
+ * </p>
+ *
+ * @return The preferred presentation display to use. When connected, returns
+ * the route's presentation display or null if it does not support live video
+ * streaming. Otherwise returns the first available
+ * {@link DisplayManager#DISPLAY_CATEGORY_PRESENTATION presentation display},
+ * such as a mirrored wireless or HDMI display or null if none.
+ */
+ public @Nullable Display getPreferredPresentationDisplay() {
+ synchronized (mLock) {
+ if (mConnection != null) {
+ return mConnection.getPresentationDisplay();
+ }
+ Display[] displays = mDisplayManager.getDisplays(
+ DisplayManager.DISPLAY_CATEGORY_PRESENTATION);
+ return displays.length != 0 ? displays[0] : null;
+ }
+ }
+
+ /**
+ * Gets the preferred volume provider that should be used to control the volume
+ * of content rendered on the currently selected route.
+ * <p>
+ * The preferred volume provider may change when a connection is established but it
+ * will remain the same until disconnected.
+ * </p>
+ *
+ * @return The preferred volume provider to use, or null if the currently
+ * selected route does not support remote volume adjustment or if the connection
+ * is not yet established. If no route is selected, returns null to indicate
+ * that system volume control should be used.
+ */
+ public @Nullable VolumeProvider getPreferredVolumeProvider() {
+ synchronized (mLock) {
+ if (mConnection != null) {
+ return mConnection.getVolumeProvider();
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Requests to pause streaming of live audio or video routes.
+ * Should be called when the application is going into the background and is
+ * no longer rendering content locally.
+ * <p>
+ * This method does nothing unless a connection has been established.
+ * </p>
+ */
+ public void pauseStream() {
+ // todo
+ }
+
+ /**
+ * Requests to resume streaming of live audio or video routes.
+ * May be called when the application is returning to the foreground and is
+ * about to resume rendering content locally.
+ * <p>
+ * This method does nothing unless a connection has been established.
+ * </p>
+ */
+ public void resumeStream() {
+ // todo
+ }
+
+ /**
+ * This class is used by UI components to let the user discover and
+ * select a destination to which the media router should connect.
+ * <p>
+ * This API has somewhat more limited functionality than the {@link MediaRouter}
+ * itself because it is designed to allow applications to control
+ * the destination of media router instances that belong to other processes.
+ * </p><p>
+ * To control the destination of your own media router, call
+ * {@link #createDelegate} to obtain a local delegate object.
+ * </p><p>
+ * To control the destination of a media router that belongs to another process,
+ * first obtain a {@link MediaController} that is associated with the media playback
+ * that is occurring in that process, then call
+ * {@link MediaController#createMediaRouterDelegate} to obtain an instance of
+ * its destination controls. Note that special permissions may be required to
+ * obtain the {@link MediaController} instance in the first place.
+ * </p>
+ */
+ public static final class Delegate {
+ /**
+ * Returns true if the media router has been released.
+ */
+ public boolean isReleased() {
+ // todo
+ return false;
+ }
+
+ /**
+ * Gets the current route discovery state.
+ *
+ * @return The current discovery state: one of {@link #DISCOVERY_STATE_STOPPED},
+ * {@link #DISCOVERY_STATE_STARTED}.
+ */
+ public @DiscoveryState int getDiscoveryState() {
+ // todo
+ return -1;
+ }
+
+ /**
+ * Gets the current route connection state.
+ *
+ * @return The current state: one of {@link #CONNECTION_STATE_DISCONNECTED},
+ * {@link #CONNECTION_STATE_CONNECTING} or {@link #CONNECTION_STATE_CONNECTED}.
+ */
+ public @ConnectionState int getConnectionState() {
+ // todo
+ return -1;
+ }
+
+ /**
+ * Gets the currently selected destination.
+ *
+ * @return The destination information, or null if none.
+ */
+ public @Nullable DestinationInfo getSelectedDestination() {
+ return null;
+ }
+
+ /**
+ * Gets the list of discovered destinations.
+ * <p>
+ * This list is only valid while discovery is running and is null otherwise.
+ * </p>
+ *
+ * @return The list of discovered destinations, or null if discovery is not running.
+ */
+ public @NonNull List<DestinationInfo> getDiscoveredDestinations() {
+ return null;
+ }
+
+ /**
+ * Adds a callback to receive state changes.
+ *
+ * @param callback The callback to set, or null if none.
+ * @param handler The handler to receive callbacks, or null to use the current thread.
+ */
+ public void addStateCallback(@Nullable StateCallback callback,
+ @Nullable Handler handler) {
+ if (callback == null) {
+ throw new IllegalArgumentException("callback must not be null");
+ }
+ if (handler == null) {
+ handler = new Handler();
+ }
+ // todo
+ }
+
+ /**
+ * Removes a callback for state changes.
+ *
+ * @param callback The callback to set, or null if none.
+ */
+ public void removeStateCallback(@Nullable StateCallback callback) {
+ // todo
+ }
+
+ /**
+ * Starts performing discovery.
+ * <p>
+ * Performing discovery is expensive. Make sure to call {@link #stopDiscovery}
+ * as soon as possible once a new destination has been selected to allow the system
+ * to stop services associated with discovery.
+ * </p>
+ *
+ * @param flags The discovery flags, such as {@link MediaRouter#DISCOVERY_FLAG_BACKGROUND}.
+ */
+ public void startDiscovery(@DiscoveryFlags int flags) {
+ // todo
+ }
+
+ /**
+ * Stops performing discovery.
+ */
+ public void stopDiscovery() {
+ // todo
+ }
+
+ /**
+ * Connects to a destination during route discovery.
+ * <p>
+ * This method may only be called while route discovery is active and the
+ * destination appears in the
+ * {@link #getDiscoveredDestinations list of discovered destinations}.
+ * If the media router is already connected to a route then it will first disconnect
+ * from the current route then connect to the new route.
+ * </p>
+ *
+ * @param destination The destination to which the media router should connect.
+ * @param flags The connection flags, such as {@link MediaRouter#CONNECTION_FLAG_BARGE}.
+ */
+ public void connect(@NonNull DestinationInfo destination, @DiscoveryFlags int flags) {
+ // todo
+ }
+
+ /**
+ * Disconnects from the currently selected destination.
+ * <p>
+ * Does nothing if not currently connected.
+ * </p>
+ *
+ * @param reason The reason for the disconnection: one of
+ * {@link #DISCONNECTION_REASON_APPLICATION_REQUEST},
+ * {@link #DISCONNECTION_REASON_USER_REQUEST}, or {@link #DISCONNECTION_REASON_ERROR}.
+ */
+ public void disconnect(@DisconnectionReason int reason) {
+ // todo
+ }
+ }
+
+ /**
+ * Describes immutable properties of a connection to a route.
+ */
+ public static final class ConnectionInfo {
+ private final RouteInfo mRoute;
+ private final AudioAttributes mAudioAttributes;
+ private final Display mPresentationDisplay;
+ private final VolumeProvider mVolumeProvider;
+ private final IBinder[] mProtocolBinders;
+ private final Object[] mProtocolInstances;
+ private final Bundle mExtras;
+ private final ArrayList<Closeable> mCloseables;
+
+ private static final Class<?>[] MEDIA_ROUTE_PROTOCOL_CTOR_PARAMETERS =
+ new Class<?>[] { IBinder.class };
+
+ ConnectionInfo(RouteInfo route,
+ AudioAttributes audioAttributes, Display display,
+ VolumeProvider volumeProvider, IBinder[] protocolBinders,
+ Bundle extras, ArrayList<Closeable> closeables) {
+ mRoute = route;
+ mAudioAttributes = audioAttributes;
+ mPresentationDisplay = display;
+ mVolumeProvider = volumeProvider;
+ mProtocolBinders = protocolBinders;
+ mProtocolInstances = new Object[mProtocolBinders.length];
+ mExtras = extras;
+ mCloseables = closeables;
+ }
+
+ /**
+ * Gets the route that is connected.
+ */
+ public @NonNull RouteInfo getRoute() {
+ return mRoute;
+ }
+
+ /**
+ * Gets the audio attributes which the client should use to stream audio
+ * to the destination, or null if the route does not support live audio streaming.
+ */
+ public @Nullable AudioAttributes getAudioAttributes() {
+ return mAudioAttributes;
+ }
+
+ /**
+ * Gets the display which the client should use to stream video to the
+ * destination using a {@link Presentation}, or null if the route does not
+ * support live video streaming.
+ */
+ public @Nullable Display getPresentationDisplay() {
+ return mPresentationDisplay;
+ }
+
+ /**
+ * Gets the route's volume provider, or null if none.
+ */
+ public @Nullable VolumeProvider getVolumeProvider() {
+ return mVolumeProvider;
+ }
+
+ /**
+ * Gets the set of supported route features.
+ */
+ public @RouteFeatures int getFeatures() {
+ return mRoute.getFeatures();
+ }
+
+ /**
+ * Gets the list of supported route protocols.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ */
+ public @NonNull List<String> getProtocols() {
+ return mRoute.getProtocols();
+ }
+
+ /**
+ * Gets an instance of a route protocol object that wraps the protocol binder
+ * and provides easy access to the protocol's functionality.
+ * <p>
+ * This is a convenience method which invokes {@link #getProtocolBinder(String)}
+ * using the name of the provided class then passes the resulting {@link IBinder}
+ * to a single-argument constructor of that class.
+ * </p><p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ */
+ @SuppressWarnings("unchecked")
+ public @Nullable <T> T getProtocolObject(Class<T> clazz) {
+ int index = getProtocols().indexOf(clazz.getName());
+ if (index < 0) {
+ return null;
+ }
+ if (mProtocolInstances[index] == null && mProtocolBinders[index] != null) {
+ final Constructor<T> ctor;
+ try {
+ ctor = clazz.getConstructor(MEDIA_ROUTE_PROTOCOL_CTOR_PARAMETERS);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException("Could not find public constructor "
+ + "with IBinder argument in protocol class: " + clazz.getName(), ex);
+ }
+ try {
+ mProtocolInstances[index] = ctor.newInstance(mProtocolBinders[index]);
+ } catch (InstantiationException | IllegalAccessException
+ | InvocationTargetException ex) {
+ throw new RuntimeException("Could create instance of protocol class: "
+ + clazz.getName(), ex);
+ }
+ }
+ return (T)mProtocolInstances[index];
+ }
+
+ /**
+ * Gets the {@link IBinder} that provides access to the specified route protocol
+ * or null if the protocol is not supported.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ */
+ public @Nullable IBinder getProtocolBinder(@NonNull String name) {
+ int index = getProtocols().indexOf(name);
+ return index >= 0 ? mProtocolBinders[index] : null;
+ }
+
+ /**
+ * Gets the {@link IBinder} that provides access to the specified route protocol
+ * at the given index in the protocol list or null if the protocol is not supported.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ */
+ public @Nullable IBinder getProtocolBinder(int index) {
+ return mProtocolBinders[index];
+ }
+
+ /**
+ * Gets optional extra media route service or protocol specific information about
+ * the connection. Use the service or protocol name as the prefix for
+ * any extras to avoid namespace collisions.
+ */
+ public @Nullable Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Closes all closeables associated with the connection when the connection
+ * is being torn down.
+ */
+ void close() {
+ final int count = mCloseables.size();
+ for (int i = 0; i < count; i++) {
+ try {
+ mCloseables.get(i).close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+
+ @Override
+ public @NonNull String toString() {
+ return "ConnectionInfo{ route=" + mRoute
+ + ", audioAttributes=" + mAudioAttributes
+ + ", presentationDisplay=" + mPresentationDisplay
+ + ", volumeProvider=" + mVolumeProvider
+ + ", protocolBinders=" + mProtocolBinders + " }";
+ }
+
+ /**
+ * Builds {@link ConnectionInfo} objects.
+ */
+ public static final class Builder {
+ private final RouteInfo mRoute;
+ private AudioAttributes mAudioAttributes;
+ private Display mPresentationDisplay;
+ private VolumeProvider mVolumeProvider;
+ private final IBinder[] mProtocols;
+ private Bundle mExtras;
+ private final ArrayList<Closeable> mCloseables = new ArrayList<Closeable>();
+
+ /**
+ * Creates a builder for connection information.
+ *
+ * @param route The route that is connected.
+ */
+ public Builder(@NonNull RouteInfo route) {
+ if (route == null) {
+ throw new IllegalArgumentException("route");
+ }
+ mRoute = route;
+ mProtocols = new IBinder[route.getProtocols().size()];
+ }
+
+ /**
+ * Sets the audio attributes which the client should use to stream audio
+ * to the destination, or null if the route does not support live audio streaming.
+ */
+ public @NonNull Builder setAudioAttributes(
+ @Nullable AudioAttributes audioAttributes) {
+ mAudioAttributes = audioAttributes;
+ return this;
+ }
+
+ /**
+ * Sets the display which the client should use to stream video to the
+ * destination using a {@link Presentation}, or null if the route does not
+ * support live video streaming.
+ */
+ public @NonNull Builder setPresentationDisplay(@Nullable Display display) {
+ mPresentationDisplay = display;
+ return this;
+ }
+
+ /**
+ * Sets the route's volume provider, or null if none.
+ */
+ public @NonNull Builder setVolumeProvider(@Nullable VolumeProvider provider) {
+ mVolumeProvider = provider;
+ return this;
+ }
+
+ /**
+ * Sets the binder stub of a supported route protocol using
+ * the protocol's fully qualified class name. The protocol must be one
+ * of those that was indicated as being supported by the route.
+ * <p>
+ * If the stub implements {@link Closeable} then it will automatically
+ * be closed when the client disconnects from the route.
+ * </p><p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ */
+ public @NonNull Builder setProtocolStub(@NonNull Class<?> clazz,
+ @NonNull IInterface stub) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("clazz must not be null");
+ }
+ if (stub == null) {
+ throw new IllegalArgumentException("stub must not be null");
+ }
+ if (stub instanceof Closeable) {
+ mCloseables.add((Closeable)stub);
+ }
+ return setProtocolBinder(clazz.getName(), stub.asBinder());
+ }
+
+ /**
+ * Sets the binder interface of a supported route protocol by name.
+ * The protocol must be one of those that was indicated as being supported
+ * by the route.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ */
+ public @NonNull Builder setProtocolBinder(@NonNull String name,
+ @NonNull IBinder binder) {
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name must not be null or empty");
+ }
+ if (binder == null) {
+ throw new IllegalArgumentException("binder must not be null");
+ }
+ int index = mRoute.getProtocols().indexOf(name);
+ if (index < 0) {
+ throw new IllegalArgumentException("name must specify a protocol that "
+ + "the route actually declared that it supports: "
+ + "name=" + name + ", protocols=" + mRoute.getProtocols());
+ }
+ mProtocols[index] = binder;
+ return this;
+ }
+
+ /**
+ * Sets optional extra media route service or protocol specific information about
+ * the connection. Use the service or protocol name as the prefix for
+ * any extras to avoid namespace collisions.
+ */
+ public @NonNull Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
+ * Builds the {@link ConnectionInfo} object.
+ */
+ public @NonNull ConnectionInfo build() {
+ return new ConnectionInfo(mRoute,
+ mAudioAttributes, mPresentationDisplay,
+ mVolumeProvider, mProtocols, mExtras, mCloseables);
+ }
+ }
+ }
+
+ /**
+ * Describes one particular way of routing media content to a destination
+ * according to the capabilities specified by a media route selector on behalf
+ * of an application.
+ */
+ public static final class RouteInfo {
+ private final String mId;
+ private final DestinationInfo mDestination;
+ private final MediaRouteSelector mSelector;
+ private final int mFeatures;
+ private final ArrayList<String> mProtocols;
+ private final Bundle mExtras;
+
+ RouteInfo(String id, DestinationInfo destination, MediaRouteSelector selector,
+ int features, ArrayList<String> protocols, Bundle extras) {
+ mId = id;
+ mDestination = destination;
+ mSelector = selector;
+ mFeatures = features;
+ mProtocols = protocols;
+ mExtras = extras;
+ }
+
+ /**
+ * Gets the route's stable identifier.
+ * <p>
+ * The id is intended to uniquely identify the route among all routes that
+ * are offered by a particular destination in such a way that the client can
+ * refer to it at a later time.
+ * </p>
+ */
+ public @NonNull String getId() {
+ return mId;
+ }
+
+ /**
+ * Gets the destination that is offering this route.
+ */
+ public @NonNull DestinationInfo getDestination() {
+ return mDestination;
+ }
+
+ /**
+ * Gets the media route selector provided by the client for which this
+ * route was created.
+ * <p>
+ * It is implied that this route supports all of the required capabilities
+ * that were expressed in the selector.
+ * </p>
+ */
+ public @NonNull MediaRouteSelector getSelector() {
+ return mSelector;
+ }
+
+ /**
+ * Gets the set of supported route features.
+ */
+ public @RouteFeatures int getFeatures() {
+ return mFeatures;
+ }
+
+ /**
+ * Gets the list of supported route protocols.
+ * <p>
+ * Refer to <code>android.support.media.protocols.MediaRouteProtocol</code>
+ * for more information.
+ * </p>
+ */
+ public @NonNull List<String> getProtocols() {
+ return mProtocols;
+ }
+
+ /**
+ * Gets optional extra information about the route, or null if none.
+ */
+ public @Nullable Bundle getExtras() {
+ return mExtras;
+ }
+
+ @Override
+ public @NonNull String toString() {
+ return "RouteInfo{ id=" + mId + ", destination=" + mDestination
+ + ", features=0x" + Integer.toHexString(mFeatures)
+ + ", selector=" + mSelector + ", protocols=" + mProtocols
+ + ", extras=" + mExtras + " }";
+ }
+
+ /**
+ * Builds {@link RouteInfo} objects.
+ */
+ public static final class Builder {
+ private final DestinationInfo mDestination;
+ private final String mId;
+ private final MediaRouteSelector mSelector;
+ private int mFeatures;
+ private final ArrayList<String> mProtocols = new ArrayList<String>();
+ private Bundle mExtras;
+
+ /**
+ * Creates a builder for route information.
+ *
+ * @param id The route's stable identifier.
+ * @param destination The destination of this route.
+ * @param selector The media route selector provided by the client for which
+ * this route was created. This must be one of the selectors that was
+ * included in the discovery request.
+ */
+ public Builder(@NonNull String id, @NonNull DestinationInfo destination,
+ @NonNull MediaRouteSelector selector) {
+ if (TextUtils.isEmpty(id)) {
+ throw new IllegalArgumentException("id must not be null or empty");
+ }
+ if (destination == null) {
+ throw new IllegalArgumentException("destination must not be null");
+ }
+ if (selector == null) {
+ throw new IllegalArgumentException("selector must not be null");
+ }
+ mDestination = destination;
+ mId = id;
+ mSelector = selector;
+ }
+
+ /**
+ * Sets the set of supported route features.
+ */
+ public @NonNull Builder setFeatures(@RouteFeatures int features) {
+ mFeatures = features;
+ return this;
+ }
+
+ /**
+ * Adds a supported route protocol using its fully qualified class name.
+ * <p>
+ * If the protocol was not requested by the client in its selector
+ * then it will be silently discarded.
+ * </p>
+ */
+ public @NonNull <T extends IInterface> Builder addProtocol(@NonNull Class<T> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("clazz must not be null");
+ }
+ return addProtocol(clazz.getName());
+ }
+
+ /**
+ * Adds a supported route protocol by name.
+ * <p>
+ * If the protocol was not requested by the client in its selector
+ * then it will be silently discarded.
+ * </p>
+ */
+ public @NonNull Builder addProtocol(@NonNull String name) {
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name must not be null");
+ }
+ if (mSelector.containsProtocol(name)) {
+ mProtocols.add(name);
+ }
+ return this;
+ }
+
+ /**
+ * Sets optional extra information about the route, or null if none.
+ */
+ public @NonNull Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
+ * Builds the {@link RouteInfo} object.
+ * <p>
+ * Ensures that all required protocols have been supplied.
+ * </p>
+ */
+ public @NonNull RouteInfo build() {
+ int missingFeatures = mSelector.getRequiredFeatures() & ~mFeatures;
+ if (missingFeatures != 0) {
+ throw new IllegalStateException("The media route selector "
+ + "specified required features which this route does "
+ + "not appear to support so it should not have been published: "
+ + "missing 0x" + Integer.toHexString(missingFeatures));
+ }
+ for (String protocol : mSelector.getRequiredProtocols()) {
+ if (!mProtocols.contains(protocol)) {
+ throw new IllegalStateException("The media route selector "
+ + "specified required protocols which this route "
+ + "does not appear to support so it should not have "
+ + "been published: missing " + protocol);
+ }
+ }
+ return new RouteInfo(mId, mDestination, mSelector,
+ mFeatures, mProtocols, mExtras);
+ }
+ }
+ }
+
+ /**
+ * Describes a destination for media content such as a device,
+ * an individual port on a device, or a group of devices.
+ */
+ public static final class DestinationInfo {
+ private final String mId;
+ private final ServiceMetadata mService;
+ private final CharSequence mName;
+ private final CharSequence mDescription;
+ private final int mIconResourceId;
+ private final Bundle mExtras;
+
+ DestinationInfo(String id, ServiceMetadata service,
+ CharSequence name, CharSequence description,
+ int iconResourceId, Bundle extras) {
+ mId = id;
+ mService = service;
+ mName = name;
+ mDescription = description;
+ mIconResourceId = iconResourceId;
+ mExtras = extras;
+ }
+
+ /**
+ * Gets the destination's stable identifier.
+ * <p>
+ * The id is intended to uniquely identify the destination among all destinations
+ * provided by the media route service in such a way that the client can
+ * refer to it at a later time. Ideally, the id should be resilient to
+ * user-initiated actions such as changes to the name or description
+ * of the destination.
+ * </p>
+ */
+ public @NonNull String getId() {
+ return mId;
+ }
+
+ /**
+ * Gets metadata about the service that is providing access to this destination.
+ */
+ public @NonNull ServiceMetadata getServiceMetadata() {
+ return mService;
+ }
+
+ /**
+ * Gets the destination's name for display to the user.
+ */
+ public @NonNull CharSequence getName() {
+ return mName;
+ }
+
+ /**
+ * Gets the destination's description for display to the user, or null if none.
+ */
+ public @Nullable CharSequence getDescription() {
+ return mDescription;
+ }
+
+ /**
+ * Gets an icon resource from the service's package which is used
+ * to identify the destination, or -1 if none.
+ */
+ public @DrawableRes int getIconResourceId() {
+ return mIconResourceId;
+ }
+
+ /**
+ * Loads the icon drawable, or null if none.
+ */
+ public @Nullable Drawable loadIcon(@NonNull PackageManager pm) {
+ return mIconResourceId >= 0 ? mService.getDrawable(pm, mIconResourceId) : null;
+ }
+
+ /**
+ * Gets optional extra information about the destination, or null if none.
+ */
+ public @Nullable Bundle getExtras() {
+ return mExtras;
+ }
+
+ @Override
+ public @NonNull String toString() {
+ return "DestinationInfo{ id=" + mId + ", service=" + mService + ", name=" + mName
+ + ", description=" + mDescription + ", iconResourceId=" + mIconResourceId
+ + ", extras=" + mExtras + " }";
+ }
+
+ /**
+ * Builds {@link DestinationInfo} objects.
+ */
+ public static final class Builder {
+ private final String mId;
+ private final ServiceMetadata mService;
+ private final CharSequence mName;
+ private CharSequence mDescription;
+ private int mIconResourceId = -1;
+ private Bundle mExtras;
+
+ /**
+ * Creates a builder for destination information.
+ *
+ * @param id The destination's stable identifier.
+ * @param service Metatada about the service that is providing access to
+ * this destination.
+ * @param name The destination's name for display to the user.
+ */
+ public Builder(@NonNull String id, @NonNull ServiceMetadata service,
+ @NonNull CharSequence name) {
+ if (TextUtils.isEmpty(id)) {
+ throw new IllegalArgumentException("id must not be null or empty");
+ }
+ if (service == null) {
+ throw new IllegalArgumentException("service must not be null");
+ }
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name must not be null or empty");
+ }
+ mId = id;
+ mService = service;
+ mName = name;
+ }
+
+ /**
+ * Sets the destination's description for display to the user, or null if none.
+ */
+ public @NonNull Builder setDescription(@Nullable CharSequence description) {
+ mDescription = description;
+ return this;
+ }
+
+ /**
+ * Sets an icon resource from this package used to identify the destination,
+ * or -1 if none.
+ */
+ public @NonNull Builder setIconResourceId(@DrawableRes int resid) {
+ mIconResourceId = resid;
+ return this;
+ }
+
+ /**
+ * Gets optional extra information about the destination, or null if none.
+ */
+ public @NonNull Builder setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ return this;
+ }
+
+ /**
+ * Builds the {@link DestinationInfo} object.
+ */
+ public @NonNull DestinationInfo build() {
+ return new DestinationInfo(mId, mService, mName, mDescription,
+ mIconResourceId, mExtras);
+ }
+ }
+ }
+
+ /**
+ * Describes metadata about a {@link MediaRouteService} which is providing
+ * access to certain kinds of destinations.
+ */
+ public static final class ServiceMetadata {
+ private final ServiceInfo mService;
+ private CharSequence mLabel;
+ private Drawable mIcon;
+
+ ServiceMetadata(Service service) throws NameNotFoundException {
+ mService = service.getPackageManager().getServiceInfo(
+ new ComponentName(service, service.getClass()),
+ PackageManager.GET_META_DATA);
+ }
+
+ ServiceMetadata(ServiceInfo service) {
+ mService = service;
+ }
+
+ /**
+ * Gets the service's component information including it name, label and icon.
+ */
+ public @NonNull ServiceInfo getService() {
+ return mService;
+ }
+
+ /**
+ * Gets the service's component name.
+ */
+ public @NonNull ComponentName getComponentName() {
+ return new ComponentName(mService.packageName, mService.name);
+ }
+
+ /**
+ * Gets the service's package name.
+ */
+ public @NonNull String getPackageName() {
+ return mService.packageName;
+ }
+
+ /**
+ * Gets the service's name for display to the user, or null if none.
+ */
+ public @NonNull CharSequence getLabel(@NonNull PackageManager pm) {
+ if (mLabel == null) {
+ mLabel = mService.loadLabel(pm);
+ }
+ return mLabel;
+ }
+
+ /**
+ * Gets the icon drawable, or null if none.
+ */
+ public @Nullable Drawable getIcon(@NonNull PackageManager pm) {
+ if (mIcon == null) {
+ mIcon = mService.loadIcon(pm);
+ }
+ return mIcon;
+ }
+
+ // TODO: add service metadata
+
+ Drawable getDrawable(PackageManager pm, int resid) {
+ return pm.getDrawable(getPackageName(), resid, mService.applicationInfo);
+ }
+
+ @Override
+ public @NonNull String toString() {
+ return "ServiceInfo{ service=" + getComponentName().toShortString() + " }";
+ }
+ }
+
+ /**
+ * Describes a request to discover routes on behalf of an application.
+ */
+ public static final class DiscoveryRequest {
+ private final ArrayList<MediaRouteSelector> mSelectors =
+ new ArrayList<MediaRouteSelector>();
+ private int mFlags;
+
+ DiscoveryRequest(@NonNull List<MediaRouteSelector> selectors) {
+ setSelectors(selectors);
+ }
+
+ /**
+ * Sets the list of media route selectors to consider during discovery.
+ */
+ public void setSelectors(@NonNull List<MediaRouteSelector> selectors) {
+ if (selectors == null) {
+ throw new IllegalArgumentException("selectors");
+ }
+ mSelectors.clear();
+ mSelectors.addAll(selectors);
+ }
+
+ /**
+ * Gets the list of media route selectors to consider during discovery.
+ */
+ public @NonNull List<MediaRouteSelector> getSelectors() {
+ return mSelectors;
+ }
+
+ /**
+ * Gets discovery flags, such as {@link MediaRouter#DISCOVERY_FLAG_BACKGROUND}.
+ */
+ public @DiscoveryFlags int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * Sets discovery flags, such as {@link MediaRouter#DISCOVERY_FLAG_BACKGROUND}.
+ */
+ public void setFlags(@DiscoveryFlags int flags) {
+ mFlags = flags;
+ }
+
+ @Override
+ public @NonNull String toString() {
+ return "DiscoveryRequest{ selectors=" + mSelectors
+ + ", flags=0x" + Integer.toHexString(mFlags)
+ + " }";
+ }
+ }
+
+ /**
+ * Describes a request to connect to a previously discovered route on
+ * behalf of an application.
+ */
+ public static final class ConnectionRequest {
+ private RouteInfo mRoute;
+ private int mFlags;
+ private Bundle mExtras;
+
+ ConnectionRequest(@NonNull RouteInfo route) {
+ setRoute(route);
+ }
+
+ /**
+ * Gets the route to which to connect.
+ */
+ public @NonNull RouteInfo getRoute() {
+ return mRoute;
+ }
+
+ /**
+ * Sets the route to which to connect.
+ */
+ public void setRoute(@NonNull RouteInfo route) {
+ if (route == null) {
+ throw new IllegalArgumentException("route must not be null");
+ }
+ mRoute = route;
+ }
+
+ /**
+ * Gets connection flags, such as {@link MediaRouter#CONNECTION_FLAG_BARGE}.
+ */
+ public @ConnectionFlags int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * Sets connection flags, such as {@link MediaRouter#CONNECTION_FLAG_BARGE}.
+ */
+ public void setFlags(@ConnectionFlags int flags) {
+ mFlags = flags;
+ }
+
+ /**
+ * Gets optional extras supplied by the application as part of the call to
+ * connect, or null if none. The media route service may use this
+ * information to configure the route during connection.
+ */
+ public @Nullable Bundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Sets optional extras supplied by the application as part of the call to
+ * connect, or null if none. The media route service may use this
+ * information to configure the route during connection.
+ */
+ public void setExtras(@Nullable Bundle extras) {
+ mExtras = extras;
+ }
+
+ @Override
+ public @NonNull String toString() {
+ return "ConnectionRequest{ route=" + mRoute
+ + ", flags=0x" + Integer.toHexString(mFlags)
+ + ", extras=" + mExtras + " }";
+ }
+ }
+
+ /**
+ * Callback interface to specify policy for route discovery, filtering,
+ * and connection establishment as well as observe media router state changes.
+ */
+ public static abstract class RoutingCallback extends StateCallback {
+ /**
+ * Called to prepare a discovery request object to specify the desired
+ * media route selectors when the media router has been asked to start discovery.
+ * <p>
+ * By default, the discovery request contains all of the selectors which
+ * have been added to the media router. Subclasses may override the list of
+ * selectors by modifying the discovery request object before returning.
+ * </p>
+ *
+ * @param request The discovery request object which may be modified by
+ * this method to alter how discovery will be performed.
+ * @param selectors The immutable list of media route selectors which were
+ * added to the media router.
+ * @return True to allow discovery to proceed or false to abort it.
+ * By default, this methods returns true.
+ */
+ public boolean onPrepareDiscoveryRequest(@NonNull DiscoveryRequest request,
+ @NonNull List<MediaRouteSelector> selectors) {
+ return true;
+ }
+
+ /**
+ * Called to prepare a connection request object to specify the desired
+ * route and connection parameters when the media router has been asked to
+ * connect to a particular destination.
+ * <p>
+ * By default, the connection request specifies the first available route
+ * to the destination. Subclasses may override the route and destination
+ * or set additional connection parameters by modifying the connection request
+ * object before returning.
+ * </p>
+ *
+ * @param request The connection request object which may be modified by
+ * this method to alter how the connection will be established.
+ * @param destination The destination to which the media router was asked
+ * to connect.
+ * @param routes The list of routes that belong to that destination sorted
+ * in the same order as their matching media route selectors which were
+ * used during discovery.
+ * @return True to allow the connection to proceed or false to abort it.
+ * By default, this methods returns true.
+ */
+ public boolean onPrepareConnectionRequest(
+ @NonNull ConnectionRequest request,
+ @NonNull DestinationInfo destination, @NonNull List<RouteInfo> routes) {
+ return true;
+ }
+ }
+
+ /**
+ * Callback class to receive events from a {@link MediaRouter.Delegate}.
+ */
+ public static abstract class StateCallback {
+ /**
+ * Called when the media router has been released.
+ */
+ public void onReleased() { }
+
+ /**
+ * Called when the discovery state has changed.
+ *
+ * @param state The new discovery state: one of
+ * {@link #DISCOVERY_STATE_STOPPED} or {@link #DISCOVERY_STATE_STARTED}.
+ */
+ public void onDiscoveryStateChanged(@DiscoveryState int state) { }
+
+ /**
+ * Called when the connection state has changed.
+ *
+ * @param state The new connection state: one of
+ * {@link #CONNECTION_STATE_DISCONNECTED}, {@link #CONNECTION_STATE_CONNECTING}
+ * or {@link #CONNECTION_STATE_CONNECTED}.
+ */
+ public void onConnectionStateChanged(@ConnectionState int state) { }
+
+ /**
+ * Called when the selected destination has changed.
+ *
+ * @param destination The new selected destination, or null if none.
+ */
+ public void onSelectedDestinationChanged(@Nullable DestinationInfo destination) { }
+
+ /**
+ * Called when route discovery has started.
+ */
+ public void onDiscoveryStarted() { }
+
+ /**
+ * Called when route discovery has stopped normally.
+ * <p>
+ * Abnormal termination is reported via {@link #onDiscoveryFailed}.
+ * </p>
+ */
+ public void onDiscoveryStopped() { }
+
+ /**
+ * Called when discovery has failed in a non-recoverable manner.
+ *
+ * @param error The error code: one of
+ * {@link MediaRouter#DISCOVERY_ERROR_UNKNOWN},
+ * {@link MediaRouter#DISCOVERY_ERROR_ABORTED},
+ * or {@link MediaRouter#DISCOVERY_ERROR_NO_CONNECTIVITY}.
+ * @param message The localized error message, or null if none. This message
+ * may be shown to the user.
+ * @param extras Additional information about the error which a client
+ * may use, or null if none.
+ */
+ public void onDiscoveryFailed(@DiscoveryError int error, @Nullable CharSequence message,
+ @Nullable Bundle extras) { }
+
+ /**
+ * Called when a new destination is found or has changed during discovery.
+ * <p>
+ * Certain destinations may be omitted because they have been filtered
+ * out by the media router's routing callback.
+ * </p>
+ *
+ * @param destination The destination that was found.
+ */
+ public void onDestinationFound(@NonNull DestinationInfo destination) { }
+
+ /**
+ * Called when a destination is no longer reachable or is no longer
+ * offering any routes that satisfy the discovery request.
+ *
+ * @param destination The destination that went away.
+ */
+ public void onDestinationLost(@NonNull DestinationInfo destination) { }
+
+ /**
+ * Called when a connection attempt begins.
+ */
+ public void onConnecting() { }
+
+ /**
+ * Called when the connection succeeds.
+ */
+ public void onConnected() { }
+
+ /**
+ * Called when the connection is terminated normally.
+ * <p>
+ * Abnormal termination is reported via {@link #onConnectionFailed}.
+ * </p>
+ */
+ public void onDisconnected() { }
+
+ /**
+ * Called when a connection attempt or connection in
+ * progress has failed in a non-recoverable manner.
+ *
+ * @param error The error code: one of
+ * {@link MediaRouter#CONNECTION_ERROR_ABORTED},
+ * {@link MediaRouter#CONNECTION_ERROR_UNAUTHORIZED},
+ * {@link MediaRouter#CONNECTION_ERROR_UNREACHABLE},
+ * {@link MediaRouter#CONNECTION_ERROR_BUSY},
+ * {@link MediaRouter#CONNECTION_ERROR_TIMEOUT},
+ * {@link MediaRouter#CONNECTION_ERROR_BROKEN},
+ * or {@link MediaRouter#CONNECTION_ERROR_BARGED}.
+ * @param message The localized error message, or null if none. This message
+ * may be shown to the user.
+ * @param extras Additional information about the error which a client
+ * may use, or null if none.
+ */
+ public void onConnectionFailed(@ConnectionError int error,
+ @Nullable CharSequence message, @Nullable Bundle extras) { }
+ }
+}
diff --git a/media/java/android/media/session/RouteEvent.aidl b/media/java/android/media/routing/ParcelableConnectionInfo.aidl
similarity index 89%
copy from media/java/android/media/session/RouteEvent.aidl
copy to media/java/android/media/routing/ParcelableConnectionInfo.aidl
index 6966207..4a9ec94 100644
--- a/media/java/android/media/session/RouteEvent.aidl
+++ b/media/java/android/media/routing/ParcelableConnectionInfo.aidl
@@ -13,6 +13,6 @@
** limitations under the License.
*/
-package android.media.session;
+package android.media.routing;
-parcelable RouteEvent;
+parcelable ParcelableConnectionInfo;
diff --git a/media/java/android/media/routing/ParcelableConnectionInfo.java b/media/java/android/media/routing/ParcelableConnectionInfo.java
new file mode 100644
index 0000000..45cfe9f
--- /dev/null
+++ b/media/java/android/media/routing/ParcelableConnectionInfo.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+package android.media.routing;
+
+import android.media.AudioAttributes;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Internal parcelable representation of a media route connection.
+ */
+class ParcelableConnectionInfo implements Parcelable {
+ public AudioAttributes audioAttributes;
+ public int presentationDisplayId = -1;
+ // todo: volume
+ public IBinder[] protocolBinders;
+ public Bundle extras;
+
+ public static final Parcelable.Creator<ParcelableConnectionInfo> CREATOR =
+ new Parcelable.Creator<ParcelableConnectionInfo>() {
+ @Override
+ public ParcelableConnectionInfo createFromParcel(Parcel source) {
+ ParcelableConnectionInfo info = new ParcelableConnectionInfo();
+ if (source.readInt() != 0) {
+ info.audioAttributes = AudioAttributes.CREATOR.createFromParcel(source);
+ }
+ info.presentationDisplayId = source.readInt();
+ info.protocolBinders = source.createBinderArray();
+ info.extras = source.readBundle();
+ return info;
+ }
+
+ @Override
+ public ParcelableConnectionInfo[] newArray(int size) {
+ return new ParcelableConnectionInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (audioAttributes != null) {
+ dest.writeInt(1);
+ audioAttributes.writeToParcel(dest, flags);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeInt(presentationDisplayId);
+ dest.writeBinderArray(protocolBinders);
+ dest.writeBundle(extras);
+ }
+}
diff --git a/media/java/android/media/session/RouteEvent.aidl b/media/java/android/media/routing/ParcelableDestinationInfo.aidl
similarity index 89%
copy from media/java/android/media/session/RouteEvent.aidl
copy to media/java/android/media/routing/ParcelableDestinationInfo.aidl
index 6966207..bf1c198 100644
--- a/media/java/android/media/session/RouteEvent.aidl
+++ b/media/java/android/media/routing/ParcelableDestinationInfo.aidl
@@ -13,6 +13,6 @@
** limitations under the License.
*/
-package android.media.session;
+package android.media.routing;
-parcelable RouteEvent;
+parcelable ParcelableDestinationInfo;
diff --git a/media/java/android/media/routing/ParcelableDestinationInfo.java b/media/java/android/media/routing/ParcelableDestinationInfo.java
new file mode 100644
index 0000000..eca5eec
--- /dev/null
+++ b/media/java/android/media/routing/ParcelableDestinationInfo.java
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+package android.media.routing;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * Internal parcelable representation of a media destination.
+ */
+class ParcelableDestinationInfo implements Parcelable {
+ public String id;
+ public CharSequence name;
+ public CharSequence description;
+ public int iconResourceId;
+ public Bundle extras;
+
+ public static final Parcelable.Creator<ParcelableDestinationInfo> CREATOR =
+ new Parcelable.Creator<ParcelableDestinationInfo>() {
+ @Override
+ public ParcelableDestinationInfo createFromParcel(Parcel source) {
+ ParcelableDestinationInfo info = new ParcelableDestinationInfo();
+ info.id = source.readString();
+ info.name = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ info.description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ info.iconResourceId = source.readInt();
+ info.extras = source.readBundle();
+ return info;
+ }
+
+ @Override
+ public ParcelableDestinationInfo[] newArray(int size) {
+ return new ParcelableDestinationInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(id);
+ TextUtils.writeToParcel(name, dest, flags);
+ TextUtils.writeToParcel(description, dest, flags);
+ dest.writeInt(iconResourceId);
+ dest.writeBundle(extras);
+ }
+}
diff --git a/media/java/android/media/session/RouteEvent.aidl b/media/java/android/media/routing/ParcelableRouteInfo.aidl
similarity index 90%
copy from media/java/android/media/session/RouteEvent.aidl
copy to media/java/android/media/routing/ParcelableRouteInfo.aidl
index 6966207..126afaa 100644
--- a/media/java/android/media/session/RouteEvent.aidl
+++ b/media/java/android/media/routing/ParcelableRouteInfo.aidl
@@ -13,6 +13,6 @@
** limitations under the License.
*/
-package android.media.session;
+package android.media.routing;
-parcelable RouteEvent;
+parcelable ParcelableRouteInfo;
diff --git a/media/java/android/media/routing/ParcelableRouteInfo.java b/media/java/android/media/routing/ParcelableRouteInfo.java
new file mode 100644
index 0000000..fb1a547
--- /dev/null
+++ b/media/java/android/media/routing/ParcelableRouteInfo.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package android.media.routing;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Internal parcelable representation of a media route.
+ */
+class ParcelableRouteInfo implements Parcelable {
+ public String id;
+ public int selectorIndex; // index of selector within list used for discovery
+ public int features;
+ public String[] protocols;
+ public Bundle extras;
+
+ public static final Parcelable.Creator<ParcelableRouteInfo> CREATOR =
+ new Parcelable.Creator<ParcelableRouteInfo>() {
+ @Override
+ public ParcelableRouteInfo createFromParcel(Parcel source) {
+ ParcelableRouteInfo info = new ParcelableRouteInfo();
+ info.id = source.readString();
+ info.selectorIndex = source.readInt();
+ info.features = source.readInt();
+ info.protocols = source.createStringArray();
+ info.extras = source.readBundle();
+ return info;
+ }
+
+ @Override
+ public ParcelableRouteInfo[] newArray(int size) {
+ return new ParcelableRouteInfo[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(id);
+ dest.writeInt(selectorIndex);
+ dest.writeInt(features);
+ dest.writeStringArray(protocols);
+ dest.writeBundle(extras);
+ }
+}
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index 5bc0de4..a92350b 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -17,10 +17,8 @@
import android.content.ComponentName;
import android.media.MediaMetadata;
+import android.media.routing.IMediaRouter;
import android.media.session.ISessionController;
-import android.media.session.RouteOptions;
-import android.media.session.RouteCommand;
-import android.media.session.RouteInfo;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.ResultReceiver;
@@ -34,17 +32,10 @@
ISessionController getController();
void setFlags(int flags);
void setActive(boolean active);
+ void setMediaRouter(in IMediaRouter router);
void setMediaButtonReceiver(in ComponentName mbr);
void destroy();
- // These commands are for setting up and communicating with routes
- // Returns true if the route was set for this session
- boolean setRoute(in RouteInfo route);
- void setRouteOptions(in List<RouteOptions> options);
- void connectToRoute(in RouteInfo route, in RouteOptions options);
- void disconnectFromRoute(in RouteInfo route);
- void sendRouteCommand(in RouteCommand event, in ResultReceiver cb);
-
// These commands are for the TransportPerformer
void setMetadata(in MediaMetadata metadata);
void setPlaybackState(in PlaybackState state);
@@ -53,4 +44,4 @@
// These commands relate to volume handling
void configureVolumeHandling(int type, int arg1, int arg2);
void setCurrentVolume(int currentVolume);
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/session/ISessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
index 0316d1fa..39391b6 100644
--- a/media/java/android/media/session/ISessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -16,9 +16,6 @@
package android.media.session;
import android.media.Rating;
-import android.media.session.RouteEvent;
-import android.media.session.RouteInfo;
-import android.media.session.RouteOptions;
import android.content.Intent;
import android.os.Bundle;
import android.os.ResultReceiver;
@@ -29,11 +26,6 @@
oneway interface ISessionCallback {
void onCommand(String command, in Bundle extras, in ResultReceiver cb);
void onMediaButton(in Intent mediaButtonIntent, int sequenceNumber, in ResultReceiver cb);
- void onRequestRouteChange(in RouteInfo route);
- void onRouteConnected(in RouteInfo route, in RouteOptions options);
- void onRouteDisconnected(in RouteInfo route, int reason);
- void onRouteStateChange(int state);
- void onRouteEvent(in RouteEvent event);
// These callbacks are for the TransportPerformer
void onPlay();
@@ -47,6 +39,6 @@
void onRate(in Rating rating);
// These callbacks are for volume handling
- void onAdjustVolumeBy(int delta);
+ void onAdjustVolume(int direction);
void onSetVolumeTo(int value);
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index b4c11f6..b555220 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -18,6 +18,8 @@
import android.content.Intent;
import android.media.MediaMetadata;
import android.media.Rating;
+import android.media.routing.IMediaRouterDelegate;
+import android.media.routing.IMediaRouterStateCallback;
import android.media.session.ISessionControllerCallback;
import android.media.session.MediaSessionInfo;
import android.media.session.ParcelableVolumeInfo;
@@ -36,14 +38,15 @@
void registerCallbackListener(in ISessionControllerCallback cb);
void unregisterCallbackListener(in ISessionControllerCallback cb);
boolean isTransportControlEnabled();
- void showRoutePicker();
MediaSessionInfo getSessionInfo();
long getFlags();
ParcelableVolumeInfo getVolumeAttributes();
- void adjustVolumeBy(int delta, int flags);
+ void adjustVolume(int direction, int flags);
void setVolumeTo(int value, int flags);
- // These commands are for the TransportController
+ IMediaRouterDelegate createMediaRouterDelegate(IMediaRouterStateCallback callback);
+
+ // These commands are for the TransportControls
void play();
void pause();
void stop();
@@ -56,4 +59,4 @@
MediaMetadata getMetadata();
PlaybackState getPlaybackState();
int getRatingType();
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/session/ISessionControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl
index baa1379..64d2bc7 100644
--- a/media/java/android/media/session/ISessionControllerCallback.aidl
+++ b/media/java/android/media/session/ISessionControllerCallback.aidl
@@ -16,7 +16,6 @@
package android.media.session;
import android.media.MediaMetadata;
-import android.media.session.RouteInfo;
import android.media.session.ParcelableVolumeInfo;
import android.media.session.PlaybackState;
import android.os.Bundle;
@@ -26,10 +25,9 @@
*/
oneway interface ISessionControllerCallback {
void onEvent(String event, in Bundle extras);
- void onRouteChanged(in RouteInfo route);
// These callbacks are for the TransportController
void onPlaybackStateChanged(in PlaybackState state);
void onMetadataChanged(in MediaMetadata metadata);
void onVolumeInfoChanged(in ParcelableVolumeInfo info);
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index dce84d4..95c2d61 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -31,7 +31,7 @@
ISession createSession(String packageName, in ISessionCallback cb, String tag, int userId);
List<IBinder> getSessions(in ComponentName compName, int userId);
void dispatchMediaKeyEvent(in KeyEvent keyEvent, boolean needWakeLock);
- void dispatchAdjustVolumeBy(int suggestedStream, int delta, int flags);
+ void dispatchAdjustVolume(int suggestedStream, int delta, int flags);
void addSessionsListener(in IActiveSessionsListener listener, in ComponentName compName,
int userId);
void removeSessionsListener(in IActiveSessionsListener listener);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index edb69bc..7fedd82 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -22,6 +22,7 @@
import android.media.MediaMetadata;
import android.media.Rating;
import android.media.VolumeProvider;
+import android.media.routing.MediaRouter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -52,8 +53,7 @@
private static final int MSG_EVENT = 1;
private static final int MSG_UPDATE_PLAYBACK_STATE = 2;
private static final int MSG_UPDATE_METADATA = 3;
- private static final int MSG_ROUTE = 4;
- private static final int MSG_UPDATE_VOLUME = 5;
+ private static final int MSG_UPDATE_VOLUME = 4;
private final ISessionController mSessionBinder;
@@ -64,39 +64,50 @@
private boolean mCbRegistered = false;
private MediaSessionInfo mInfo;
- private TransportControls mTransportController;
-
- private MediaController(ISessionController sessionBinder) {
- mSessionBinder = sessionBinder;
- mTransportController = new TransportControls();
- }
+ private final TransportControls mTransportControls;
/**
+ * Call for creating a MediaController directly from a binder. Should only
+ * be used by framework code.
+ *
* @hide
*/
- public static MediaController fromBinder(ISessionController sessionBinder) {
- return new MediaController(sessionBinder);
+ public MediaController(ISessionController sessionBinder) {
+ if (sessionBinder == null) {
+ throw new IllegalArgumentException("Session token cannot be null");
+ }
+ mSessionBinder = sessionBinder;
+ mTransportControls = new TransportControls();
}
/**
- * Get a new media controller from a session token which may have
- * been obtained from another process. If successful the controller returned
- * will be connected to the session that generated the token.
+ * Create a new MediaController from a session's token.
*
- * @param token The session token to control.
- * @return A controller for the session or null if inaccessible.
+ * @param token The token for the session.
*/
- public static MediaController fromToken(@NonNull MediaSession.Token token) {
- return fromBinder(token.getBinder());
+ public MediaController(@NonNull MediaSession.Token token) {
+ this(token.getBinder());
}
/**
- * Get a {@link TransportControls} instance for this session.
+ * Get a {@link TransportControls} instance to send transport actions to
+ * the associated session.
*
- * @return A controls instance
+ * @return A transport controls instance.
*/
public @NonNull TransportControls getTransportControls() {
- return mTransportController;
+ return mTransportControls;
+ }
+
+ /**
+ * Creates a media router delegate through which the destination of the media
+ * router may be observed and controlled.
+ *
+ * @return The media router delegate, or null if the media session does
+ * not support media routing.
+ */
+ public @Nullable MediaRouter.Delegate createMediaRouterDelegate() {
+ return new MediaRouter.Delegate();
}
/**
@@ -223,19 +234,21 @@
}
/**
- * Adjust the volume of the stream or output this session is playing on.
- * Negative values will lower the volume. The command will be ignored if it
- * does not support {@link VolumeProvider#VOLUME_CONTROL_RELATIVE} or
+ * Adjust the volume of the stream or output this session is playing on. The
+ * direction must be one of {@link AudioManager#ADJUST_LOWER},
+ * {@link AudioManager#ADJUST_RAISE}, or {@link AudioManager#ADJUST_SAME}.
+ * The command will be ignored if the session does not support
+ * {@link VolumeProvider#VOLUME_CONTROL_RELATIVE} or
* {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}. The flags in
* {@link AudioManager} may be used to affect the handling.
*
* @see #getVolumeInfo()
- * @param delta The number of steps to adjust the volume by.
+ * @param direction The direction to adjust the volume in.
* @param flags Any flags to pass with the command.
*/
- public void adjustVolumeBy(int delta, int flags) {
+ public void adjustVolume(int direction, int flags) {
try {
- mSessionBinder.adjustVolumeBy(delta, flags);
+ mSessionBinder.adjustVolume(direction, flags);
} catch (RemoteException e) {
Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
}
@@ -308,20 +321,6 @@
}
/**
- * Request that the route picker be shown for this session. This should
- * generally be called in response to a user action.
- *
- * @hide
- */
- public void showRoutePicker() {
- try {
- mSessionBinder.showRoutePicker();
- } catch (RemoteException e) {
- Log.d(TAG, "Dead object in showRoutePicker", e);
- }
- }
-
- /**
* Get the info for the session this controller is connected to.
*
* @return The session info for the connected session.
@@ -421,15 +420,6 @@
}
/**
- * Override to handle route changes for this session.
- *
- * @param route The new route
- * @hide
- */
- public void onRouteChanged(RouteInfo route) {
- }
-
- /**
* Override to handle changes in playback state.
*
* @param state The new playback state of the session
@@ -670,14 +660,6 @@
}
@Override
- public void onRouteChanged(RouteInfo route) {
- MediaController controller = mController.get();
- if (controller != null) {
- controller.postMessage(MSG_ROUTE, route, null);
- }
- }
-
- @Override
public void onPlaybackStateChanged(PlaybackState state) {
MediaController controller = mController.get();
if (controller != null) {
@@ -719,9 +701,6 @@
case MSG_EVENT:
mCallback.onSessionEvent((String) msg.obj, msg.getData());
break;
- case MSG_ROUTE:
- mCallback.onRouteChanged((RouteInfo) msg.obj);
- break;
case MSG_UPDATE_PLAYBACK_STATE:
mCallback.onPlaybackStateChanged((PlaybackState) msg.obj);
break;
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 2cbdc96..4841360 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -20,11 +20,13 @@
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.Rating;
import android.media.VolumeProvider;
+import android.media.routing.MediaRouter;
import android.media.session.ISessionController;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
@@ -36,10 +38,13 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ResultReceiver;
+import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.telephony.DctConstants.Activity;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -58,8 +63,9 @@
* create a {@link MediaController} to interact with the session.
* <p>
* To receive commands, media keys, and other events a {@link Callback} must be
- * set with {@link #addCallback(Callback)}. To receive transport control
- * commands a {@link TransportControlsCallback} must be set with
+ * set with {@link #addCallback(Callback)} and {@link #setActive(boolean)
+ * setActive(true)} must be called. To receive transport control commands a
+ * {@link TransportControlsCallback} must be set with
* {@link #addTransportControlsCallback}.
* <p>
* When an app is finished performing playback it must call {@link #release()}
@@ -93,40 +99,6 @@
public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 1 << 16;
/**
- * Indicates the session was disconnected because the user that the session
- * belonged to is stopping.
- *
- * @hide
- */
- public static final int DISCONNECT_REASON_USER_STOPPING = 1;
-
- /**
- * Indicates the session was disconnected because the provider disconnected
- * the route.
- * @hide
- */
- public static final int DISCONNECT_REASON_PROVIDER_DISCONNECTED = 2;
-
- /**
- * Indicates the session was disconnected because the route has changed.
- * @hide
- */
- public static final int DISCONNECT_REASON_ROUTE_CHANGED = 3;
-
- /**
- * Indicates the session was disconnected because the session owner
- * requested it disconnect.
- * @hide
- */
- public static final int DISCONNECT_REASON_SESSION_DISCONNECTED = 4;
-
- /**
- * Indicates the session was disconnected because it was destroyed.
- * @hide
- */
- public static final int DISCONNECT_REASON_SESSION_DESTROYED = 5;
-
- /**
* The session uses local playback.
*/
public static final int PLAYBACK_TYPE_LOCAL = 1;
@@ -146,28 +118,51 @@
= new ArrayList<CallbackMessageHandler>();
private final ArrayList<TransportMessageHandler> mTransportCallbacks
= new ArrayList<TransportMessageHandler>();
- // TODO route interfaces
- private final ArrayMap<String, RouteInterface.EventListener> mInterfaceListeners
- = new ArrayMap<String, RouteInterface.EventListener>();
- private Route mRoute;
private VolumeProvider mVolumeProvider;
private boolean mActive = false;
/**
+ * Creates a new session. The session will automatically be registered with
+ * the system but will not be published until {@link #setActive(boolean)
+ * setActive(true)} is called. You must call {@link #release()} when
+ * finished with the session.
+ *
+ * @param context The context to use to create the session.
+ * @param tag A short name for debugging purposes.
+ */
+ public MediaSession(@NonNull Context context, @NonNull String tag) {
+ this(context, tag, UserHandle.myUserId());
+ }
+
+ /**
+ * Creates a new session as the specified user. To create a session as a
+ * user other than your own you must hold the
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
+ * permission.
+ *
+ * @param context The context to use to create the session.
+ * @param tag A short name for debugging purposes.
+ * @param userId The user id to create the session as.
* @hide
*/
- public MediaSession(ISession binder, CallbackStub cbStub) {
- mBinder = binder;
- mCbStub = cbStub;
- ISessionController controllerBinder = null;
- try {
- controllerBinder = mBinder.getController();
- } catch (RemoteException e) {
- throw new RuntimeException("Dead object in MediaSessionController constructor: ", e);
+ public MediaSession(@NonNull Context context, @NonNull String tag, int userId) {
+ if (context == null) {
+ throw new IllegalArgumentException("context cannot be null.");
}
- mSessionToken = new Token(controllerBinder);
+ if (TextUtils.isEmpty(tag)) {
+ throw new IllegalArgumentException("tag cannot be null or empty");
+ }
+ mCbStub = new CallbackStub();
+ MediaSessionManager manager = (MediaSessionManager) context
+ .getSystemService(Context.MEDIA_SESSION_SERVICE);
+ try {
+ mBinder = manager.createSession(mCbStub, tag, userId);
+ mSessionToken = new Token(mBinder.getController());
+ } catch (RemoteException e) {
+ throw new RuntimeException("Remote error creating session.", e);
+ }
}
/**
@@ -228,6 +223,23 @@
}
/**
+ * Associates a {@link MediaRouter} with this session to control the destination
+ * of media content.
+ * <p>
+ * A media router may only be associated with at most one session at a time.
+ * </p>
+ *
+ * @param router The media router, or null to remove the current association.
+ */
+ public void setMediaRouter(@Nullable MediaRouter router) {
+ try {
+ mBinder.setMediaRouter(router != null ? router.getBinder() : null);
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e);
+ }
+ }
+
+ /**
* Set a media button event receiver component to use to restart playback
* after an app has been stopped.
*
@@ -377,90 +389,6 @@
}
/**
- * Connect to the current route using the specified request.
- * <p>
- * Connection updates will be sent to the callback's
- * {@link Callback#onRouteConnected(Route)} and
- * {@link Callback#onRouteDisconnected(Route, int)} methods. If the
- * connection fails {@link Callback#onRouteDisconnected(Route, int)} will be
- * called.
- * <p>
- * If you already have a connection to this route it will be disconnected
- * before the new connection is established. TODO add an easy way to compare
- * MediaRouteOptions.
- *
- * @param route The route the app is trying to connect to.
- * @param request The connection request to use.
- * @hide
- */
- public void connect(RouteInfo route, RouteOptions request) {
- if (route == null) {
- throw new IllegalArgumentException("Must specify the route");
- }
- if (request == null) {
- throw new IllegalArgumentException("Must specify the connection request");
- }
- try {
- mBinder.connectToRoute(route, request);
- } catch (RemoteException e) {
- Log.wtf(TAG, "Error starting connection to route", e);
- }
- }
-
- /**
- * Disconnect from the current route. After calling you will be switched
- * back to the default route.
- *
- * @hide
- */
- public void disconnect() {
- if (mRoute != null) {
- try {
- mBinder.disconnectFromRoute(mRoute.getRouteInfo());
- } catch (RemoteException e) {
- Log.wtf(TAG, "Error disconnecting from route");
- }
- }
- }
-
- /**
- * Set the list of route options your app is interested in connecting to. It
- * will be used for picking valid routes.
- *
- * @param options The set of route options your app may use to connect.
- * @hide
- */
- public void setRouteOptions(List<RouteOptions> options) {
- try {
- mBinder.setRouteOptions(options);
- } catch (RemoteException e) {
- Log.wtf(TAG, "Error setting route options.", e);
- }
- }
-
- /**
- * @hide
- * TODO allow multiple listeners for the same interface, allow removal
- */
- public void addInterfaceListener(String iface,
- RouteInterface.EventListener listener) {
- mInterfaceListeners.put(iface, listener);
- }
-
- /**
- * @hide
- */
- public boolean sendRouteCommand(RouteCommand command, ResultReceiver cb) {
- try {
- mBinder.sendRouteCommand(command, cb);
- } catch (RemoteException e) {
- Log.wtf(TAG, "Error sending command to route.", e);
- return false;
- }
- return true;
- }
-
- /**
* Add a callback to receive transport controls on, such as play, rewind, or
* fast forward.
*
@@ -670,34 +598,6 @@
}
}
- private void postRequestRouteChange(RouteInfo route) {
- synchronized (mLock) {
- for (int i = mCallbacks.size() - 1; i >= 0; i--) {
- mCallbacks.get(i).post(CallbackMessageHandler.MSG_ROUTE_CHANGE, route);
- }
- }
- }
-
- private void postRouteConnected(RouteInfo route, RouteOptions options) {
- synchronized (mLock) {
- mRoute = new Route(route, options, this);
- for (int i = mCallbacks.size() - 1; i >= 0; i--) {
- mCallbacks.get(i).post(CallbackMessageHandler.MSG_ROUTE_CONNECTED, mRoute);
- }
- }
- }
-
- private void postRouteDisconnected(RouteInfo route, int reason) {
- synchronized (mLock) {
- if (mRoute != null && TextUtils.equals(mRoute.getRouteInfo().getId(), route.getId())) {
- for (int i = mCallbacks.size() - 1; i >= 0; i--) {
- mCallbacks.get(i).post(CallbackMessageHandler.MSG_ROUTE_DISCONNECTED, mRoute,
- reason);
- }
- }
- }
- }
-
/**
* Return true if this is considered an active playback state.
*
@@ -796,47 +696,6 @@
public void onControlCommand(@NonNull String command, @Nullable Bundle extras,
@Nullable ResultReceiver cb) {
}
-
- /**
- * Called when the user has selected a different route to connect to.
- * The app is responsible for connecting to the new route and migrating
- * ongoing playback if necessary.
- *
- * @param route
- * @hide
- */
- public void onRequestRouteChange(RouteInfo route) {
- }
-
- /**
- * Called when a route has successfully connected. Calls to the route
- * are now valid.
- *
- * @param route The route that was connected
- * @hide
- */
- public void onRouteConnected(Route route) {
- }
-
- /**
- * Called when a route was disconnected. Further calls to the route will
- * fail. If available a reason for being disconnected will be provided.
- * <p>
- * Valid reasons are:
- * <ul>
- * <li>{@link #DISCONNECT_REASON_USER_STOPPING}</li>
- * <li>{@link #DISCONNECT_REASON_PROVIDER_DISCONNECTED}</li>
- * <li>{@link #DISCONNECT_REASON_ROUTE_CHANGED}</li>
- * <li>{@link #DISCONNECT_REASON_SESSION_DISCONNECTED}</li>
- * <li>{@link #DISCONNECT_REASON_SESSION_DESTROYED}</li>
- * </ul>
- *
- * @param route The route that disconnected
- * @param reason The reason for the disconnect
- * @hide
- */
- public void onRouteDisconnected(Route route, int reason) {
- }
}
/**
@@ -902,17 +761,6 @@
*/
public void onSetRating(@NonNull Rating rating) {
}
-
- /**
- * Report that audio focus has changed on the app. This only happens if
- * you have indicated you have started playing with
- * {@link #setPlaybackState}.
- *
- * @param focusChange The type of focus change, TBD.
- * @hide
- */
- public void onRouteFocusChange(int focusChange) {
- }
}
/**
@@ -926,8 +774,7 @@
}
@Override
- public void onCommand(String command, Bundle extras, ResultReceiver cb)
- throws RemoteException {
+ public void onCommand(String command, Bundle extras, ResultReceiver cb) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.postCommand(command, extras, cb);
@@ -935,8 +782,8 @@
}
@Override
- public void onMediaButton(Intent mediaButtonIntent, int sequenceNumber, ResultReceiver cb)
- throws RemoteException {
+ public void onMediaButton(Intent mediaButtonIntent, int sequenceNumber,
+ ResultReceiver cb) {
MediaSession session = mMediaSession.get();
try {
if (session != null) {
@@ -950,31 +797,7 @@
}
@Override
- public void onRequestRouteChange(RouteInfo route) throws RemoteException {
- MediaSession session = mMediaSession.get();
- if (session != null) {
- session.postRequestRouteChange(route);
- }
- }
-
- @Override
- public void onRouteConnected(RouteInfo route, RouteOptions options) {
- MediaSession session = mMediaSession.get();
- if (session != null) {
- session.postRouteConnected(route, options);
- }
- }
-
- @Override
- public void onRouteDisconnected(RouteInfo route, int reason) {
- MediaSession session = mMediaSession.get();
- if (session != null) {
- session.postRouteDisconnected(route, reason);
- }
- }
-
- @Override
- public void onPlay() throws RemoteException {
+ public void onPlay() {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPlay();
@@ -982,7 +805,7 @@
}
@Override
- public void onPause() throws RemoteException {
+ public void onPause() {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPause();
@@ -990,7 +813,7 @@
}
@Override
- public void onStop() throws RemoteException {
+ public void onStop() {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchStop();
@@ -998,7 +821,7 @@
}
@Override
- public void onNext() throws RemoteException {
+ public void onNext() {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchNext();
@@ -1006,7 +829,7 @@
}
@Override
- public void onPrevious() throws RemoteException {
+ public void onPrevious() {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchPrevious();
@@ -1014,7 +837,7 @@
}
@Override
- public void onFastForward() throws RemoteException {
+ public void onFastForward() {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchFastForward();
@@ -1022,7 +845,7 @@
}
@Override
- public void onRewind() throws RemoteException {
+ public void onRewind() {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchRewind();
@@ -1030,7 +853,7 @@
}
@Override
- public void onSeekTo(long pos) throws RemoteException {
+ public void onSeekTo(long pos) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchSeekTo(pos);
@@ -1038,7 +861,7 @@
}
@Override
- public void onRate(Rating rating) throws RemoteException {
+ public void onRate(Rating rating) {
MediaSession session = mMediaSession.get();
if (session != null) {
session.dispatchRate(rating);
@@ -1046,36 +869,17 @@
}
@Override
- public void onRouteEvent(RouteEvent event) throws RemoteException {
- MediaSession session = mMediaSession.get();
- if (session != null) {
- RouteInterface.EventListener iface
- = session.mInterfaceListeners.get(event.getIface());
- Log.d(TAG, "Received route event on iface " + event.getIface() + ". Listener is "
- + iface);
- if (iface != null) {
- iface.onEvent(event.getEvent(), event.getExtras());
- }
- }
- }
-
- @Override
- public void onRouteStateChange(int state) throws RemoteException {
- // TODO
- }
-
- @Override
- public void onAdjustVolumeBy(int delta) throws RemoteException {
+ public void onAdjustVolume(int direction) {
MediaSession session = mMediaSession.get();
if (session != null) {
if (session.mVolumeProvider != null) {
- session.mVolumeProvider.onAdjustVolumeBy(delta);
+ session.mVolumeProvider.onAdjustVolume(direction);
}
}
}
@Override
- public void onSetVolumeTo(int value) throws RemoteException {
+ public void onSetVolumeTo(int value) {
MediaSession session = mMediaSession.get();
if (session != null) {
if (session.mVolumeProvider != null) {
@@ -1089,9 +893,6 @@
private class CallbackMessageHandler extends Handler {
private static final int MSG_MEDIA_BUTTON = 1;
private static final int MSG_COMMAND = 2;
- private static final int MSG_ROUTE_CHANGE = 3;
- private static final int MSG_ROUTE_CONNECTED = 4;
- private static final int MSG_ROUTE_DISCONNECTED = 5;
private MediaSession.Callback mCallback;
@@ -1114,15 +915,6 @@
Command cmd = (Command) msg.obj;
mCallback.onControlCommand(cmd.command, cmd.extras, cmd.stub);
break;
- case MSG_ROUTE_CHANGE:
- mCallback.onRequestRouteChange((RouteInfo) msg.obj);
- break;
- case MSG_ROUTE_CONNECTED:
- mCallback.onRouteConnected((Route) msg.obj);
- break;
- case MSG_ROUTE_DISCONNECTED:
- mCallback.onRouteDisconnected((Route) msg.obj, msg.arg1);
- break;
}
}
}
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 5d1a7e02..da1a6ed 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -28,6 +28,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
import android.view.KeyEvent;
@@ -46,6 +47,7 @@
private static final Object sLock = new Object();
private static MediaSessionLegacyHelper sInstance;
+ private Context mContext;
private MediaSessionManager mSessionManager;
private Handler mHandler = new Handler(Looper.getMainLooper());
// The legacy APIs use PendingIntents to register/unregister media button
@@ -54,6 +56,7 @@
= new ArrayMap<PendingIntent, SessionHolder>();
private MediaSessionLegacyHelper(Context context) {
+ mContext = context;
mSessionManager = (MediaSessionManager) context
.getSystemService(Context.MEDIA_SESSION_SERVICE);
}
@@ -202,17 +205,17 @@
if (up) {
flags = AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE;
} else {
- flags = AudioManager.FLAG_SHOW_UI;
+ flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_VIBRATE;
}
}
- mSessionManager.dispatchAdjustVolumeBy(AudioManager.USE_DEFAULT_STREAM_TYPE,
+ mSessionManager.dispatchAdjustVolume(AudioManager.USE_DEFAULT_STREAM_TYPE,
direction, flags);
}
}
public void sendAdjustVolumeBy(int suggestedStream, int delta, int flags) {
- mSessionManager.dispatchAdjustVolumeBy(suggestedStream, delta, flags);
+ mSessionManager.dispatchAdjustVolume(suggestedStream, delta, flags);
if (DEBUG) {
Log.d(TAG, "dispatched volume adjustment");
}
@@ -225,6 +228,9 @@
return;
}
SessionHolder holder = getHolder(pi, true);
+ if (holder == null) {
+ return;
+ }
if (holder.mRccListener != null) {
if (holder.mRccListener == listener) {
if (DEBUG) {
@@ -270,6 +276,9 @@
return;
}
SessionHolder holder = getHolder(pi, true);
+ if (holder == null) {
+ return;
+ }
if (holder.mMediaButtonListener != null) {
// Already have this listener registered, but update it anyway as
// the extras may have changed.
@@ -316,7 +325,8 @@
private SessionHolder getHolder(PendingIntent pi, boolean createIfMissing) {
SessionHolder holder = mSessions.get(pi);
if (holder == null && createIfMissing) {
- MediaSession session = mSessionManager.createSession(TAG);
+ MediaSession session;
+ session = new MediaSession(mContext, TAG);
session.setActive(true);
holder = new SessionHolder(session, pi);
mSessions.put(pi, holder);
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index c73a8d3..824b397 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -20,6 +20,7 @@
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
+import android.media.AudioManager;
import android.media.IRemoteVolumeController;
import android.media.session.ISessionManager;
import android.os.IBinder;
@@ -35,9 +36,8 @@
import java.util.List;
/**
- * MediaSessionManager allows the creation and control of MediaSessions in the
- * system. A MediaSession enables publishing information about ongoing media and
- * interacting with MediaControllers and MediaRoutes.
+ * Provides support for interacting with {@link MediaSession media sessions}
+ * that applications have published to express their ongoing media playback state.
* <p>
* Use <code>Context.getSystemService(Context.MEDIA_SESSION_SERVICE)</code> to
* get an instance of this class.
@@ -65,42 +65,15 @@
}
/**
- * Creates a new session.
+ * Create a new session in the system and get the binder for it.
*
* @param tag A short name for debugging purposes.
- * @return A {@link MediaSession} for the new session.
- */
- public @NonNull MediaSession createSession(@NonNull String tag) {
- return createSessionAsUser(tag, UserHandle.myUserId());
- }
-
- /**
- * Creates a new session as the specified user. To create a session as a
- * user other than your own you must hold the
- * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
- * permission.
- *
- * @param tag A short name for debugging purposes.
- * @param userId The user id to create the session as.
- * @return A {@link MediaSession} for the new session.
+ * @return The binder object from the system
* @hide
*/
- public @NonNull MediaSession createSessionAsUser(@NonNull String tag, int userId) {
- if (TextUtils.isEmpty(tag)) {
- throw new IllegalArgumentException("tag must not be null or empty");
- }
-
- try {
- MediaSession.CallbackStub cbStub = new MediaSession.CallbackStub();
- MediaSession session = new MediaSession(mService
- .createSession(mContext.getPackageName(), cbStub, tag, userId), cbStub);
- cbStub.setMediaSession(session);
-
- return session;
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to create session: ", e);
- return null;
- }
+ public @NonNull ISession createSession(@NonNull MediaSession.CallbackStub cbStub,
+ @NonNull String tag, int userId) throws RemoteException {
+ return mService.createSession(mContext.getPackageName(), cbStub, tag, userId);
}
/**
@@ -143,7 +116,7 @@
List<IBinder> binders = mService.getSessions(notificationListener, userId);
int size = binders.size();
for (int i = 0; i < size; i++) {
- MediaController controller = MediaController.fromBinder(ISessionController.Stub
+ MediaController controller = new MediaController(ISessionController.Stub
.asInterface(binders.get(i)));
controllers.add(controller);
}
@@ -256,18 +229,20 @@
}
/**
- * Dispatch an adjust volume request to the system. It will be routed to the
- * most relevant stream/session.
+ * Dispatch an adjust volume request to the system. It will be sent to the
+ * most relevant audio stream or media session. The direction must be one of
+ * {@link AudioManager#ADJUST_LOWER}, {@link AudioManager#ADJUST_RAISE},
+ * {@link AudioManager#ADJUST_SAME}.
*
* @param suggestedStream The stream to fall back to if there isn't a
* relevant stream
- * @param delta The amount to adjust the volume by.
+ * @param direction The direction to adjust volume in.
* @param flags Any flags to include with the volume change.
* @hide
*/
- public void dispatchAdjustVolumeBy(int suggestedStream, int delta, int flags) {
+ public void dispatchAdjustVolume(int suggestedStream, int direction, int flags) {
try {
- mService.dispatchAdjustVolumeBy(suggestedStream, delta, flags);
+ mService.dispatchAdjustVolume(suggestedStream, direction, flags);
} catch (RemoteException e) {
Log.e(TAG, "Failed to send adjust volume.", e);
}
@@ -292,12 +267,11 @@
private final IActiveSessionsListener.Stub mStub = new IActiveSessionsListener.Stub() {
@Override
- public void onActiveSessionsChanged(List<MediaSession.Token> tokens)
- throws RemoteException {
+ public void onActiveSessionsChanged(List<MediaSession.Token> tokens) {
ArrayList<MediaController> controllers = new ArrayList<MediaController>();
int size = tokens.size();
for (int i = 0; i < size; i++) {
- controllers.add(MediaController.fromToken(tokens.get(i)));
+ controllers.add(new MediaController(tokens.get(i)));
}
SessionListener.this.onActiveSessionsChanged(controllers);
}
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 6125cb4..f7e7176 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -157,10 +157,11 @@
/**
* State indicating the class doing playback is currently connecting to a
- * route. Depending on the implementation you may return to the previous
- * state when the connection finishes or enter {@link #STATE_NONE}. If
- * the connection failed {@link #STATE_ERROR} should be used.
- * @hide
+ * new destination. Depending on the implementation you may return to the previous
+ * state when the connection finishes or enter {@link #STATE_NONE}.
+ * If the connection failed {@link #STATE_ERROR} should be used.
+ *
+ * @see #setState
*/
public final static int STATE_CONNECTING = 8;
@@ -183,41 +184,29 @@
*/
public final static long PLAYBACK_POSITION_UNKNOWN = -1;
- private int mState;
- private long mPosition;
- private long mBufferPosition;
- private float mRate;
- private long mActions;
- private CharSequence mErrorMessage;
- private long mUpdateTime;
+ private final int mState;
+ private final long mPosition;
+ private final long mBufferPosition;
+ private final float mSpeed;
+ private final long mActions;
+ private final CharSequence mErrorMessage;
+ private final long mUpdateTime;
- /**
- * Create an empty PlaybackState. At minimum a state and actions should be
- * set before publishing a PlaybackState.
- */
- public PlaybackState() {
- }
-
- /**
- * Create a new PlaybackState from an existing PlaybackState. All fields
- * will be copied to the new state.
- *
- * @param from The PlaybackState to duplicate
- */
- public PlaybackState(PlaybackState from) {
- mState = from.mState;
- mPosition = from.mPosition;
- mRate = from.mRate;
- mUpdateTime = from.mUpdateTime;
- mBufferPosition = from.mBufferPosition;
- mActions = from.mActions;
- mErrorMessage = from.mErrorMessage;
+ private PlaybackState(int state, long position, long updateTime, float speed,
+ long bufferPosition, long actions, CharSequence error) {
+ mState = state;
+ mPosition = position;
+ mSpeed = speed;
+ mUpdateTime = updateTime;
+ mBufferPosition = bufferPosition;
+ mActions = actions;
+ mErrorMessage = error;
}
private PlaybackState(Parcel in) {
mState = in.readInt();
mPosition = in.readLong();
- mRate = in.readFloat();
+ mSpeed = in.readFloat();
mUpdateTime = in.readLong();
mBufferPosition = in.readLong();
mActions = in.readLong();
@@ -231,7 +220,7 @@
bob.append("state=").append(mState);
bob.append(", position=").append(mPosition);
bob.append(", buffered position=").append(mBufferPosition);
- bob.append(", rate=").append(mRate);
+ bob.append(", speed=").append(mSpeed);
bob.append(", updated=").append(mUpdateTime);
bob.append(", actions=").append(mActions);
bob.append(", error=").append(mErrorMessage);
@@ -248,7 +237,7 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mState);
dest.writeLong(mPosition);
- dest.writeFloat(mRate);
+ dest.writeFloat(mSpeed);
dest.writeLong(mUpdateTime);
dest.writeLong(mBufferPosition);
dest.writeLong(mActions);
@@ -270,41 +259,6 @@
public int getState() {
return mState;
}
-
- /**
- * Set the current state of playback.
- * <p>
- * The position must be in ms and indicates the current playback position
- * within the track. If the position is unknown use
- * {@link #PLAYBACK_POSITION_UNKNOWN}.
- * <p>
- * The rate is a multiple of normal playback and should be 0 when paused and
- * negative when rewinding. Normal playback rate is 1.0.
- * <p>
- * The state must be one of the following:
- * <ul>
- * <li> {@link PlaybackState#STATE_NONE}</li>
- * <li> {@link PlaybackState#STATE_STOPPED}</li>
- * <li> {@link PlaybackState#STATE_PLAYING}</li>
- * <li> {@link PlaybackState#STATE_PAUSED}</li>
- * <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
- * <li> {@link PlaybackState#STATE_REWINDING}</li>
- * <li> {@link PlaybackState#STATE_BUFFERING}</li>
- * <li> {@link PlaybackState#STATE_ERROR}</li>
- * </ul>
- *
- * @param state The current state of playback.
- * @param position The position in the current track in ms.
- * @param playbackRate The current rate of playback as a multiple of normal
- * playback.
- */
- public void setState(int state, long position, float playbackRate) {
- this.mState = state;
- this.mPosition = position;
- this.mRate = playbackRate;
- mUpdateTime = SystemClock.elapsedRealtime();
- }
-
/**
* Get the current playback position in ms.
*/
@@ -322,23 +276,14 @@
}
/**
- * Set the current buffer position in ms. This is the farthest playback
- * point that can be reached from the current position using only buffered
- * content.
- */
- public void setBufferPosition(long bufferPosition) {
- mBufferPosition = bufferPosition;
- }
-
- /**
- * Get the current playback rate as a multiple of normal playback. This
+ * Get the current playback speed as a multiple of normal playback. This
* should be negative when rewinding. A value of 1 means normal playback and
* 0 means paused.
*
- * @return The current rate of playback.
+ * @return The current speed of playback.
*/
- public float getPlaybackRate() {
- return mRate;
+ public float getPlaybackSpeed() {
+ return mSpeed;
}
/**
@@ -361,25 +306,6 @@
}
/**
- * Set the current capabilities available on this session. This should use a
- * bitmask of the available capabilities.
- * <ul>
- * <li> {@link PlaybackState#ACTION_SKIP_TO_PREVIOUS}</li>
- * <li> {@link PlaybackState#ACTION_REWIND}</li>
- * <li> {@link PlaybackState#ACTION_PLAY}</li>
- * <li> {@link PlaybackState#ACTION_PAUSE}</li>
- * <li> {@link PlaybackState#ACTION_STOP}</li>
- * <li> {@link PlaybackState#ACTION_FAST_FORWARD}</li>
- * <li> {@link PlaybackState#ACTION_SKIP_TO_NEXT}</li>
- * <li> {@link PlaybackState#ACTION_SEEK_TO}</li>
- * <li> {@link PlaybackState#ACTION_SET_RATING}</li>
- * </ul>
- */
- public void setActions(long capabilities) {
- mActions = capabilities;
- }
-
- /**
* Get a user readable error message. This should be set when the state is
* {@link PlaybackState#STATE_ERROR}.
*/
@@ -392,21 +318,12 @@
* position has never been set this will return 0;
*
* @return The last time the position was updated.
- * @hide
*/
public long getLastPositionUpdateTime() {
return mUpdateTime;
}
/**
- * Set a user readable error message. This should be set when the state is
- * {@link PlaybackState#STATE_ERROR}.
- */
- public void setErrorMessage(CharSequence errorMessage) {
- mErrorMessage = errorMessage;
- }
-
- /**
* Get the {@link PlaybackState} state for the given
* {@link RemoteControlClient} state.
*
@@ -573,4 +490,175 @@
return new PlaybackState[size];
}
};
+
+ /**
+ * Builder for {@link PlaybackState} objects.
+ */
+ public static final class Builder {
+ private int mState;
+ private long mPosition;
+ private long mBufferPosition;
+ private float mSpeed;
+ private long mActions;
+ private CharSequence mErrorMessage;
+ private long mUpdateTime;
+
+ /**
+ * Creates an initially empty state builder.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Creates a builder with the same initial values as those in the from
+ * state.
+ *
+ * @param from The state to use for initializing the builder.
+ */
+ public Builder(PlaybackState from) {
+ if (from == null) {
+ return;
+ }
+ mState = from.mState;
+ mPosition = from.mPosition;
+ mBufferPosition = from.mBufferPosition;
+ mSpeed = from.mSpeed;
+ mActions = from.mActions;
+ mErrorMessage = from.mErrorMessage;
+ mUpdateTime = from.mUpdateTime;
+ }
+
+ /**
+ * Set the current state of playback.
+ * <p>
+ * The position must be in ms and indicates the current playback
+ * position within the track. If the position is unknown use
+ * {@link #PLAYBACK_POSITION_UNKNOWN}. When not using an unknown
+ * position the time at which the position was updated must be provided.
+ * It is okay to use {@link SystemClock#elapsedRealtime()} if the
+ * current position was just retrieved.
+ * <p>
+ * The speed is a multiple of normal playback and should be 0 when
+ * paused and negative when rewinding. Normal playback speed is 1.0.
+ * <p>
+ * The state must be one of the following:
+ * <ul>
+ * <li> {@link PlaybackState#STATE_NONE}</li>
+ * <li> {@link PlaybackState#STATE_STOPPED}</li>
+ * <li> {@link PlaybackState#STATE_PLAYING}</li>
+ * <li> {@link PlaybackState#STATE_PAUSED}</li>
+ * <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
+ * <li> {@link PlaybackState#STATE_REWINDING}</li>
+ * <li> {@link PlaybackState#STATE_BUFFERING}</li>
+ * <li> {@link PlaybackState#STATE_ERROR}</li>
+ * </ul>
+ *
+ * @param state The current state of playback.
+ * @param position The position in the current track in ms.
+ * @param playbackSpeed The current speed of playback as a multiple of
+ * normal playback.
+ * @param updateTime The time in the {@link SystemClock#elapsedRealtime}
+ * timebase that the position was updated at.
+ * @return this
+ */
+ public Builder setState(int state, long position, float playbackSpeed, long updateTime) {
+ mState = state;
+ mPosition = position;
+ mUpdateTime = updateTime;
+ mSpeed = playbackSpeed;
+ return this;
+ }
+
+ /**
+ * Set the current state of playback.
+ * <p>
+ * The position must be in ms and indicates the current playback
+ * position within the track. If the position is unknown use
+ * {@link #PLAYBACK_POSITION_UNKNOWN}. The update time will be set to
+ * the current {@link SystemClock#elapsedRealtime()}.
+ * <p>
+ * The speed is a multiple of normal playback and should be 0 when
+ * paused and negative when rewinding. Normal playback speed is 1.0.
+ * <p>
+ * The state must be one of the following:
+ * <ul>
+ * <li> {@link PlaybackState#STATE_NONE}</li>
+ * <li> {@link PlaybackState#STATE_STOPPED}</li>
+ * <li> {@link PlaybackState#STATE_PLAYING}</li>
+ * <li> {@link PlaybackState#STATE_PAUSED}</li>
+ * <li> {@link PlaybackState#STATE_FAST_FORWARDING}</li>
+ * <li> {@link PlaybackState#STATE_REWINDING}</li>
+ * <li> {@link PlaybackState#STATE_BUFFERING}</li>
+ * <li> {@link PlaybackState#STATE_ERROR}</li>
+ * </ul>
+ *
+ * @param state The current state of playback.
+ * @param position The position in the current track in ms.
+ * @param playbackSpeed The current speed of playback as a multiple of
+ * normal playback.
+ * @return this
+ */
+ public Builder setState(int state, long position, float playbackSpeed) {
+ return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime());
+ }
+
+ /**
+ * Set the current actions available on this session. This should use a
+ * bitmask of possible actions.
+ * <ul>
+ * <li> {@link PlaybackState#ACTION_SKIP_TO_PREVIOUS}</li>
+ * <li> {@link PlaybackState#ACTION_REWIND}</li>
+ * <li> {@link PlaybackState#ACTION_PLAY}</li>
+ * <li> {@link PlaybackState#ACTION_PAUSE}</li>
+ * <li> {@link PlaybackState#ACTION_STOP}</li>
+ * <li> {@link PlaybackState#ACTION_FAST_FORWARD}</li>
+ * <li> {@link PlaybackState#ACTION_SKIP_TO_NEXT}</li>
+ * <li> {@link PlaybackState#ACTION_SEEK_TO}</li>
+ * <li> {@link PlaybackState#ACTION_SET_RATING}</li>
+ * </ul>
+ *
+ * @param actions The set of actions allowed.
+ * @return this
+ */
+ public Builder setActions(long actions) {
+ mActions = actions;
+ return this;
+ }
+
+ /**
+ * Set the current buffer position in ms. This is the farthest playback
+ * point that can be reached from the current position using only
+ * buffered content.
+ *
+ * @param bufferPosition The position in ms that playback is buffered
+ * to.
+ * @return this
+ */
+ public Builder setBufferPosition(long bufferPosition) {
+ mBufferPosition = bufferPosition;
+ return this;
+ }
+
+ /**
+ * Set a user readable error message. This should be set when the state
+ * is {@link PlaybackState#STATE_ERROR}.
+ *
+ * @param error The error message for display to the user.
+ * @return this
+ */
+ public Builder setErrorMessage(CharSequence error) {
+ mErrorMessage = error;
+ return this;
+ }
+
+ /**
+ * Build and return the PlaybackState instance with these values.
+ *
+ * @return A new state instance.
+ */
+ public PlaybackState build() {
+ return new PlaybackState(mState, mPosition, mUpdateTime, mSpeed, mBufferPosition,
+ mActions, mErrorMessage);
+ }
+ }
}
diff --git a/media/java/android/media/session/Route.java b/media/java/android/media/session/Route.java
deleted file mode 100644
index 935eb5b..0000000
--- a/media/java/android/media/session/Route.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.
- */
-package android.media.session;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.List;
-
-/**
- * Represents a destination which an application has connected to and may send
- * media content.
- * <p>
- * This allows a session owner to interact with a route it has been connected
- * to. The MediaRoute must be used to get {@link RouteInterface}
- * instances which can be used to communicate over a specific interface on the
- * route.
- * @hide
- */
-public final class Route {
- private static final String TAG = "Route";
- private final RouteInfo mInfo;
- private final MediaSession mSession;
- private final RouteOptions mOptions;
-
- /**
- * @hide
- */
- public Route(RouteInfo info, RouteOptions options, MediaSession session) {
- if (info == null || options == null) {
- throw new IllegalStateException("Route info was not valid!");
- }
- mInfo = info;
- mOptions = options;
- mSession = session;
- }
-
- /**
- * Get the {@link RouteInfo} for this route.
- *
- * @return The info for this route.
- */
- public RouteInfo getRouteInfo() {
- return mInfo;
- }
-
- /**
- * Get the {@link RouteOptions} that were used to connect this route.
- *
- * @return The options used to connect to this route.
- */
- public RouteOptions getOptions() {
- return mOptions;
- }
-
- /**
- * Gets an interface provided by this route. If the interface is not
- * supported by the route, returns null.
- *
- * @see RouteInterface
- * @param iface The name of the interface to create
- * @return A {@link RouteInterface} or null if the interface is
- * not supported.
- */
- public RouteInterface getInterface(String iface) {
- if (TextUtils.isEmpty(iface)) {
- throw new IllegalArgumentException("iface may not be empty.");
- }
- List<String> ifaces = mOptions.getInterfaceNames();
- if (ifaces != null) {
- for (int i = ifaces.size() - 1; i >= 0; i--) {
- if (iface.equals(ifaces.get(i))) {
- return new RouteInterface(this, iface, mSession);
- }
- }
- }
- Log.e(TAG, "Interface not supported by route");
- return null;
- }
-
- /**
- * @hide
- */
- MediaSession getSession() {
- return mSession;
- }
-}
diff --git a/media/java/android/media/session/RouteCommand.aidl b/media/java/android/media/session/RouteCommand.aidl
deleted file mode 100644
index 725b308..0000000
--- a/media/java/android/media/session/RouteCommand.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 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.
-*/
-
-package android.media.session;
-
-parcelable RouteCommand;
diff --git a/media/java/android/media/session/RouteCommand.java b/media/java/android/media/session/RouteCommand.java
deleted file mode 100644
index 358bc0a..0000000
--- a/media/java/android/media/session/RouteCommand.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- */
-package android.media.session;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents a command that an application may send to a route.
- * <p>
- * Commands are associated with a specific route and interface supported by that
- * route and sent through the session. This class isn't used directly by apps.
- *
- * @hide
- */
-public final class RouteCommand implements Parcelable {
- private final String mRoute;
- private final String mIface;
- private final String mEvent;
- private final Bundle mExtras;
-
- /**
- * @param route The id of the route this event is being sent on
- * @param iface The interface the sender used
- * @param event The event or command
- * @param extras Any extras included with the event
- */
- public RouteCommand(String route, String iface, String event, Bundle extras) {
- mRoute = route;
- mIface = iface;
- mEvent = event;
- mExtras = extras;
- }
-
- private RouteCommand(Parcel in) {
- mRoute = in.readString();
- mIface = in.readString();
- mEvent = in.readString();
- mExtras = in.readBundle();
- }
-
- /**
- * Get the id for the route this event was sent on.
- *
- * @return The route id this event is using
- */
- public String getRouteInfo() {
- return mRoute;
- }
-
- /**
- * Get the interface this event was sent from
- *
- * @return The interface for this event
- */
- public String getIface() {
- return mIface;
- }
-
- /**
- * Get the action/name of the event.
- *
- * @return The name of event/command.
- */
- public String getEvent() {
- return mEvent;
- }
-
- /**
- * Get any extras included with the event.
- *
- * @return The bundle included with the event or null
- */
- public Bundle getExtras() {
- return mExtras;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mRoute);
- dest.writeString(mIface);
- dest.writeString(mEvent);
- dest.writeBundle(mExtras);
- }
-
- public static final Parcelable.Creator<RouteCommand> CREATOR
- = new Parcelable.Creator<RouteCommand>() {
- @Override
- public RouteCommand createFromParcel(Parcel in) {
- return new RouteCommand(in);
- }
-
- @Override
- public RouteCommand[] newArray(int size) {
- return new RouteCommand[size];
- }
- };
-}
diff --git a/media/java/android/media/session/RouteEvent.java b/media/java/android/media/session/RouteEvent.java
deleted file mode 100644
index 918e410..0000000
--- a/media/java/android/media/session/RouteEvent.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.
- */
-package android.media.session;
-
-import android.media.routeprovider.RouteConnection;
-import android.media.routeprovider.RouteProviderService;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * Represents an event that a route provider is sending to a particular
- * {@link RouteConnection}. Events are associated with a specific interface
- * supported by the connection and sent through the {@link RouteProviderService}.
- * This class isn't used directly by apps.
- *
- * @hide
- */
-public class RouteEvent implements Parcelable {
- private final IBinder mConnection;
- private final String mIface;
- private final String mEvent;
- private final Bundle mExtras;
-
- /**
- * @param connection The connection that this event is for
- * @param iface The interface the sender used
- * @param event The event or command
- * @param extras Any extras included with the event
- */
- public RouteEvent(IBinder connection, String iface, String event, Bundle extras) {
- mConnection = connection;
- mIface = iface;
- mEvent = event;
- mExtras = extras;
- }
-
- private RouteEvent(Parcel in) {
- mConnection = in.readStrongBinder();
- mIface = in.readString();
- mEvent = in.readString();
- mExtras = in.readBundle();
- }
-
- /**
- * Get the connection this event was sent on.
- *
- * @return The connection this event is using
- */
- public IBinder getConnection() {
- return mConnection;
- }
-
- /**
- * Get the interface this event was sent from
- *
- * @return The interface for this event
- */
- public String getIface() {
- return mIface;
- }
-
- /**
- * Get the action/name of the event.
- *
- * @return The name of event/command.
- */
- public String getEvent() {
- return mEvent;
- }
-
- /**
- * Get any extras included with the event.
- *
- * @return The bundle included with the event or null
- */
- public Bundle getExtras() {
- return mExtras;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(mConnection);
- dest.writeString(mIface);
- dest.writeString(mEvent);
- dest.writeBundle(mExtras);
- }
-
- public static final Parcelable.Creator<RouteEvent> CREATOR
- = new Parcelable.Creator<RouteEvent>() {
- @Override
- public RouteEvent createFromParcel(Parcel in) {
- return new RouteEvent(in);
- }
-
- @Override
- public RouteEvent[] newArray(int size) {
- return new RouteEvent[size];
- }
- };
-}
diff --git a/media/java/android/media/session/RouteInfo.aidl b/media/java/android/media/session/RouteInfo.aidl
deleted file mode 100644
index c5f50c8..0000000
--- a/media/java/android/media/session/RouteInfo.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 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.
-*/
-
-package android.media.session;
-
-parcelable RouteInfo;
diff --git a/media/java/android/media/session/RouteInfo.java b/media/java/android/media/session/RouteInfo.java
deleted file mode 100644
index 02f78f9..0000000
--- a/media/java/android/media/session/RouteInfo.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * 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.
- */
-package android.media.session;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Information about a route, including its display name, a way to identify it,
- * and the ways it can be connected to.
- * @hide
- */
-public final class RouteInfo implements Parcelable {
- private final String mName;
- private final String mId;
- private final String mProviderId;
- private final List<RouteOptions> mOptions;
-
- private RouteInfo(String id, String name, String providerId,
- List<RouteOptions> connRequests) {
- mId = id;
- mName = name;
- mProviderId = providerId;
- mOptions = connRequests;
- }
-
- private RouteInfo(Parcel in) {
- mId = in.readString();
- mName = in.readString();
- mProviderId = in.readString();
- mOptions = new ArrayList<RouteOptions>();
- in.readTypedList(mOptions, RouteOptions.CREATOR);
- }
-
- /**
- * Get the displayable name of this route.
- *
- * @return A short, user readable name for this route
- */
- public String getName() {
- return mName;
- }
-
- /**
- * Get the unique id for this route.
- *
- * @return A unique route id.
- */
- public String getId() {
- return mId;
- }
-
- /**
- * Get the package name of this route's provider.
- *
- * @return The package name of this route's provider.
- */
- public String getProvider() {
- return mProviderId;
- }
-
- /**
- * Get the set of connections that may be used with this route.
- *
- * @return An array of connection requests that may be used to connect
- */
- public List<RouteOptions> getConnectionMethods() {
- return mOptions;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mId);
- dest.writeString(mName);
- dest.writeString(mProviderId);
- dest.writeTypedList(mOptions);
- }
-
- @Override
- public String toString() {
- StringBuilder bob = new StringBuilder();
- bob.append("RouteInfo: id=").append(mId).append(", name=").append(mName)
- .append(", provider=").append(mProviderId).append(", options={");
- for (int i = 0; i < mOptions.size(); i++) {
- if (i != 0) {
- bob.append(", ");
- }
- bob.append(mOptions.get(i).toString());
- }
- bob.append("}");
- return bob.toString();
- }
-
- public static final Parcelable.Creator<RouteInfo> CREATOR
- = new Parcelable.Creator<RouteInfo>() {
- @Override
- public RouteInfo createFromParcel(Parcel in) {
- return new RouteInfo(in);
- }
-
- @Override
- public RouteInfo[] newArray(int size) {
- return new RouteInfo[size];
- }
- };
-
- /**
- * Helper for creating MediaRouteInfos. A route must have a name and an id.
- * While options are not strictly required the route cannot be connected to
- * without at least one set of options.
- */
- public static final class Builder {
- private String mName;
- private String mId;
- private String mProviderPackage;
- private ArrayList<RouteOptions> mOptions;
-
- /**
- * Copies an existing route info object. TODO Remove once we have
- * helpers for creating route infos.
- *
- * @param from The existing info to copy.
- */
- public Builder(RouteInfo from) {
- mOptions = new ArrayList<RouteOptions>(from.getConnectionMethods());
- mName = from.mName;
- mId = from.mId;
- mProviderPackage = from.mProviderId;
- }
-
- public Builder() {
- mOptions = new ArrayList<RouteOptions>();
- }
-
- /**
- * Set the user visible name for this route.
- *
- * @param name The name of the route
- * @return The builder for easy chaining.
- */
- public Builder setName(String name) {
- mName = name;
- return this;
- }
-
- /**
- * Set the id of the route. This should be unique to the provider.
- *
- * @param id The unique id of the route.
- * @return The builder for easy chaining.
- */
- public Builder setId(String id) {
- mId = id;
- return this;
- }
-
- /**
- * @hide
- */
- public Builder setProviderId(String packageName) {
- mProviderPackage = packageName;
- return this;
- }
-
- /**
- * Add a set of {@link RouteOptions} to the route. Multiple options
- * may be added to the same route.
- *
- * @param options The options to add to this route.
- * @return The builder for easy chaining.
- */
- public Builder addRouteOptions(RouteOptions options) {
- mOptions.add(options);
- return this;
- }
-
- /**
- * Clear the set of {@link RouteOptions} on the route.
- *
- * @return The builder for easy chaining
- */
- public Builder clearRouteOptions() {
- mOptions.clear();
- return this;
- }
-
- /**
- * Build a new MediaRouteInfo.
- *
- * @return A new MediaRouteInfo with the values that were set.
- */
- public RouteInfo build() {
- if (TextUtils.isEmpty(mName)) {
- throw new IllegalArgumentException("Must set a name before building");
- }
- if (TextUtils.isEmpty(mId)) {
- throw new IllegalArgumentException("Must set an id before building");
- }
- return new RouteInfo(mId, mName, mProviderPackage, mOptions);
- }
-
- /**
- * Get the current number of options that have been added to this
- * builder.
- *
- * @return The number of options that have been added.
- */
- public int getOptionsSize() {
- return mOptions.size();
- }
- }
-}
diff --git a/media/java/android/media/session/RouteInterface.java b/media/java/android/media/session/RouteInterface.java
deleted file mode 100644
index 8de4d89..0000000
--- a/media/java/android/media/session/RouteInterface.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * 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.
- */
-package android.media.session;
-
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-import java.util.ArrayList;
-
-/**
- * A route can support multiple interfaces for a {@link MediaSession} to
- * interact with. To use a specific interface with a route a
- * MediaSessionRouteInterface needs to be retrieved from the route. An
- * implementation of the specific interface, like
- * {@link RoutePlaybackControls}, should be used to simplify communication
- * and reduce errors on that interface.
- *
- * @see RoutePlaybackControls for an example
- * @hide
- */
-public final class RouteInterface {
- private static final String TAG = "RouteInterface";
-
- /**
- * Error indicating the route is currently not connected.
- */
- public static final int RESULT_NOT_CONNECTED = -5;
- /**
- * Error indicating the session is no longer using the route this command
- * was sent to.
- */
- public static final int RESULT_ROUTE_IS_STALE = -4;
- /**
- * Error indicating that the interface does not support the command.
- */
- public static final int RESULT_COMMAND_NOT_SUPPORTED = -3;
- /**
- * Error indicating that the route does not support the interface.
- */
- public static final int RESULT_INTERFACE_NOT_SUPPORTED = -2;
- /**
- * Generic error. Extra information about the error may be included in the
- * result bundle.
- */
- public static final int RESULT_ERROR = -1;
- /**
- * The command was successful. Extra information may be included in the
- * result bundle.
- */
- public static final int RESULT_SUCCESS = 1;
-
- private final Route mRoute;
- private final String mIface;
- private final MediaSession mSession;
-
- private final Object mLock = new Object();
- private final ArrayList<EventHandler> mListeners = new ArrayList<EventHandler>();
-
- /**
- * @hide
- */
- RouteInterface(Route route, String iface, MediaSession session) {
- mRoute = route;
- mIface = iface;
- mSession = session;
- mSession.addInterfaceListener(iface, mEventListener);
- }
-
- /**
- * Send a command using this interface.
- *
- * @param command The command to send.
- * @param extras Any extras to include with the command.
- * @param cb The callback to receive the result on.
- * @return true if the command was sent, false otherwise.
- */
- public boolean sendCommand(String command, Bundle extras, ResultReceiver cb) {
- RouteCommand cmd = new RouteCommand(mRoute.getRouteInfo().getId(), mIface,
- command, extras);
- return mSession.sendRouteCommand(cmd, cb);
- }
-
- /**
- * Add a listener to this interface. Events will be sent on the caller's
- * thread.
- *
- * @param listener The listener to receive events on.
- */
- public void addListener(EventListener listener) {
- addListener(listener, null);
- }
-
- /**
- * Add a listener for this interface. If a handler is specified events will
- * be performed on the handler's thread, otherwise the caller's thread will
- * be used.
- *
- * @param listener The listener to receive events on
- * @param handler The handler whose thread to post calls on
- */
- public void addListener(EventListener listener, Handler handler) {
- if (listener == null) {
- throw new IllegalArgumentException("listener may not be null");
- }
- if (handler == null) {
- handler = new Handler();
- }
- synchronized (mLock) {
- if (findIndexOfListenerLocked(listener) != -1) {
- Log.d(TAG, "Listener is already added, ignoring");
- return;
- }
- mListeners.add(new EventHandler(handler.getLooper(), listener));
- }
- }
-
- /**
- * Remove a listener from this interface.
- *
- * @param listener The listener to stop receiving events on.
- */
- public void removeListener(EventListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener may not be null");
- }
- synchronized (mLock) {
- int index = findIndexOfListenerLocked(listener);
- if (index != -1) {
- mListeners.remove(index);
- }
- }
- }
-
- private int findIndexOfListenerLocked(EventListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("Callback cannot be null");
- }
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- EventHandler handler = mListeners.get(i);
- if (listener == handler.mListener) {
- return i;
- }
- }
- return -1;
- }
-
- private EventListener mEventListener = new EventListener() {
- @Override
- public void onEvent(String event, Bundle args) {
- synchronized (mLock) {
- for (int i = mListeners.size() - 1; i >= 0; i--) {
- mListeners.get(i).postEvent(event, args);
- }
- }
- }
-
- };
-
- /**
- * An EventListener can be registered by an app with TODO to handle events
- * sent by the session on a specific interface.
- */
- public static abstract class EventListener {
- /**
- * This is called when an event is received from the interface. Events
- * are sent by the session owner and will be delivered to all
- * controllers that are listening to the interface.
- *
- * @param event The event that occurred.
- * @param args Any extras that were included with the event. May be
- * null.
- */
- public abstract void onEvent(String event, Bundle args);
- }
-
- private static final class EventHandler extends Handler {
-
- private final EventListener mListener;
-
- public EventHandler(Looper looper, EventListener cb) {
- super(looper, null, true);
- mListener = cb;
- }
-
- @Override
- public void handleMessage(Message msg) {
- mListener.onEvent((String) msg.obj, msg.getData());
- }
-
- public void postEvent(String event, Bundle args) {
- Message msg = obtainMessage(0, event);
- msg.setData(args);
- msg.sendToTarget();
- }
- }
-}
diff --git a/media/java/android/media/session/RouteOptions.aidl b/media/java/android/media/session/RouteOptions.aidl
deleted file mode 100644
index feaf517..0000000
--- a/media/java/android/media/session/RouteOptions.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 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.
-*/
-
-package android.media.session;
-
-parcelable RouteOptions;
diff --git a/media/java/android/media/session/RouteOptions.java b/media/java/android/media/session/RouteOptions.java
deleted file mode 100644
index b4fb341..0000000
--- a/media/java/android/media/session/RouteOptions.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.
- */
-package android.media.session;
-
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Specifies options that an application might use when connecting to a route.
- * This includes things like interfaces, connection parameters, and required
- * features.
- * <p>
- * An application may create several different route options that describe
- * alternative sets of capabilities that it can use and choose the most
- * appropriate route options when it is ready to connect to the route. Each
- * route options instance must specify a complete set of capabilities to request
- * when the connection is established.
- * @hide
- */
-public final class RouteOptions implements Parcelable {
- private static final String TAG = "RouteOptions";
-
- private final ArrayList<String> mIfaces;
- private final Bundle mConnectionParams;
-
- private RouteOptions(List<String> ifaces, Bundle params) {
- mIfaces = new ArrayList<String>(ifaces);
- mConnectionParams = params;
- }
-
- private RouteOptions(Parcel in) {
- mIfaces = new ArrayList<String>();
- in.readStringList(mIfaces);
- mConnectionParams = in.readBundle();
- }
-
- /**
- * Get the interfaces this connection wants to use.
- *
- * @return The interfaces for this connection
- */
- public List<String> getInterfaceNames() {
- return mIfaces;
- }
-
- /**
- * Get the parameters that will be used for connecting.
- *
- * @return The set of connection parameters this connections uses
- */
- public Bundle getConnectionParams() {
- return mConnectionParams;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStringList(mIfaces);
- dest.writeBundle(mConnectionParams);
- }
-
- @Override
- public String toString() {
- StringBuilder bob = new StringBuilder();
- bob.append("Options: interfaces={");
- for (int i = 0; i < mIfaces.size(); i++) {
- if (i != 0) {
- bob.append(", ");
- }
- bob.append(mIfaces.get(i));
- }
- bob.append("}");
- bob.append(", parameters=");
- bob.append(mConnectionParams == null ? "null" : mConnectionParams.toString());
- return bob.toString();
- }
-
- public static final Parcelable.Creator<RouteOptions> CREATOR
- = new Parcelable.Creator<RouteOptions>() {
- @Override
- public RouteOptions createFromParcel(Parcel in) {
- return new RouteOptions(in);
- }
-
- @Override
- public RouteOptions[] newArray(int size) {
- return new RouteOptions[size];
- }
- };
-
- /**
- * Builder for creating {@link RouteOptions}.
- */
- public final static class Builder {
- private ArrayList<String> mIfaces = new ArrayList<String>();
- private Bundle mConnectionParams;
-
- public Builder() {
- }
-
- /**
- * Add a required interface to the options.
- *
- * @param interfaceName The name of the interface to add.
- * @return The builder to allow chaining commands.
- */
- public Builder addInterface(String interfaceName) {
- if (TextUtils.isEmpty(interfaceName)) {
- throw new IllegalArgumentException("interfaceName cannot be empty");
- }
- if (!mIfaces.contains(interfaceName)) {
- mIfaces.add(interfaceName);
- } else {
- Log.w(TAG, "Attempted to add interface that is already added");
- }
- return this;
- }
-
- /**
- * Set the connection parameters to use with the options. TODO replace
- * with more specific calls once we decide on the standard way to
- * express parameters.
- *
- * @param parameters The parameters to use.
- * @return The builder to allow chaining commands.
- */
- public Builder setParameters(Bundle parameters) {
- mConnectionParams = parameters;
- return this;
- }
-
- /**
- * Generate a set of options.
- *
- * @return The options with the specified components.
- */
- public RouteOptions build() {
- return new RouteOptions(mIfaces, mConnectionParams);
- }
- }
-}
diff --git a/media/java/android/media/session/RoutePlaybackControls.java b/media/java/android/media/session/RoutePlaybackControls.java
deleted file mode 100644
index 8211983..0000000
--- a/media/java/android/media/session/RoutePlaybackControls.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.
- */
-package android.media.session;
-
-import android.media.MediaMetadata;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-
-/**
- * A standard media control interface for Routes that support queueing and
- * transport controls. Routes may support multiple interfaces for MediaSessions
- * to interact with.
- * @hide
- */
-public final class RoutePlaybackControls {
- private static final String TAG = "RoutePlaybackControls";
- public static final String NAME = "android.media.session.RoutePlaybackControls";
-
- /** @hide */
- public static final String KEY_VALUE1 = "value1";
-
- /** @hide */
- public static final String CMD_FAST_FORWARD = "fastForward";
- /** @hide */
- public static final String CMD_GET_CURRENT_POSITION = "getCurrentPosition";
- /** @hide */
- public static final String CMD_GET_CAPABILITIES = "getCapabilities";
- /** @hide */
- public static final String CMD_PLAY_NOW = "playNow";
- /** @hide */
- public static final String CMD_RESUME = "resume";
- /** @hide */
- public static final String CMD_PAUSE = "pause";
-
- /** @hide */
- public static final String EVENT_PLAYSTATE_CHANGE = "playstateChange";
- /** @hide */
- public static final String EVENT_METADATA_CHANGE = "metadataChange";
-
- private final RouteInterface mIface;
-
- private RoutePlaybackControls(RouteInterface iface) {
- mIface = iface;
- }
-
- /**
- * Get a new MediaRoutePlaybackControls instance for sending commands using
- * this interface. If the provided route doesn't support this interface null
- * will be returned.
- *
- * @param route The route to send commands to.
- * @return A MediaRoutePlaybackControls instance or null if not supported.
- */
- public static RoutePlaybackControls from(Route route) {
- RouteInterface iface = route.getInterface(NAME);
- if (iface != null) {
- return new RoutePlaybackControls(iface);
- }
- return null;
- }
-
- /**
- * Send a resume command to the route.
- */
- public void resume() {
- mIface.sendCommand(CMD_RESUME, null, null);
- }
-
- /**
- * Send a pause command to the route.
- */
- public void pause() {
- mIface.sendCommand(CMD_PAUSE, null, null);
- }
-
- /**
- * Send a fast forward command.
- */
- public void fastForward() {
- Bundle b = new Bundle();
- mIface.sendCommand(CMD_FAST_FORWARD, b, null);
- }
-
- /**
- * Retrieves the current playback position.
- *
- * @param cb The callback to receive the result on.
- */
- public void getCurrentPosition(ResultReceiver cb) {
- mIface.sendCommand(CMD_GET_CURRENT_POSITION, null, cb);
- }
-
- public void getCapabilities(ResultReceiver cb) {
- mIface.sendCommand(CMD_GET_CAPABILITIES, null, cb);
- }
-
- public void addListener(Listener listener) {
- mIface.addListener(listener);
- }
-
- public void addListener(Listener listener, Handler handler) {
- mIface.addListener(listener, handler);
- }
-
- public void removeListener(Listener listener) {
- mIface.removeListener(listener);
- }
-
- public void playNow(String content) {
- Bundle bundle = new Bundle();
- bundle.putString(KEY_VALUE1, content);
- mIface.sendCommand(CMD_PLAY_NOW, bundle, null);
- }
-
- /**
- * Register this event listener using {@link #addListener} to receive
- * RoutePlaybackControl events from a session.
- */
- public static abstract class Listener extends RouteInterface.EventListener {
- @Override
- public final void onEvent(String event, Bundle args) {
- if (EVENT_PLAYSTATE_CHANGE.equals(event)) {
- onPlaybackStateChange(args.getInt(KEY_VALUE1, 0));
- } else if (EVENT_METADATA_CHANGE.equals(event)) {
- onMetadataUpdate((MediaMetadata) args.getParcelable(KEY_VALUE1));
- }
- }
-
- /**
- * Override to handle updates to the playback state. Valid values are in
- * {@link TransportPerformer}. TODO put playstate values somewhere more
- * generic.
- *
- * @param state
- */
- public void onPlaybackStateChange(int state) {
- }
-
- /**
- * Override to handle metadata changes for this session's media. The
- * default supported fields are those in {@link MediaMetadata}.
- *
- * @param metadata
- */
- public void onMetadataUpdate(MediaMetadata metadata) {
- }
- }
-
-}
diff --git a/media/java/android/media/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index 27360ed..423e317 100644
--- a/media/java/android/media/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -30,9 +30,10 @@
*/
oneway interface ITvInputClient {
void onSessionCreated(in String inputId, IBinder token, in InputChannel channel, int seq);
- void onAvailabilityChanged(in String inputId, boolean isAvailable);
void onSessionReleased(int seq);
void onSessionEvent(in String name, in Bundle args, int seq);
void onChannelRetuned(in Uri channelUri, int seq);
void onTrackInfoChanged(in List<TvTrackInfo> tracks, int seq);
+ void onVideoAvailable(int seq);
+ void onVideoUnavailable(int reason, int seq);
}
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 9a6a648..6a0c592 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -18,9 +18,10 @@
import android.content.ComponentName;
import android.graphics.Rect;
+import android.media.tv.ITvInputClient;
import android.media.tv.ITvInputHardware;
import android.media.tv.ITvInputHardwareCallback;
-import android.media.tv.ITvInputClient;
+import android.media.tv.ITvInputManagerCallback;
import android.media.tv.TvInputHardwareInfo;
import android.media.tv.TvInputInfo;
import android.media.tv.TvTrackInfo;
@@ -34,10 +35,8 @@
interface ITvInputManager {
List<TvInputInfo> getTvInputList(int userId);
- boolean getAvailability(in ITvInputClient client, in String inputId, int userId);
-
- void registerCallback(in ITvInputClient client, in String inputId, int userId);
- void unregisterCallback(in ITvInputClient client, in String inputId, int userId);
+ void registerCallback(in ITvInputManagerCallback callback, int userId);
+ void unregisterCallback(in ITvInputManagerCallback callback, int userId);
void createSession(in ITvInputClient client, in String inputId, int seq, int userId);
void releaseSession(in IBinder sessionToken, int userId);
@@ -56,7 +55,12 @@
// For TV input hardware binding
List<TvInputHardwareInfo> getHardwareList();
+ /*
+ * All TvInputServices which want to use hardware must call this method on
+ * BOOT_COMPLETE.
+ */
+ void registerTvInputInfo(in TvInputInfo info, int deviceId);
ITvInputHardware acquireTvInputHardware(int deviceId, in ITvInputHardwareCallback callback,
- int userId);
+ in TvInputInfo info, int userId);
void releaseTvInputHardware(int deviceId, in ITvInputHardware hardware, int userId);
}
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl b/media/java/android/media/tv/ITvInputManagerCallback.aidl
similarity index 65%
copy from telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl
copy to media/java/android/media/tv/ITvInputManagerCallback.aidl
index 3a02b06..5c8a0a3 100644
--- a/telephony/java/com/android/internal/telephony/IThirdPartyCallSendDtmfCallback.aidl
+++ b/media/java/android/media/tv/ITvInputManagerCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package android.media.tv;
/**
- * Callback interface for when DTMF has been sent.
+ * Interface to receive callbacks from ITvInputManager regardless of sessions.
+ * @hide
*/
-oneway interface IThirdPartyCallSendDtmfCallback {
- /**
- * Called when the DTMF code has been sent.
- */
- void onSendDtmfCompleted();
+oneway interface ITvInputManagerCallback {
+ void onInputStateChanged(in String inputId, int state);
}
diff --git a/media/java/android/media/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
index c9484dd..1fdb8c5 100644
--- a/media/java/android/media/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -24,5 +24,5 @@
* @hide
*/
oneway interface ITvInputServiceCallback {
- void onAvailabilityChanged(in String inputId, boolean isAvailable);
+ void onInputStateChanged(int state);
}
diff --git a/media/java/android/media/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index 4d72059..e0036e1 100644
--- a/media/java/android/media/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -31,4 +31,6 @@
void onSessionEvent(in String name, in Bundle args);
void onChannelRetuned(in Uri channelUri);
void onTrackInfoChanged(in List<TvTrackInfo> tracks);
+ void onVideoAvailable();
+ void onVideoUnavailable(int reason);
}
diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java
new file mode 100644
index 0000000..905b0bd
--- /dev/null
+++ b/media/java/android/media/tv/TvContentRating.java
@@ -0,0 +1,245 @@
+/*
+ * 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.
+ */
+
+package android.media.tv;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class representing a TV content rating.
+ */
+public class TvContentRating {
+ private static final String TAG = "TvContentRating";
+
+ private static final int RATING_PREFIX_LENGTH = 10;
+ private static final String PREFIX_RATING_US = "RATING_US_";
+ private static final String PREFIX_SUBRATING_US = "SUBRATING_US_";
+
+ /**
+ * Rating constant for TV-Y from the TV Parental Guidelines system in US. This program is
+ * designed to be appropriate for all children.
+ */
+ public static final String RATING_US_TV_Y = PREFIX_RATING_US + "TV_Y";
+ /**
+ * Rating constant for TV-Y7 from the TV Parental Guidelines system in US. This program is
+ * designed for children age 7 and above.
+ */
+ public static final String RATING_US_TV_Y7 = PREFIX_RATING_US + "TV_Y7";
+ /**
+ * Rating constant for TV-G from the TV Parental Guidelines system in US. Most parents would
+ * find this program suitable for all ages.
+ */
+ public static final String RATING_US_TV_G = PREFIX_RATING_US + "TV_G";
+ /**
+ * Rating constant for TV-PG from the TV Parental Guidelines system in US. This program contains
+ * material that parents may find unsuitable for younger children.
+ */
+ public static final String RATING_US_TV_PG = PREFIX_RATING_US + "TV_PG";
+ /**
+ * Rating constant for TV-14 from the TV Parental Guidelines system in US. This program contains
+ * some material that many parents would find unsuitable for children under 14 years of age.
+ */
+ public static final String RATING_US_TV_14 = PREFIX_RATING_US + "TV_14";
+ /**
+ * Rating constant for TV-MA from the TV Parental Guidelines system in US. This program is
+ * specifically designed to be viewed by adults and therefore may be unsuitable for children
+ * under 17.
+ */
+ public static final String RATING_US_TV_MA = PREFIX_RATING_US + "TV_MA";
+
+ /**
+ * Sub-rating constant for D (Suggestive dialogue) from the TV Parental Guidelines system in US.
+ */
+ public static final String SUBRATING_US_D = PREFIX_SUBRATING_US + "D";
+ /**
+ * Sub-rating constant for L (Coarse language) from the TV Parental Guidelines system in US.
+ */
+ public static final String SUBRATING_US_L = PREFIX_SUBRATING_US + "L";
+ /**
+ * Sub-rating constant for S (Sexual content) from the TV Parental Guidelines system in US.
+ */
+ public static final String SUBRATING_US_S = PREFIX_SUBRATING_US + "S";
+ /**
+ * Sub-rating constant for V (Violence) from the TV Parental Guidelines system in US.
+ */
+ public static final String SUBRATING_US_V = PREFIX_SUBRATING_US + "V";
+ /**
+ * Sub-rating constant for FV (Fantasy violence) from the TV Parental Guidelines system in US.
+ */
+ public static final String SUBRATING_US_FV = PREFIX_SUBRATING_US + "FV";
+
+ private static final String PREFIX_RATING_KR = "RATING_KR_";
+
+ /**
+ * Rating constant for 'ALL' from the South Korean television rating system. This rating is for
+ * programming that is appropriate for all ages.
+ */
+ public static final String RATING_KR_ALL = PREFIX_RATING_KR + "ALL";
+ /**
+ * Rating constant for '7' from the South Korean television rating system. This rating is for
+ * programming that may contain material inappropriate for children younger than 7, and parental
+ * discretion should be used.
+ */
+ public static final String RATING_KR_7 = PREFIX_RATING_KR + "7";
+ /**
+ * Rating constant for '12' from the South Korean television rating system. This rating is for
+ * programs that may deemed inappropriate for those younger than 12, and parental discretion
+ * should be used.
+ */
+ public static final String RATING_KR_12 = PREFIX_RATING_KR + "12";
+ /**
+ * Rating constant for '15' from the South Korean television rating system. This rating is for
+ * programs that contain material that may be inappropriate for children under 15, and that
+ * parental discretion should be used.
+ */
+ public static final String RATING_KR_15 = PREFIX_RATING_KR + "15";
+ /**
+ * Rating constant for '19' from the South Korean television rating system. This rating is for
+ * programs that are intended for adults only. 19-rated programming cannot air during the hours
+ * of 7:00AM to 9:00AM, and 1:00PM to 10:00PM.
+ */
+ public static final String RATING_KR_19 = PREFIX_RATING_KR + "19";
+
+ private static final String DELIMITER = "/";
+
+ // A mapping from two-letter country code (ISO 3166-1 alpha-2) to its rating-to-sub-ratings map.
+ // This is used for validating the builder parameters.
+ private static final Map<String, Map<String, String[]>> sRatings
+ = new HashMap<String, Map<String, String[]>>();
+
+ static {
+ Map<String, String[]> usRatings = new HashMap<String, String[]>();
+ usRatings.put(RATING_US_TV_Y, null);
+ usRatings.put(RATING_US_TV_Y7, new String[] { SUBRATING_US_FV });
+ usRatings.put(RATING_US_TV_G, null);
+ usRatings.put(RATING_US_TV_PG, new String[] {
+ SUBRATING_US_D, SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V });
+ usRatings.put(RATING_US_TV_14, new String[] {
+ SUBRATING_US_D, SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V });
+ usRatings.put(RATING_US_TV_MA, new String[] {
+ SUBRATING_US_L, SUBRATING_US_S, SUBRATING_US_V });
+ sRatings.put(PREFIX_RATING_US, usRatings);
+
+ Map<String, String[]> krRatings = new HashMap<String, String[]>();
+ krRatings.put(RATING_KR_ALL, null);
+ krRatings.put(RATING_KR_7, null);
+ krRatings.put(RATING_KR_12, null);
+ krRatings.put(RATING_KR_15, null);
+ krRatings.put(RATING_KR_19, null);
+ sRatings.put(PREFIX_RATING_KR, krRatings);
+ }
+
+ private final String mRating;
+ private final String[] mSubRatings;
+
+ /**
+ * Constructs a TvContentRating object from a given rating constant.
+ *
+ * @param rating The rating constant defined in this class.
+ */
+ public TvContentRating(String rating) {
+ mRating = rating;
+ mSubRatings = null;
+ }
+
+ /**
+ * Constructs a TvContentRating object from a given rating and sub-rating constants.
+ *
+ * @param rating The rating constant defined in this class.
+ * @param subRatings The String array of sub-rating constants defined in this class.
+ */
+ public TvContentRating(String rating, String[] subRatings) {
+ mRating = rating;
+ mSubRatings = subRatings;
+ if (TextUtils.isEmpty(mRating)) {
+ throw new IllegalArgumentException("rating cannot be null");
+ }
+ String prefix = "";
+ if (mRating.length() > RATING_PREFIX_LENGTH) {
+ prefix = mRating.substring(0, RATING_PREFIX_LENGTH);
+ }
+ Map<String, String[]> ratings = sRatings.get(prefix);
+ if (ratings != null) {
+ if (!ratings.keySet().contains(mRating)) {
+ Log.w(TAG, "Unknown rating: " + mRating);
+ } else if (mSubRatings != null) {
+ String[] validSubRatings = ratings.get(mRating);
+ if (validSubRatings == null) {
+ Log.w(TAG, "Invalid subratings: " + mSubRatings);
+ } else {
+ List<String> validSubRatingList = Arrays.asList(subRatings);
+ for (String sr : mSubRatings) {
+ if (!validSubRatingList.contains(sr)) {
+ Log.w(TAG, "Invalid subrating: " + sr);
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ Log.w(TAG, "Rating undefined for " + mRating);
+ }
+ }
+
+ /**
+ * Recovers a TvContentRating from a String that was previously created with
+ * {@link #flattenToString}.
+ *
+ * @param ratingString The String that was returned by flattenToString().
+ * @return a new TvContentRating containing the rating and sub-ratings information was encoded
+ * in {@code ratingString}.
+ * @see #flattenToString
+ */
+ public static TvContentRating unflattenFromString(String ratingString) {
+ if (TextUtils.isEmpty(ratingString)) {
+ throw new IllegalArgumentException("Empty rating string");
+ }
+ String[] strs = ratingString.split(DELIMITER);
+ if (strs.length < 1) {
+ throw new IllegalArgumentException("Invalid rating string: " + ratingString);
+ }
+ if (strs.length > 1) {
+ String[] subRatings = new String[strs.length - 1];
+ System.arraycopy(strs, 1, subRatings, 0, subRatings.length);
+ return new TvContentRating(strs[0], subRatings);
+ }
+ return new TvContentRating(strs[0]);
+ }
+
+ /**
+ * @return a String that unambiguously describes both the rating and sub-rating information
+ * contained in the TvContentRating. You can later recover the TvContentRating from this
+ * string through {@link #unflattenFromString}.
+ * @see #unflattenFromString
+ */
+ public String flattenToString() {
+ StringBuffer ratingStr = new StringBuffer();
+ ratingStr.append(mRating);
+ if (mSubRatings != null) {
+ for (String subRating : mSubRatings) {
+ ratingStr.append(DELIMITER);
+ ratingStr.append(subRating);
+ }
+ }
+ return ratingStr.toString();
+ }
+}
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 46aeb1d..8ecf808 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -16,9 +16,9 @@
package android.media.tv;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
+import android.media.tv.TvContract.Programs;
import android.net.Uri;
import android.provider.BaseColumns;
import android.util.ArraySet;
@@ -120,26 +120,23 @@
/**
* Builds a URI that points to all browsable channels from a given TV input.
*
- * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
- * implements the given TV input.
+ * @param inputId The ID of the TV input to build a channels URI for.
*/
- public static final Uri buildChannelsUriForInput(ComponentName name) {
- return buildChannelsUriForInput(name, true);
+ public static final Uri buildChannelsUriForInput(String inputId) {
+ return buildChannelsUriForInput(inputId, true);
}
/**
* Builds a URI that points to all or browsable-only channels from a given TV input.
*
- * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
- * implements the given TV input.
+ * @param inputId The ID of the TV input to build a channels URI for.
* @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
* to {@code false} the URI points to all channels regardless of whether they are
* browsable or not.
*/
- public static final Uri buildChannelsUriForInput(ComponentName name, boolean browsableOnly) {
+ public static final Uri buildChannelsUriForInput(String inputId, boolean browsableOnly) {
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
- .appendPath(PATH_INPUT).appendPath(name.getPackageName())
- .appendPath(name.getClassName()).appendPath(PATH_CHANNEL)
+ .appendPath(PATH_INPUT).appendPath(inputId).appendPath(PATH_CHANNEL)
.appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly)).build();
}
@@ -147,26 +144,26 @@
* Builds a URI that points to all or browsable-only channels which have programs with the given
* genre from the given TV input.
*
- * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
- * implements the given TV input. If null, builds a URI for all the TV inputs.
+ * @param inputId The ID of the TV input to build a channels URI for. If null, builds a URI for
+ * all the TV inputs.
* @param genre {@link Programs.Genres} to search.
* @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
* to {@code false} the URI points to all channels regardless of whether they are
* browsable or not.
* @hide
*/
- public static final Uri buildChannelsUriForCanonicalGenre(ComponentName name, String genre,
+ public static final Uri buildChannelsUriForCanonicalGenre(String inputId, String genre,
boolean browsableOnly) {
if (!Programs.Genres.isCanonical(genre)) {
throw new IllegalArgumentException("Not a canonical genre: '" + genre + "'");
}
Uri uri;
- if (name == null) {
+ if (inputId == null) {
uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
.appendPath(PATH_CHANNEL).build();
} else {
- uri = buildChannelsUriForInput(name, browsableOnly);
+ uri = buildChannelsUriForInput(inputId, browsableOnly);
}
return uri.buildUpon().appendQueryParameter(PARAM_CANONICAL_GENRE, genre).build();
}
@@ -249,42 +246,25 @@
}
/**
- * Extracts the {@link Channels#COLUMN_PACKAGE_NAME} from a given URI.
+ * Extracts the {@link Channels#COLUMN_INPUT_ID} from a given URI.
*
- * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(ComponentName)} or
- * {@link #buildChannelsUriForInput(ComponentName, boolean)}.
+ * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(String)},
+ * {@link #buildChannelsUriForInput(String, boolean)}, or
+ * {@link #buildChannelsUriForCanonicalGenre(String, String, boolean)}.
* @hide
*/
- public static final String getPackageName(Uri channelsUri) {
+ public static final String getInputId(Uri channelsUri) {
final List<String> paths = channelsUri.getPathSegments();
- if (paths.size() < 4) {
+ if (paths.size() < 3) {
throw new IllegalArgumentException("Not channels: " + channelsUri);
}
- if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(3))) {
+ if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(2))) {
throw new IllegalArgumentException("Not channels: " + channelsUri);
}
return paths.get(1);
}
/**
- * Extracts the {@link Channels#COLUMN_SERVICE_NAME} from a given URI.
- *
- * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(ComponentName)} or
- * {@link #buildChannelsUriForInput(ComponentName, boolean)}.
- * @hide
- */
- public static final String getServiceName(Uri channelsUri) {
- final List<String> paths = channelsUri.getPathSegments();
- if (paths.size() < 4) {
- throw new IllegalArgumentException("Not channels: " + channelsUri);
- }
- if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(3))) {
- throw new IllegalArgumentException("Not channels: " + channelsUri);
- }
- return paths.get(2);
- }
-
- /**
* Extracts the {@link Channels#_ID} from a given URI.
*
* @param programsUri A URI constructed by {@link #buildProgramsUriForChannel(Uri)} or
@@ -495,15 +475,14 @@
}
/**
- * The name of the {@link TvInputService} subclass that provides this TV channel. This
- * should be a fully qualified class name (such as, "com.example.project.TvInputService").
+ * The ID of the TV input that provides this TV channel.
* <p>
* This is a required field.
* </p><p>
* Type: TEXT
* </p>
*/
- public static final String COLUMN_SERVICE_NAME = "service_name";
+ public static final String COLUMN_INPUT_ID = "input_id";
/**
* The predefined type of this TV channel.
@@ -913,6 +892,24 @@
public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
/**
+ * The comma-separated content ratings of this TV program.
+ * <p>
+ * This is used to describe the content rating(s) of this program. Each comma-separated
+ * content rating sub-string should be generated by calling
+ * {@link TvContentRating#flattenToString}. Note that in most cases the program content is
+ * rated by a single rating system, thus resulting in a corresponding single sub-string that
+ * does not require comma separation and multiple sub-strings appear only when the program
+ * content is rated by two or more content rating systems. If any of those ratings is
+ * specified as "blocked rating" in the user's parental control settings, the TV input
+ * service should block the current content and wait for the signal that it is okay to
+ * unblock.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String COLUMN_CONTENT_RATING = "content_rating";
+
+ /**
* The URI for the poster art of this TV program.
* <p>
* Can be empty.
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 7b8f2ec..3dc9ffb 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -68,9 +68,9 @@
public static final int TYPE_PASSTHROUGH = 3;
/**
- * The name of the TV input service to provide to the setup activity and settings activity.
+ * The ID of the TV input to provide to the setup activity and settings activity.
*/
- public static final String EXTRA_SERVICE_NAME = "serviceName";
+ public static final String EXTRA_INPUT_ID = "inputId";
private static final String XML_START_TAG_NAME = "tv-input";
@@ -80,7 +80,7 @@
// Attributes from XML meta data.
private String mSetupActivity;
private String mSettingsActivity;
- private int mType;
+ private int mType = TYPE_VIRTUAL;
/**
* Create a new instance of the TvInputInfo class,
@@ -128,10 +128,13 @@
Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for "
+ si.name);
}
- input.mType = sa.getInt(
- com.android.internal.R.styleable.TvInputService_tvInputType, TYPE_VIRTUAL);
- if (DEBUG) {
- Log.d(TAG, "Type loaded. [" + input.mType + "] for " + si.name);
+ if (pm.checkPermission(android.Manifest.permission.TV_INPUT_HARDWARE, si.packageName)
+ == PackageManager.PERMISSION_GRANTED) {
+ input.mType = sa.getInt(
+ com.android.internal.R.styleable.TvInputService_tvInputType, TYPE_VIRTUAL);
+ if (DEBUG) {
+ Log.d(TAG, "Type loaded. [" + input.mType + "] for " + si.name);
+ }
}
sa.recycle();
@@ -187,7 +190,7 @@
if (!TextUtils.isEmpty(mSetupActivity)) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(mService.serviceInfo.packageName, mSetupActivity);
- intent.putExtra(EXTRA_SERVICE_NAME, mService.serviceInfo.name);
+ intent.putExtra(EXTRA_INPUT_ID, getId());
return intent;
}
return null;
@@ -200,7 +203,7 @@
if (!TextUtils.isEmpty(mSettingsActivity)) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setClassName(mService.serviceInfo.packageName, mSettingsActivity);
- intent.putExtra(EXTRA_SERVICE_NAME, mService.serviceInfo.name);
+ intent.putExtra(EXTRA_INPUT_ID, getId());
return intent;
}
return null;
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f1a63ad..79a83b0 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -24,6 +24,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.util.ArrayMap;
import android.util.Log;
import android.util.Pools.Pool;
import android.util.Pools.SimplePool;
@@ -37,6 +38,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -47,11 +49,61 @@
public final class TvInputManager {
private static final String TAG = "TvInputManager";
+ /**
+ * A generic reason. Video is not available due to an unspecified error.
+ */
+ public static final int VIDEO_UNAVAILABLE_REASON_UNKNOWN = 0;
+ /**
+ * Video is not available because the TV input is tuning to another channel.
+ */
+ public static final int VIDEO_UNAVAILABLE_REASON_TUNE = 1;
+ /**
+ * Video is not available due to the weak TV signal.
+ */
+ public static final int VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL = 2;
+ /**
+ * Video is not available because the TV input stopped the playback temporarily to buffer more
+ * data.
+ */
+ public static final int VIDEO_UNAVAILABLE_REASON_BUFFERING = 3;
+
+ /**
+ * The TV input is connected.
+ * <p>
+ * State for {@link #getInputState} and {@link
+ * TvInputManager.TvInputListener#onInputStateChanged}.
+ * </p>
+ */
+ public static final int INPUT_STATE_CONNECTED = 0;
+ /**
+ * The TV input is connected but in standby mode. It would take a while until it becomes
+ * fully ready.
+ * <p>
+ * State for {@link #getInputState} and {@link
+ * TvInputManager.TvInputListener#onInputStateChanged}.
+ * </p>
+ */
+ public static final int INPUT_STATE_CONNECTED_STANDBY = 1;
+ /**
+ * The TV input is disconnected.
+ * <p>
+ * State for {@link #getInputState} and {@link
+ * TvInputManager.TvInputListener#onInputStateChanged}.
+ * </p>
+ */
+ public static final int INPUT_STATE_DISCONNECTED = 2;
+
private final ITvInputManager mService;
- // A mapping from an input to the list of its TvInputListenerRecords.
- private final Map<String, List<TvInputListenerRecord>> mTvInputListenerRecordsMap =
- new HashMap<String, List<TvInputListenerRecord>>();
+ private final Object mLock = new Object();
+
+ // @GuardedBy(mLock)
+ private final List<TvInputListenerRecord> mTvInputListenerRecordsList =
+ new LinkedList<TvInputListenerRecord>();
+
+ // A mapping from TV input ID to the state of corresponding input.
+ // @GuardedBy(mLock)
+ private final Map<String, Integer> mStateMap = new ArrayMap<String, Integer>();
// A mapping from the sequence number of a session to its SessionCallbackRecord.
private final SparseArray<SessionCallbackRecord> mSessionCallbackRecordMap =
@@ -63,6 +115,8 @@
private final ITvInputClient mClient;
+ private final ITvInputManagerCallback mCallback;
+
private final int mUserId;
/**
@@ -108,6 +162,29 @@
}
/**
+ * This is called when the video is available, so the TV input starts the playback.
+ *
+ * @param session A {@link TvInputManager.Session} associated with this callback
+ */
+ public void onVideoAvailable(Session session) {
+ }
+
+ /**
+ * This is called when the video is not available, so the TV input stops the playback.
+ *
+ * @param session A {@link TvInputManager.Session} associated with this callback
+ * @param reason The reason why the TV input stopped the playback:
+ * <ul>
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNE}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+ * </ul>
+ */
+ public void onVideoUnavailable(Session session, int reason) {
+ }
+
+ /**
* This is called when a custom event has been sent from this session.
*
* @param session A {@link TvInputManager.Session} associated with this callback
@@ -168,6 +245,24 @@
});
}
+ public void postVideoAvailable() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSessionCallback.onVideoAvailable(mSession);
+ }
+ });
+ }
+
+ public void postVideoUnavailable(final int reason) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSessionCallback.onVideoUnavailable(mSession, reason);
+ }
+ });
+ }
+
public void postSessionEvent(final String eventType, final Bundle eventArgs) {
mHandler.post(new Runnable() {
@Override
@@ -183,13 +278,17 @@
*/
public abstract static class TvInputListener {
/**
- * This is called when the availability status of a given TV input is changed.
+ * This is called when the state of a given TV input is changed.
*
* @param inputId the id of the TV input.
- * @param isAvailable {@code true} if the given TV input is available to show TV programs.
- * {@code false} otherwise.
+ * @param state state of the TV input. The value is one of the following:
+ * <ul>
+ * <li>{@link TvInputManager#INPUT_STATE_CONNECTED}
+ * <li>{@link TvInputManager#INPUT_STATE_CONNECTED_STANDBY}
+ * <li>{@link TvInputManager#INPUT_STATE_DISCONNECTED}
+ * </ul>
*/
- public void onAvailabilityChanged(String inputId, boolean isAvailable) {
+ public void onInputStateChanged(String inputId, int state) {
}
}
@@ -206,11 +305,11 @@
return mListener;
}
- public void postAvailabilityChanged(final String inputId, final boolean isAvailable) {
+ public void postStateChanged(final String inputId, final int state) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mListener.onAvailabilityChanged(inputId, isAvailable);
+ mListener.onInputStateChanged(inputId, state);
}
});
}
@@ -280,6 +379,30 @@
}
@Override
+ public void onVideoAvailable(int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq " + seq);
+ return;
+ }
+ record.postVideoAvailable();
+ }
+ }
+
+ @Override
+ public void onVideoUnavailable(int reason, int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq " + seq);
+ return;
+ }
+ record.postVideoUnavailable(reason);
+ }
+ }
+
+ @Override
public void onSessionEvent(String eventType, Bundle eventArgs, int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
@@ -290,22 +413,23 @@
record.postSessionEvent(eventType, eventArgs);
}
}
-
+ };
+ mCallback = new ITvInputManagerCallback.Stub() {
@Override
- public void onAvailabilityChanged(String inputId, boolean isAvailable) {
- synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
- if (records == null) {
- // Silently ignore - no listener is registered yet.
- return;
- }
- int recordsCount = records.size();
- for (int i = 0; i < recordsCount; i++) {
- records.get(i).postAvailabilityChanged(inputId, isAvailable);
+ public void onInputStateChanged(String inputId, int state) {
+ synchronized (mLock) {
+ mStateMap.put(inputId, state);
+ for (TvInputListenerRecord record : mTvInputListenerRecordsList) {
+ record.postStateChanged(inputId, state);
}
}
}
};
+ try {
+ mService.registerCallback(mCallback, mUserId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "mService.registerCallback failed: " + e);
+ }
}
/**
@@ -322,98 +446,66 @@
}
/**
- * Returns the availability of a given TV input.
+ * Returns the state of a given TV input. It retuns one of the following:
+ * <ul>
+ * <li>{@link #INPUT_STATE_CONNECTED}
+ * <li>{@link #INPUT_STATE_CONNECTED_STANDBY}
+ * <li>{@link #INPUT_STATE_DISCONNECTED}
+ * </ul>
*
* @param inputId the id of the TV input.
- * @throws IllegalArgumentException if the argument is {@code null}.
- * @throws IllegalStateException If there is no {@link TvInputListener} registered on the given
- * TV input.
+ * @throws IllegalArgumentException if the argument is {@code null} or if there is no
+ * {@link TvInputInfo} corresponding to {@code inputId}.
*/
- public boolean getAvailability(String inputId) {
+ public int getInputState(String inputId) {
if (inputId == null) {
throw new IllegalArgumentException("id cannot be null");
}
- synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
- if (records == null || records.size() == 0) {
- throw new IllegalStateException("At least one listener should be registered.");
+ synchronized (mLock) {
+ Integer state = mStateMap.get(inputId);
+ if (state == null) {
+ throw new IllegalArgumentException("Unrecognized input ID: " + inputId);
}
- }
- try {
- return mService.getAvailability(mClient, inputId, mUserId);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
+ return state.intValue();
}
}
/**
- * Registers a {@link TvInputListener} for a given TV input.
+ * Registers a {@link TvInputListener}.
*
- * @param inputId the id of the TV input.
- * @param listener a listener used to monitor status of the given TV input.
+ * @param listener a listener used to monitor status of the TV inputs.
* @param handler a {@link Handler} that the status change will be delivered to.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
- * @hide
*/
- public void registerListener(String inputId, TvInputListener listener, Handler handler) {
- if (inputId == null) {
- throw new IllegalArgumentException("id cannot be null");
- }
+ public void registerListener(TvInputListener listener, Handler handler) {
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
if (handler == null) {
throw new IllegalArgumentException("handler cannot be null");
}
- synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
- if (records == null) {
- records = new ArrayList<TvInputListenerRecord>();
- mTvInputListenerRecordsMap.put(inputId, records);
- try {
- mService.registerCallback(mClient, inputId, mUserId);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- records.add(new TvInputListenerRecord(listener, handler));
+ synchronized (mLock) {
+ mTvInputListenerRecordsList.add(new TvInputListenerRecord(listener, handler));
}
}
/**
- * Unregisters the existing {@link TvInputListener} for a given TV input.
+ * Unregisters the existing {@link TvInputListener}.
*
- * @param inputId the id of the TV input.
- * @param listener the existing listener to remove for the given TV input.
+ * @param listener the existing listener to remove.
* @throws IllegalArgumentException if any of the arguments is {@code null}.
- * @hide
*/
- public void unregisterListener(String inputId, final TvInputListener listener) {
- if (inputId == null) {
- throw new IllegalArgumentException("id cannot be null");
- }
+ public void unregisterListener(final TvInputListener listener) {
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
- synchronized (mTvInputListenerRecordsMap) {
- List<TvInputListenerRecord> records = mTvInputListenerRecordsMap.get(inputId);
- if (records == null) {
- Log.e(TAG, "No listener found for " + inputId);
- return;
- }
- for (Iterator<TvInputListenerRecord> it = records.iterator(); it.hasNext();) {
+ synchronized (mLock) {
+ for (Iterator<TvInputListenerRecord> it = mTvInputListenerRecordsList.iterator();
+ it.hasNext(); ) {
TvInputListenerRecord record = it.next();
if (record.getListener() == listener) {
it.remove();
- }
- }
- if (records.isEmpty()) {
- try {
- mService.unregisterCallback(mClient, inputId, mUserId);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- } finally {
- mTvInputListenerRecordsMap.remove(inputId);
+ break;
}
}
}
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index ba12e2e..3206320 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -82,20 +82,9 @@
*/
public static final String SERVICE_META_DATA = "android.media.tv.input";
- private String mId;
private final Handler mHandler = new ServiceHandler();
private final RemoteCallbackList<ITvInputServiceCallback> mCallbacks =
new RemoteCallbackList<ITvInputServiceCallback>();
- // STOPSHIP: Redesign the API around the availability change. For now, the service will be
- // always available.
- private final boolean mAvailable = true;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mId = TvInputInfo.generateInputIdForComponentName(
- new ComponentName(getPackageName(), getClass().getName()));
- }
@Override
public final IBinder onBind(Intent intent) {
@@ -104,13 +93,6 @@
public void registerCallback(ITvInputServiceCallback cb) {
if (cb != null) {
mCallbacks.register(cb);
- // The first time a callback is registered, the service needs to report its
- // availability status so that the system can know its initial value.
- try {
- cb.onAvailabilityChanged(mId, mAvailable);
- } catch (RemoteException e) {
- Log.e(TAG, "error in onAvailabilityChanged", e);
- }
}
}
@@ -267,6 +249,56 @@
}
/**
+ * Informs the application that video is available and the playback of the TV stream has
+ * been started.
+ */
+ public void dispatchVideoAvailable() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) Log.d(TAG, "dispatchVideoAvailable");
+ mSessionCallback.onVideoAvailable();
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in dispatchVideoAvailable");
+ }
+ }
+ });
+ }
+
+ /**
+ * Informs the application that video is not available, so the TV input cannot continue
+ * playing the TV stream.
+ *
+ * @param reason The reason why the TV input stopped the playback:
+ * <ul>
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNE}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+ * </ul>
+ */
+ public void dispatchVideoUnavailable(final int reason) {
+ if (reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN
+ && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNE
+ && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL
+ && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING) {
+ throw new IllegalArgumentException("Unknown reason: " + reason);
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) Log.d(TAG, "dispatchVideoUnavailable");
+ mSessionCallback.onVideoUnavailable(reason);
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in dispatchVideoUnavailable");
+ }
+ }
+ });
+ }
+
+ /**
* Called when the session is released.
*/
public abstract void onRelease();
@@ -289,7 +321,9 @@
public abstract void onSetStreamVolume(float volume);
/**
- * Tunes to a given channel.
+ * Tunes to a given channel. When the video is available, {@link #dispatchVideoAvailable()}
+ * should be called. Also, {@link #dispatchVideoUnavailable(int)} should be called when the
+ * TV input cannot continue playing the given channel.
*
* @param channelUri The URI of the channel.
* @return {@code true} the tuning was successful, {@code false} otherwise.
@@ -681,7 +715,6 @@
@SuppressLint("HandlerLeak")
private final class ServiceHandler extends Handler {
private static final int DO_CREATE_SESSION = 1;
- private static final int DO_BROADCAST_AVAILABILITY_CHANGE = 2;
@Override
public final void handleMessage(Message msg) {
@@ -707,20 +740,6 @@
args.recycle();
return;
}
- case DO_BROADCAST_AVAILABILITY_CHANGE: {
- boolean isAvailable = (Boolean) msg.obj;
- int n = mCallbacks.beginBroadcast();
- try {
- for (int i = 0; i < n; i++) {
- mCallbacks.getBroadcastItem(i).onAvailabilityChanged(mId, isAvailable);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Unexpected exception", e);
- } finally {
- mCallbacks.finishBroadcast();
- }
- return;
- }
default: {
Log.w(TAG, "Unhandled message code: " + msg.what);
return;
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 7eb27b6..4ac1ba4 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -525,6 +525,29 @@
}
/**
+ * This is called when the video is available, so the TV input starts the playback.
+ *
+ * @param inputId The ID of the TV input bound to this view.
+ */
+ public void onVideoAvailable(String inputId) {
+ }
+
+ /**
+ * This is called when the video is not available, so the TV input stops the playback.
+ *
+ * @param inputId The ID of the TV input bound to this view.
+ * @param reason The reason why the TV input stopped the playback:
+ * <ul>
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_UNKNOWN}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_TUNE}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL}
+ * <li>{@link TvInputManager#VIDEO_UNAVAILABLE_REASON_BUFFERING}
+ * </ul>
+ */
+ public void onVideoUnavailable(String inputId, int reason) {
+ }
+
+ /**
* This is invoked when a custom event from the bound TV input is sent to this view.
*
* @param eventType The type of the event.
@@ -625,6 +648,24 @@
}
}
+ public void onVideoAvailable(Session session) {
+ if (DEBUG) {
+ Log.d(TAG, "onVideoAvailable()");
+ }
+ if (mListener != null) {
+ mListener.onVideoAvailable(mInputId);
+ }
+ }
+
+ public void onVideoUnavailable(Session session, int reason) {
+ if (DEBUG) {
+ Log.d(TAG, "onVideoUnavailable(" + reason + ")");
+ }
+ if (mListener != null) {
+ mListener.onVideoUnavailable(mInputId, reason);
+ }
+ }
+
@Override
public void onSessionEvent(TvInputManager.Session session, String eventType,
Bundle eventArgs) {
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 6a835d6..04ff098 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -197,6 +197,10 @@
return mCodec->flush();
}
+status_t JMediaCodec::reset() {
+ return mCodec->reset();
+}
+
status_t JMediaCodec::queueInputBuffer(
size_t index,
size_t offset, size_t size, int64_t timeUs, uint32_t flags,
@@ -449,13 +453,13 @@
byteBuffer, orderID, nativeByteOrderObj);
env->DeleteLocalRef(me);
me = env->CallObjectMethod(
- byteBuffer, positionID,
- input ? 0 : buffer->offset());
- env->DeleteLocalRef(me);
- me = env->CallObjectMethod(
byteBuffer, limitID,
input ? buffer->capacity() : (buffer->offset() + buffer->size()));
env->DeleteLocalRef(me);
+ me = env->CallObjectMethod(
+ byteBuffer, positionID,
+ input ? 0 : buffer->offset());
+ env->DeleteLocalRef(me);
me = NULL;
env->DeleteLocalRef(nativeByteOrderObj);
@@ -854,6 +858,26 @@
throwExceptionAsNecessary(env, err);
}
+static void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
+ ALOGV("android_media_MediaCodec_reset");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ // should never be here
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ status_t err = codec->reset();
+ if (err != OK) {
+ // treat all errors as fatal for now, though resource not available
+ // errors could be treated as transient.
+ err = 0x80000000;
+ }
+ throwExceptionAsNecessary(env, err);
+}
+
static void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
ALOGV("android_media_MediaCodec_flush");
@@ -1398,6 +1422,8 @@
static JNINativeMethod gMethods[] = {
{ "native_release", "()V", (void *)android_media_MediaCodec_release },
+ { "native_reset", "()V", (void *)android_media_MediaCodec_reset },
+
{ "native_setCallback",
"(Landroid/media/MediaCodec$Callback;)V",
(void *)android_media_MediaCodec_native_setCallback },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 2e650e3..dbccb0f 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -56,6 +56,7 @@
status_t start();
status_t stop();
+ status_t reset();
status_t flush();
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 3dbf77b..52e9910 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -36,6 +36,8 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/NuMediaExtractor.h>
+#include <nativehelper/ScopedLocalRef.h>
+
#include "android_util_Binder.h"
namespace android {
@@ -206,12 +208,12 @@
size_t dstSize;
jbyteArray byteArray = NULL;
- if (dst == NULL) {
- jclass byteBufClass = env->FindClass("java/nio/ByteBuffer");
- CHECK(byteBufClass != NULL);
+ ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
+ CHECK(byteBufClass.get() != NULL);
+ if (dst == NULL) {
jmethodID arrayID =
- env->GetMethodID(byteBufClass, "array", "()[B");
+ env->GetMethodID(byteBufClass.get(), "array", "()[B");
CHECK(arrayID != NULL);
byteArray =
@@ -251,6 +253,24 @@
*sampleSize = buffer->size();
+ jmethodID positionID = env->GetMethodID(
+ byteBufClass.get(), "position", "(I)Ljava/nio/Buffer;");
+
+ CHECK(positionID != NULL);
+
+ jmethodID limitID = env->GetMethodID(
+ byteBufClass.get(), "limit", "(I)Ljava/nio/Buffer;");
+
+ CHECK(limitID != NULL);
+
+ jobject me = env->CallObjectMethod(
+ byteBuf, limitID, offset + *sampleSize);
+ env->DeleteLocalRef(me);
+ me = env->CallObjectMethod(
+ byteBuf, positionID, offset);
+ env->DeleteLocalRef(me);
+ me = NULL;
+
return OK;
}
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 1685a44..5646740 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -157,6 +157,10 @@
return;
}
sp<Camera> c = get_native_camera(env, camera, NULL);
+ if (c == NULL) {
+ // get_native_camera will throw an exception in this case
+ return;
+ }
sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
process_media_recorder_call(env, mr->setCamera(c->remote(), c->getRecordingProxy()),
"java/lang/RuntimeException", "setCamera failed.");
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 62795b6..4bf3e4f 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -28,7 +28,7 @@
<string name="menu_open" msgid="432922957274920903">"เปิด"</string>
<string name="menu_save" msgid="2394743337684426338">"บันทึก"</string>
<string name="menu_share" msgid="3075149983979628146">"แชร์"</string>
- <string name="menu_delete" msgid="8138799623850614177">"นำออก"</string>
+ <string name="menu_delete" msgid="8138799623850614177">"ลบ"</string>
<string name="menu_select" msgid="8711270657353563424">"เลือก \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
<string name="mode_selected_count" msgid="459111894725594625">"เลือกไว้ <xliff:g id="COUNT">%1$d</xliff:g>"</string>
<string name="sort_name" msgid="9183560467917256779">"ตามชื่อ"</string>
@@ -50,6 +50,6 @@
<string name="pref_device_size" msgid="3542106883278997222">"แสดงขนาดของอุปกรณ์"</string>
<string name="empty" msgid="7858882803708117596">"ไม่มีรายการ"</string>
<string name="toast_no_application" msgid="1339885974067891667">"ไม่สามารถเปิดไฟล์ได้"</string>
- <string name="toast_failed_delete" msgid="2180678019407244069">"ไม่สามารถนำออกเอกสารบางรายการ"</string>
+ <string name="toast_failed_delete" msgid="2180678019407244069">"ไม่สามารถลบเอกสารบางรายการ"</string>
<string name="share_via" msgid="8966594246261344259">"แชร์ผ่าน"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index afd8b63..4aefd0d 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"文件"</string>
- <string name="title_open" msgid="4353228937663917801">"開啟自"</string>
+ <string name="title_open" msgid="4353228937663917801">"開啟檔案"</string>
<string name="title_save" msgid="2433679664882857999">"儲存至"</string>
<string name="menu_create_dir" msgid="5947289605844398389">"建立資料夾"</string>
<string name="menu_grid" msgid="6878021334497835259">"格狀檢視"</string>
diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml
index 51f87a3..c724d85 100644
--- a/packages/Keyguard/res/values-th/strings.xml
+++ b/packages/Keyguard/res/values-th/strings.xml
@@ -58,7 +58,7 @@
<string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"การควบคุมสื่อ"</string>
<string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"เริ่มเรียงลำดับวิดเจ็ตใหม่"</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"เรียงลำดับวิดเจ็ตใหม่เสร็จแล้ว"</string>
- <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"นำออกวิดเจ็ต <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> แล้ว"</string>
+ <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"ลบวิดเจ็ต <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> แล้ว"</string>
<string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"ขยายพื้นที่ปลดล็อก"</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"การปลดล็อกด้วยการเลื่อน"</string>
<string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"การปลดล็อกด้วยรูปแบบ"</string>
@@ -77,14 +77,14 @@
<string name="keyguard_accessibility_transport_heart_description" msgid="2336943232474689887">"หัวใจ"</string>
<string name="keyguard_accessibility_show_bouncer" msgid="5425837272418176176">"ปลดล็อกเพื่อดำเนินการต่อ"</string>
<string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"ยกเลิกการเปิดใช้งานแล้ว"</string>
- <string name="keyguard_accessibility_delete_widget_start" msgid="4096550552634391451">"ลาก <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> เพื่อนำออก"</string>
- <string name="keyguard_accessibility_delete_widget_end" msgid="508833506780909393">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> จะไม่ถูกนำออก"</string>
+ <string name="keyguard_accessibility_delete_widget_start" msgid="4096550552634391451">"ลาก <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> เพื่อลบ"</string>
+ <string name="keyguard_accessibility_delete_widget_end" msgid="508833506780909393">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> จะไม่ถูกลบ"</string>
<string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
<string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
<string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
<string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
<string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"ยกเลิก"</string>
- <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"นำออก"</string>
+ <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"ลบ"</string>
<string name="keyboardview_keycode_done" msgid="1992571118466679775">"เสร็จสิ้น"</string>
<string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"เปลี่ยนโหมด"</string>
<string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
@@ -135,7 +135,7 @@
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกแท็บเล็ตโดยใช้บัญชีอีเมล\n\n โปรดลองอีกครั้งใน <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้ับัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%d</xliff:g> วินาที"</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
- <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"นำออก"</string>
+ <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"ลบ"</string>
<string name="kg_password_wrong_pin_code_pukked" msgid="30531039455764924">"รหัส PIN ของซิมไม่ถูกต้อง ตอนนี้คุณต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์ของคุณ"</string>
<plurals name="kg_password_wrong_pin_code">
<item quantity="one" msgid="8134313997799638254">"รหัส PIN ของซิมไม่ถูกต้อง คุณพยายามได้อีก <xliff:g id="NUMBER">%d</xliff:g> ครั้งก่อนที่จะต้องติดต่อผู้ให้บริการเพื่อปลดล็อกอุปกรณ์ของคุณ"</item>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index 58bda92..e1f0bd8 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -29,12 +29,12 @@
<string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Nhập mật khẩu để mở khóa"</string>
<string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"Nhập mã PIN để mở khóa"</string>
<string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Mã PIN không chính xác."</string>
- <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khóa, hãy nhấn vào Trình đơn sau đó nhấn 0."</string>
+ <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khóa, hãy nhấn vào Menu sau đó nhấn 0."</string>
<string name="faceunlock_multiple_failures" msgid="754137583022792429">"Đã vượt quá số lần Mở khóa bằng khuôn mặt tối đa"</string>
<string name="keyguard_charged" msgid="3272223906073492454">"Pin đầy"</string>
<string name="keyguard_plugged_in" msgid="9087497435553252863">"Đang sạc"</string>
<string name="keyguard_low_battery" msgid="8143808018719173859">"Kết nối bộ sạc của bạn."</string>
- <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"Nhấn vào Trình đơn để mở khóa."</string>
+ <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"Nhấn vào Menu để mở khóa."</string>
<string name="keyguard_network_locked_message" msgid="9169717779058037168">"Mạng đã bị khóa"</string>
<string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Không có thẻ SIM nào"</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"Không có thẻ SIM nào trong máy tính bảng."</string>
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 223013f..9a62864 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -69,12 +69,12 @@
<activity
android:name=".ui.SelectPrinterActivity"
android:label="@string/all_printers_label"
- android:theme="@style/SelectPrinterActivityTheme"
+ android:theme="@android:style/Theme.Material.Settings"
android:exported="false">
</activity>
<receiver
- android:name=".NotificationController$NotificationBroadcastReceiver"
+ android:name=".model.NotificationController$NotificationBroadcastReceiver"
android:exported="false" >
</receiver>
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_check_circle.png b/packages/PrintSpooler/res/drawable-hdpi/ic_check_circle.png
new file mode 100644
index 0000000..4ad5417
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-hdpi/ic_check_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png
new file mode 100644
index 0000000..b6a5eb5
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less_24dp.png b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less_24dp.png
deleted file mode 100644
index d2e5408..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_less_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png
new file mode 100644
index 0000000..4e36bd2
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more_24dp.png b/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more_24dp.png
deleted file mode 100644
index f4c4b0c..0000000
--- a/packages/PrintSpooler/res/drawable-hdpi/ic_expand_more_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_remove_circle.png b/packages/PrintSpooler/res/drawable-hdpi/ic_remove_circle.png
new file mode 100644
index 0000000..ef053b6
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-hdpi/ic_remove_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_check_circle.png b/packages/PrintSpooler/res/drawable-mdpi/ic_check_circle.png
new file mode 100644
index 0000000..f66065a
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-mdpi/ic_check_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png
new file mode 100644
index 0000000..428a946
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_less.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png
new file mode 100644
index 0000000..fbbd094
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-mdpi/ic_expand_more.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_remove_circle.png b/packages/PrintSpooler/res/drawable-mdpi/ic_remove_circle.png
new file mode 100644
index 0000000..7e044ac
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-mdpi/ic_remove_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_check_circle.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_check_circle.png
new file mode 100644
index 0000000..d8ea4d29
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xhdpi/ic_check_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png
new file mode 100644
index 0000000..6161c20
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less_24dp.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less_24dp.png
deleted file mode 100644
index f0074275..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_less_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png
new file mode 100644
index 0000000..3a89805
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more_24dp.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more_24dp.png
deleted file mode 100644
index 43debb3..0000000
--- a/packages/PrintSpooler/res/drawable-xhdpi/ic_expand_more_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_remove_circle.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_remove_circle.png
new file mode 100644
index 0000000..622989c
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xhdpi/ic_remove_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_check_circle.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_check_circle.png
new file mode 100644
index 0000000..ac36eba
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xxhdpi/ic_check_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png
new file mode 100644
index 0000000..52a52d9
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less_24dp.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less_24dp.png
deleted file mode 100644
index 39bc2ba..0000000
--- a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_less_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png
new file mode 100644
index 0000000..15e6abd
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more_24dp.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more_24dp.png
deleted file mode 100644
index 664f3f2..0000000
--- a/packages/PrintSpooler/res/drawable-xxhdpi/ic_expand_more_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxhdpi/ic_remove_circle.png b/packages/PrintSpooler/res/drawable-xxhdpi/ic_remove_circle.png
new file mode 100644
index 0000000..303ccfb
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xxhdpi/ic_remove_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_check_circle.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_check_circle.png
new file mode 100644
index 0000000..1737f0a
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_check_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png
new file mode 100644
index 0000000..46811a1
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less_24dp.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less_24dp.png
deleted file mode 100644
index fe9c539..0000000
--- a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_less_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png
new file mode 100644
index 0000000..141f28b
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more_24dp.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more_24dp.png
deleted file mode 100644
index 18d075c..0000000
--- a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_expand_more_24dp.png
+++ /dev/null
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xxxhdpi/ic_remove_circle.png b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_remove_circle.png
new file mode 100644
index 0000000..e9c6252
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xxxhdpi/ic_remove_circle.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable/ic_expand_less.xml b/packages/PrintSpooler/res/drawable/ic_expand_less.xml
index b0c7d51..6f1ece1 100644
--- a/packages/PrintSpooler/res/drawable/ic_expand_less.xml
+++ b/packages/PrintSpooler/res/drawable/ic_expand_less.xml
@@ -20,7 +20,7 @@
<item
android:state_checked="true">
<bitmap
- android:src="@drawable/ic_expand_less_24dp"
+ android:src="@drawable/ic_expand_less"
android:tint="?android:attr/colorControlActivated">
</bitmap>
</item>
@@ -28,14 +28,14 @@
<item
android:state_pressed="true">
<bitmap
- android:src="@drawable/ic_expand_less_24dp"
+ android:src="@drawable/ic_expand_less"
android:tint="?android:attr/colorControlActivated">
</bitmap>
</item>
<item>
<bitmap
- android:src="@drawable/ic_expand_less_24dp"
+ android:src="@drawable/ic_expand_less"
android:tint="?android:attr/colorControlNormal">
</bitmap>
</item>
diff --git a/packages/PrintSpooler/res/drawable/ic_expand_more.xml b/packages/PrintSpooler/res/drawable/ic_expand_more.xml
index b809c25..8d71452 100644
--- a/packages/PrintSpooler/res/drawable/ic_expand_more.xml
+++ b/packages/PrintSpooler/res/drawable/ic_expand_more.xml
@@ -20,7 +20,7 @@
<item
android:state_checked="true">
<bitmap
- android:src="@drawable/ic_expand_more_24dp"
+ android:src="@drawable/ic_expand_more"
android:tint="?android:attr/colorControlActivated">
</bitmap>
</item>
@@ -28,14 +28,14 @@
<item
android:state_pressed="true">
<bitmap
- android:src="@drawable/ic_expand_more_24dp"
+ android:src="@drawable/ic_expand_more"
android:tint="?android:attr/colorControlActivated">
</bitmap>
</item>
<item>
<bitmap
- android:src="@drawable/ic_expand_more_24dp"
+ android:src="@drawable/ic_expand_more"
android:tint="?android:attr/colorControlNormal">
</bitmap>
</item>
diff --git a/packages/PrintSpooler/res/drawable/ic_search.xml b/packages/PrintSpooler/res/drawable/ic_search.xml
new file mode 100644
index 0000000..991fa38b
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/ic_search.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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true">
+
+ <item
+ android:state_checked="true">
+ <bitmap
+ android:src="@*android:drawable/ic_menu_search"
+ android:tint="?android:attr/colorControlActivated">
+ </bitmap>
+ </item>
+
+ <item
+ android:state_pressed="true">
+ <bitmap
+ android:src="@*android:drawable/ic_menu_search"
+ android:tint="?android:attr/colorControlActivated">
+ </bitmap>
+ </item>
+
+ <item>
+ <bitmap
+ android:src="@*android:drawable/ic_menu_search"
+ android:tint="?android:attr/colorControlNormal">
+ </bitmap>
+ </item>
+
+</selector>
diff --git a/packages/PrintSpooler/res/drawable/page_selector_background.xml b/packages/PrintSpooler/res/drawable/page_selector_background.xml
new file mode 100644
index 0000000..7f1da31
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable/page_selector_background.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:enterFadeDuration="@android:integer/config_shortAnimTime"
+ android:exitFadeDuration="@android:integer/config_shortAnimTime">
+
+ <item
+ android:state_selected="true">
+ <bitmap
+ android:src="@drawable/ic_check_circle"
+ android:tint="@color/promoted_action_background_color">
+ </bitmap>
+ </item>
+
+ <item>
+ <bitmap
+ android:src="@drawable/ic_remove_circle"
+ android:tint="@color/promoted_action_background_color">
+ </bitmap>
+ </item>
+
+</selector>
diff --git a/packages/PrintSpooler/res/drawable/print_button_background.xml b/packages/PrintSpooler/res/drawable/print_button_background.xml
index 7b9aea5..aec8474 100644
--- a/packages/PrintSpooler/res/drawable/print_button_background.xml
+++ b/packages/PrintSpooler/res/drawable/print_button_background.xml
@@ -18,7 +18,7 @@
android:shape="oval">
<solid
- android:color="#FF00E5FF">
+ android:color="@color/promoted_action_background_color">
</solid>
<size
diff --git a/packages/PrintSpooler/res/layout/preview_page.xml b/packages/PrintSpooler/res/layout/preview_page.xml
index 0e314d1..509a1d2 100644
--- a/packages/PrintSpooler/res/layout/preview_page.xml
+++ b/packages/PrintSpooler/res/layout/preview_page.xml
@@ -31,7 +31,7 @@
<RelativeLayout
android:id="@+id/page_footer"
android:layout_width="fill_parent"
- android:layout_height="?android:attr/listPreferredItemHeightSmall"
+ android:layout_height="32dip"
android:background="@*android:color/material_grey_500"
android:orientation="horizontal">
@@ -40,18 +40,19 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorPrimary">
</TextView>
- <CheckBox
+ <ImageView
android:id="@+id/page_selector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dip"
android:layout_alignParentEnd="true"
- android:layout_centerVertical="true">
- </CheckBox>
+ android:layout_centerVertical="true"
+ android:background="@drawable/page_selector_background">
+ </ImageView>
</RelativeLayout>
diff --git a/packages/PrintSpooler/res/layout/print_activity.xml b/packages/PrintSpooler/res/layout/print_activity.xml
index 8896a7b..3905646 100644
--- a/packages/PrintSpooler/res/layout/print_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_activity.xml
@@ -29,7 +29,7 @@
android:layout_height="wrap_content"
android:padding="16dip"
android:elevation="@dimen/preview_controls_elevation"
- android:background="?android:attr/colorForegroundInverse">
+ android:background="?android:attr/colorPrimary">
<Spinner
android:id="@+id/destination_spinner"
@@ -51,7 +51,7 @@
android:paddingEnd="16dip"
android:orientation="horizontal"
android:elevation="@dimen/preview_controls_elevation"
- android:background="?android:attr/colorForegroundInverse">
+ android:background="?android:attr/colorPrimary">
<TextView
android:layout_width="wrap_content"
diff --git a/packages/PrintSpooler/res/layout/print_activity_controls.xml b/packages/PrintSpooler/res/layout/print_activity_controls.xml
index 2da0714..ef6044a 100644
--- a/packages/PrintSpooler/res/layout/print_activity_controls.xml
+++ b/packages/PrintSpooler/res/layout/print_activity_controls.xml
@@ -22,7 +22,7 @@
android:layout_height="wrap_content"
android:orientation="vertical"
android:elevation="@dimen/preview_controls_elevation"
- android:background="?android:attr/colorForegroundInverse">
+ android:background="?android:attr/colorPrimary">
<LinearLayout
android:id="@+id/draggable_content"
@@ -61,6 +61,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
style="?android:attr/editTextStyle"
+ android:singleLine="true"
+ android:ellipsize="end"
android:inputType="numberDecimal">
</view>
@@ -88,8 +90,7 @@
<Spinner
android:id="@+id/paper_size_spinner"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="@style/PrintOptionSpinnerStyle">
+ android:layout_height="wrap_content">
</Spinner>
</LinearLayout>
@@ -116,8 +117,7 @@
<Spinner
android:id="@+id/color_spinner"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="@style/PrintOptionSpinnerStyle">
+ android:layout_height="wrap_content">
</Spinner>
</LinearLayout>
@@ -144,8 +144,7 @@
<Spinner
android:id="@+id/orientation_spinner"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="@style/PrintOptionSpinnerStyle">
+ android:layout_height="wrap_content">
</Spinner>
</LinearLayout>
@@ -160,21 +159,19 @@
<!-- Range options -->
<TextView
- android:id="@+id/range_options_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dip"
android:layout_marginStart="12dip"
android:textAppearance="?android:attr/textAppearanceSmall"
android:labelFor="@+id/range_options_spinner"
- android:text="@string/page_count_unknown">
+ android:text="@string/label_pages">
</TextView>
<Spinner
android:id="@+id/range_options_spinner"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="@style/PrintOptionSpinnerStyle">
+ android:layout_height="wrap_content">
</Spinner>
</LinearLayout>
@@ -207,7 +204,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|fill_horizontal"
- style="@style/PrintOptionEditTextStyle"
+ android:singleLine="true"
+ android:ellipsize="end"
android:visibility="visible"
android:inputType="textNoSuggestions">
</view>
diff --git a/packages/PrintSpooler/res/layout/printer_list_item.xml b/packages/PrintSpooler/res/layout/printer_list_item.xml
index 1f5efbc..7bc144a 100644
--- a/packages/PrintSpooler/res/layout/printer_list_item.xml
+++ b/packages/PrintSpooler/res/layout/printer_list_item.xml
@@ -49,7 +49,7 @@
android:ellipsize="end"
android:textIsSelectable="false"
android:gravity="top|start"
- android:textColor="?android:attr/textColorSecondary"
+ android:textColor="?android:attr/textColorPrimary"
android:duplicateParentState="true">
</TextView>
@@ -62,7 +62,7 @@
android:ellipsize="end"
android:textIsSelectable="false"
android:visibility="gone"
- android:textColor="?android:attr/textColorSecondary"
+ android:textColor="?android:attr/textColorPrimary"
android:duplicateParentState="true">
</TextView>
diff --git a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
index 1fb221a..14403a1 100644
--- a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
@@ -17,8 +17,6 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:paddingStart="8dip"
- android:paddingEnd="8dip"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:orientation="vertical"
android:gravity="start|center_vertical">
@@ -27,12 +25,13 @@
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ style="?android:attr/spinnerDropDownItemStyle"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorPrimary"
android:singleLine="true"
android:ellipsize="end"
android:textIsSelectable="false"
android:gravity="top|left"
- android:textColor="?android:attr/textColorPrimary"
android:duplicateParentState="true">
</TextView>
@@ -40,12 +39,13 @@
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ style="?android:attr/spinnerDropDownItemStyle"
android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorPrimary"
android:singleLine="true"
android:ellipsize="end"
android:textIsSelectable="false"
android:visibility="gone"
- android:textColor="?android:attr/textColorPrimary"
android:duplicateParentState="true">
</TextView>
diff --git a/packages/PrintSpooler/res/menu/select_printer_activity.xml b/packages/PrintSpooler/res/menu/select_printer_activity.xml
index ee62f9f..8da5769 100644
--- a/packages/PrintSpooler/res/menu/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/menu/select_printer_activity.xml
@@ -19,7 +19,7 @@
<item
android:id="@+id/action_search"
android:title="@string/search"
- android:icon="@*android:drawable/ic_menu_search_holo_light"
+ android:icon="@*android:drawable/ic_search"
android:actionViewClass="android.widget.SearchView"
android:showAsAction="ifRoom|collapseActionView"
android:alphabeticShortcut="f"
diff --git a/packages/PrintSpooler/res/values-af/strings.xml b/packages/PrintSpooler/res/values-af/strings.xml
index 2810785..f343f0b 100644
--- a/packages/PrintSpooler/res/values-af/strings.xml
+++ b/packages/PrintSpooler/res/values-af/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Papiergrootte:"</string>
<string name="label_color" msgid="1108690305218188969">"Kleur"</string>
<string name="label_orientation" msgid="2853142581990496477">"Oriëntasie"</string>
- <string name="label_pages" msgid="6300874667546617333">"Bladsye (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"bv. 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"Drukvoorskou"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Installeer PDF-bekyker vir voorskou"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Drukkerprogram het omgeval"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Bladsye"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Genereer uitdruktaak"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Stoor as PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Alle drukkers…"</string>
<string name="print_dialog" msgid="32628687461331979">"Drukdialoog"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Deursoek"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Alle drukkers"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Voeg diens by"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portret"</item>
<item msgid="3199660090246166812">"Landskap"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Alles"</item>
- <item msgid="6812869625222503603">"Reikwydte"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Kon nie na lêer skryf nie"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Kon nie uitdruktaak genereer nie"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Jammer, dit het nie gewerk nie. Probeer weer."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Herprobeer"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Drukker nie beskikbaar nie"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Kanselleer tans …"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Hierdie drukker is nie op die oomblik beskikbaar nie."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Berei tans voorskou voor …"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml
index dfcc4a1..ee974a8 100644
--- a/packages/PrintSpooler/res/values-am/strings.xml
+++ b/packages/PrintSpooler/res/values-am/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"የወረቀት መጠን፦"</string>
<string name="label_color" msgid="1108690305218188969">"ቀለም"</string>
<string name="label_orientation" msgid="2853142581990496477">"አቀማመጠ ገፅ"</string>
- <string name="label_pages" msgid="6300874667546617333">"ገጾች (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"ለምሳሌ፦ 1–5,8,11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"የህትመት ቅድመ እይታ"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"ለቅድመ-እይታ የፒ ዲ ኤፍ መመልከቻ ይጫኑ"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"የአታሚ መተግበሪያ ተበላሽቷል"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"ገፆች"</string>
<string name="generating_print_job" msgid="3119608742651698916">"የህትመት ስራን በማመንጨት ላይ"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"እንደ ፒዲኤፍ አስቀምጥ"</string>
<string name="all_printers" msgid="5018829726861876202">"ሁሉም አታሚዎች…"</string>
<string name="print_dialog" msgid="32628687461331979">"የህትመት መገናኛ"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"ፍለጋ"</string>
<string name="all_printers_label" msgid="3178848870161526399">"ሁሉም አታሚዎች"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"አገልግሎት አክል"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"የቁም"</item>
<item msgid="3199660090246166812">"የወርድ"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"ሁሉም"</item>
- <item msgid="6812869625222503603">"ምጥጥነ ገጽታ"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"ወደ ፋይል መጻፍ አልተቻለም"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"የህትመት ስራን ማመንጨት አልተቻለም"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"ይቅርታ፣ ያ አልሰራም። እንደገና ይሞክሩ።"</string>
<string name="print_error_retry" msgid="1426421728784259538">"እንደገና ይሞክሩ"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"አታሚ አይገኝም"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"በመሰረዝ ላይ…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"አታሚው አሁን አይገኝም።"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"ቅድመ እይታን በማዘጋጀት ላይ…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ar/strings.xml b/packages/PrintSpooler/res/values-ar/strings.xml
index ca6100b..7c9a7b7 100644
--- a/packages/PrintSpooler/res/values-ar/strings.xml
+++ b/packages/PrintSpooler/res/values-ar/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"حجم الورق:"</string>
<string name="label_color" msgid="1108690305218188969">"ألوان"</string>
<string name="label_orientation" msgid="2853142581990496477">"الاتجاه"</string>
- <string name="label_pages" msgid="6300874667546617333">"الصفحات (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"على سبيل المثال، 1—5،8،11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"معاينة قبل الطباعة"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"تثبيت برنامج عرض PDF للمعاينة"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"تعطّل تطبيق الطباعة"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"الصفحات"</string>
<string name="generating_print_job" msgid="3119608742651698916">"جارٍ إنشاء مهمة الطباعة"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"حفظ بتنسيق PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"جميع الطابعات…"</string>
<string name="print_dialog" msgid="32628687461331979">"مربع حوار الطباعة"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"بحث"</string>
<string name="all_printers_label" msgid="3178848870161526399">"جميع الطابعات"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"إضافة خدمة"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"عمودي"</item>
<item msgid="3199660090246166812">"أفقي"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"الكل"</item>
- <item msgid="6812869625222503603">"النطاق"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"تعذرت الكتابة إلى الملف"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"تعذر إنشاء عملية الطباعة"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"عذرًا، هذا لا يعمل. أعد المحاولة."</string>
<string name="print_error_retry" msgid="1426421728784259538">"إعادة المحاولة"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"الطابعة غير متاحة"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"جارٍ الإلغاء…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"الطابعة ليست متوفرة في الوقت الحالي."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"جارٍ تحضير المعاينة…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-bg/strings.xml b/packages/PrintSpooler/res/values-bg/strings.xml
index 6c52d16..95af506 100644
--- a/packages/PrintSpooler/res/values-bg/strings.xml
+++ b/packages/PrintSpooler/res/values-bg/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Размер на хартията:"</string>
<string name="label_color" msgid="1108690305218188969">"Цвят"</string>
<string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string>
- <string name="label_pages" msgid="6300874667546617333">"Страници (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"напр. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Визуализация за печат"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Инсталиране на визуализатор на PDF"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Получи се срив в приложението за отпечатване"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Страници"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Заданието за печат се генерира"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Запазване като PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Всички принтери…"</string>
<string name="print_dialog" msgid="32628687461331979">"Диалогов прозорец за отпечатване"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Търсене"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Всички принтери"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Добавяне на услуга"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Вертикално"</item>
<item msgid="3199660090246166812">"Хоризонтално"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Всички"</item>
- <item msgid="6812869625222503603">"Поредица"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Не можа да се запише във файла"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Заданието за отпечатване не можа да се генерира"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"За съжаление това не проработи. Опитайте отново."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Нов опит"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Няма достъп до принтера"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Анулира се…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"В момента този принтер не е налице."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Визуализацията се подготвя…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ca/strings.xml b/packages/PrintSpooler/res/values-ca/strings.xml
index 53190ab..b2ae2e0 100644
--- a/packages/PrintSpooler/res/values-ca/strings.xml
+++ b/packages/PrintSpooler/res/values-ca/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Mida del paper:"</string>
<string name="label_color" msgid="1108690305218188969">"Color"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientació"</string>
- <string name="label_pages" msgid="6300874667546617333">"Pàgines (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"p. ex. 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Visualització prèvia impressió"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Instal·la un lector de PDF per a visualitz. prèvia"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"L\'aplicació d\'impressió ha fallat"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Pàgines"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generant tasca impressió"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Desa com a PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Totes les impressores…"</string>
<string name="print_dialog" msgid="32628687461331979">"Diàleg d\'impressió"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Cerca"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Totes les impressores"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Afegeix un servei"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Vertical"</item>
<item msgid="3199660090246166812">"Horitzontal"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Tots"</item>
- <item msgid="6812869625222503603">"Interval"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"No s\'ha pogut escriure al fitxer."</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"No s\'ha pogut generar la tasca d\'impressió"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"No ha funcionat. Torna-ho a provar."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Torna-ho a provar"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Impressora no disponible"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"S\'està cancel·lant…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Ara mateix, aquesta impressora no està disponible."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"S\'està preparant la visualització prèvia..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-cs/strings.xml b/packages/PrintSpooler/res/values-cs/strings.xml
index 68e8ec3..aee5adc 100644
--- a/packages/PrintSpooler/res/values-cs/strings.xml
+++ b/packages/PrintSpooler/res/values-cs/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Velikost papíru:"</string>
<string name="label_color" msgid="1108690305218188969">"Barva"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientace"</string>
- <string name="label_pages" msgid="6300874667546617333">"STRÁNKY (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"např. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Náhled tisku"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Nainstalovat prohlížeč PDF (umožní náhled)"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Aplikace tisku selhala"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Stránky"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generování úlohy tisku"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Uložit ve formátu PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Všechny tiskárny…"</string>
<string name="print_dialog" msgid="32628687461331979">"Dialog tisku"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Hledat"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Všechny tiskárny"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Přidat službu"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Na výšku"</item>
<item msgid="3199660090246166812">"Na šířku"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Vše"</item>
- <item msgid="6812869625222503603">"Rozsah"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Do souboru nelze zapisovat."</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Tiskovou úlohu nelze vytvořit"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Litujeme, nepodařilo se. Zkuste to znovu."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Opakovat"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Tiskárna je nedostupná."</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Rušení…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Tiskárna aktuálně není k dispozici."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Příprava náhledu…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 368c3768..7c841e2 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Papirstørrelse:"</string>
<string name="label_color" msgid="1108690305218188969">"Farve"</string>
<string name="label_orientation" msgid="2853142581990496477">"Retning"</string>
- <string name="label_pages" msgid="6300874667546617333">"Sider (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"f.eks. 1-5,8,11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Vis udskrift"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Installer et PDF-visningsprog. for at se eksempel"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Udskrivningsapp gik ned"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Sider"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Udskriften generes"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Gem som PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Alle printere..."</string>
<string name="print_dialog" msgid="32628687461331979">"Udskriftsdialog"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> af <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Søg"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Alle printere"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Tilføj tjeneste"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Stående"</item>
<item msgid="3199660090246166812">"Liggende"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Alle"</item>
- <item msgid="6812869625222503603">"Interval"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Der kunne ikke skrives til filen"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Der kunne ikke genereres et udskriftsjob"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Det virkede desværre ikke. Prøv igen."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Prøv igen"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Printeren er utilgængelig"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Annullerer…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Denne printer er i øjeblikket ikke tilgængelig."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Eksempelvisning forberedes..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-de/strings.xml b/packages/PrintSpooler/res/values-de/strings.xml
index 8dc52a2..3071fe4 100644
--- a/packages/PrintSpooler/res/values-de/strings.xml
+++ b/packages/PrintSpooler/res/values-de/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Papierformat:"</string>
<string name="label_color" msgid="1108690305218188969">"Farbe"</string>
<string name="label_orientation" msgid="2853142581990496477">"Ausrichtung"</string>
- <string name="label_pages" msgid="6300874667546617333">"Seiten (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"z. B. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Vorschau drucken"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"PDF-Viewer für Vorschau installieren"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Druck-App abgestürzt"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Seiten"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Druckauftrag wird generiert..."</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Als PDF speichern"</string>
<string name="all_printers" msgid="5018829726861876202">"Alle Drucker…"</string>
<string name="print_dialog" msgid="32628687461331979">"Druckdialogfeld"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Suchen"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Alle Drucker"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Dienst hinzufügen"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Hochformat"</item>
<item msgid="3199660090246166812">"Querformat"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Alle"</item>
- <item msgid="6812869625222503603">"Bereich"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Fehler beim Schreiben in Datei"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Druckauftrag konnte nicht generiert werden."</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Fehler. Bitte versuchen Sie es erneut."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Erneut versuchen"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Drucker nicht verfügbar"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Vorgang wird abgebrochen..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Dieser Drucker ist momentan nicht verfügbar."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Vorschau wird vorbereitet…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-el/strings.xml b/packages/PrintSpooler/res/values-el/strings.xml
index 542caf9..389b19d 100644
--- a/packages/PrintSpooler/res/values-el/strings.xml
+++ b/packages/PrintSpooler/res/values-el/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Μέγεθος χαρτιού:"</string>
<string name="label_color" msgid="1108690305218188969">"Χρώμα"</string>
<string name="label_orientation" msgid="2853142581990496477">"Προσανατολισμός"</string>
- <string name="label_pages" msgid="6300874667546617333">"Σελίδες (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"π.χ. 1-5,8,11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Προεπισκόπηση εκτύπωσης"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Εγκαταστήστε το PDF viewer για προεπισκόπηση"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Διακοπή λειτουργίας εφαρμογής εκτύπωσης"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Σελίδες"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Δημιουργία εργασίας εκτύπωσης"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Αποθήκευση ως PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Όλοι οι εκτυπωτές…"</string>
<string name="print_dialog" msgid="32628687461331979">"Πλαίσιο διαλόγου εκτύπωσης"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Αναζήτηση"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Όλοι οι εκτυπωτές"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Προσθήκη υπηρεσίας"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Πορτραίτο"</item>
<item msgid="3199660090246166812">"Οριζόντια"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Όλα"</item>
- <item msgid="6812869625222503603">"Εύρος"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Δεν ήταν δυνατή η εγγραφή στο αρχείο"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Δεν ήταν δυνατή η δημιουργία εργασίας εκτύπωσης"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Δυστυχώς, αυτό δεν λειτούργησε. Δοκιμάστε ξανά."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Επανάληψη"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Ο εκτυπωτής δεν είναι διαθέσιμος"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Ακύρωση…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Αυτός ο εκτυπωτής δεν είναι διαθέσιμος αυτήν τη στιγμή."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Προετοιμασία προεπισκόπησης…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-en-rGB/strings.xml b/packages/PrintSpooler/res/values-en-rGB/strings.xml
index 3728437..366eb1f 100644
--- a/packages/PrintSpooler/res/values-en-rGB/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rGB/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Paper size:"</string>
<string name="label_color" msgid="1108690305218188969">"Colour"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
- <string name="label_pages" msgid="6300874667546617333">"Pages (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"e.g. 1–5,8,11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Print preview"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Install PDF viewer for preview"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Printing app crashed"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Pages"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generating print job"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Save as PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"All printers…"</string>
<string name="print_dialog" msgid="32628687461331979">"Print dialogue"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Search"</string>
<string name="all_printers_label" msgid="3178848870161526399">"All printers"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Add service"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portrait"</item>
<item msgid="3199660090246166812">"Landscape"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"All"</item>
- <item msgid="6812869625222503603">"Range"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Couldn\'t write to file"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Couldn\'t generate print job"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Sorry, that didn\'t work. Try again."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Retry"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Printer unavailable"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Cancelling…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"This printer isn\'t available right now."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Preparing preview…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-en-rIN/strings.xml b/packages/PrintSpooler/res/values-en-rIN/strings.xml
index 3728437..366eb1f 100644
--- a/packages/PrintSpooler/res/values-en-rIN/strings.xml
+++ b/packages/PrintSpooler/res/values-en-rIN/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Paper size:"</string>
<string name="label_color" msgid="1108690305218188969">"Colour"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
- <string name="label_pages" msgid="6300874667546617333">"Pages (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"e.g. 1–5,8,11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Print preview"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Install PDF viewer for preview"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Printing app crashed"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Pages"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generating print job"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Save as PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"All printers…"</string>
<string name="print_dialog" msgid="32628687461331979">"Print dialogue"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Search"</string>
<string name="all_printers_label" msgid="3178848870161526399">"All printers"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Add service"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portrait"</item>
<item msgid="3199660090246166812">"Landscape"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"All"</item>
- <item msgid="6812869625222503603">"Range"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Couldn\'t write to file"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Couldn\'t generate print job"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Sorry, that didn\'t work. Try again."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Retry"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Printer unavailable"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Cancelling…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"This printer isn\'t available right now."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Preparing preview…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml
index 90e81bd..f3b2787 100644
--- a/packages/PrintSpooler/res/values-es-rUS/strings.xml
+++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Tamaño de papel:"</string>
<string name="label_color" msgid="1108690305218188969">"Color"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientación"</string>
- <string name="label_pages" msgid="6300874667546617333">"Páginas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"Ej.: 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Vista previa de impresión"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Instalar visualizador de PDF para vista previa"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"La aplicación de impresión falló"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Páginas"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generando trabajo de impresión"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Guardar como PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Todas las impresoras…"</string>
<string name="print_dialog" msgid="32628687461331979">"Cuadro de diálogo de impresión"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Buscar"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Todas las impresoras"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Agregar servicio"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Vertical"</item>
<item msgid="3199660090246166812">"Horizontal"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Todas"</item>
- <item msgid="6812869625222503603">"Intervalo"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"No se pudo escribir en el archivo."</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Error al generar el trabajo de impresión"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"No funcionó. Vuelve a intentarlo."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Reintentar"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Impresora no disponible"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Cancelando…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Esta impresora no está disponible en este momento."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Preparando vista previa…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml
index 101831a..bbc77dc 100644
--- a/packages/PrintSpooler/res/values-es/strings.xml
+++ b/packages/PrintSpooler/res/values-es/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Tamaño del papel:"</string>
<string name="label_color" msgid="1108690305218188969">"Color"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientación"</string>
- <string name="label_pages" msgid="6300874667546617333">"Páginas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"p. ej.: 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Vista previa de impresión"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Instalar visor PDF para obtener vista previa"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Error de aplicación de impresión"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Páginas"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generando trabajo de impresión"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Guardar como PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Todas las impresoras…"</string>
<string name="print_dialog" msgid="32628687461331979">"Cuadro de diálogo de impresión"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Buscar"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Todas las impresoras"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Añadir servicio"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Vertical"</item>
<item msgid="3199660090246166812">"Horizontal"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Todo"</item>
- <item msgid="6812869625222503603">"Intervalo"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Error al escribir en el archivo"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Error al generar el trabajo de impresión"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"No ha funcionado. Repítelo."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Reintentar"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Impresora no disponible"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Cancelando…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Esta impresora no está disponible en este momento."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Preparando vista previa…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-et-rEE/strings.xml b/packages/PrintSpooler/res/values-et-rEE/strings.xml
index 24e1e54..ccc0ecc 100644
--- a/packages/PrintSpooler/res/values-et-rEE/strings.xml
+++ b/packages/PrintSpooler/res/values-et-rEE/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Paberi suurus:"</string>
<string name="label_color" msgid="1108690305218188969">"Värv"</string>
<string name="label_orientation" msgid="2853142581990496477">"Suund"</string>
- <string name="label_pages" msgid="6300874667546617333">"Lehti (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"nt 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Prindi eelvaade"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"PDF-vaaturi installimine eelvaate kuvamiseks"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Printimisrakendus jooksis kokku"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Lehed"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Prinditöö loomine"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Salvesta PDF-ina"</string>
<string name="all_printers" msgid="5018829726861876202">"Kõik printerid …"</string>
<string name="print_dialog" msgid="32628687461331979">"Printimisdialoog"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>-st"</string>
<string name="search" msgid="5421724265322228497">"Otsing"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Kõik printerid"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Lisa teenus"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Vertikaalpaigutus"</item>
<item msgid="3199660090246166812">"Horisontaalpaigutus"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Kõik"</item>
- <item msgid="6812869625222503603">"Vahemik"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Failile ei saanud kirjutada."</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Prinditööd ei saanud luua"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Kahjuks see ei toiminud. Proovige uuesti."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Proovi uuesti"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Printer pole saadaval"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Tühistamine ..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"See printer ei ole praegu saadaval."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Eelvaate ettevalmistamine ..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 9aa0aeb..2bd53a4 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"اندازه کاغذ:"</string>
<string name="label_color" msgid="1108690305218188969">"رنگی"</string>
<string name="label_orientation" msgid="2853142581990496477">"جهت"</string>
- <string name="label_pages" msgid="6300874667546617333">"صفحات (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"مثلاً ۱—۵،۹،۷—۱۰"</string>
<string name="print_preview" msgid="8010217796057763343">"پیشنمایش چاپ"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"نصب نمایشگر PDF برای پیشنمایش"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"برنامه چاپ خراب شد"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"صفحات"</string>
<string name="generating_print_job" msgid="3119608742651698916">"در حال ایجاد کار چاپ"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"ذخیره بهعنوان PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"همه چاپگرها..."</string>
<string name="print_dialog" msgid="32628687461331979">"چاپ گفتگو"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"جستجو"</string>
<string name="all_printers_label" msgid="3178848870161526399">"همه چاپگرها"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"افزودن سرویس"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"عمودی"</item>
<item msgid="3199660090246166812">"افقی"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"همه"</item>
- <item msgid="6812869625222503603">"محدوده"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"در فایل نوشته نشد"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"کار چاپ ایجاد نشد"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"متأسفیم، تلاش ناموفق بود. دوباره امتحان کنید."</string>
<string name="print_error_retry" msgid="1426421728784259538">"امتحان مجدد"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"چاپگر در دسترس نیست"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"در حال لغو…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"این چاپگر اکنون در دسترس نیست."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"در حال آمادهسازی پیشنمایش…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-fi/strings.xml b/packages/PrintSpooler/res/values-fi/strings.xml
index a92b860..2d621e5 100644
--- a/packages/PrintSpooler/res/values-fi/strings.xml
+++ b/packages/PrintSpooler/res/values-fi/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Paperikoko:"</string>
<string name="label_color" msgid="1108690305218188969">"Väri"</string>
<string name="label_orientation" msgid="2853142581990496477">"Suunta"</string>
- <string name="label_pages" msgid="6300874667546617333">"Sivut (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"esim. 1–5,8,11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Tulostuksen esikatselu"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Asenna PDF-katseluohjelma esikatselua varten"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Tulostussovellus kaatui"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Sivut"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Luodaan tulostustyö"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Tallenna PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Kaikki tulostimet…"</string>
<string name="print_dialog" msgid="32628687461331979">"Tulostusikkuna"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Haku"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Kaikki tulostimet"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Lisää palvelu"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Pysty"</item>
<item msgid="3199660090246166812">"Vaaka"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Kaikki"</item>
- <item msgid="6812869625222503603">"Väli"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Tiedostoon kirjoittaminen epäonnistui"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Tulostustyötä ei voitu luoda"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Ei valitettavasti onnistunut. Yritä uudelleen."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Yritä uudelleen"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Tulostin ei ole käytettävissä"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Peruutetaan…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Tämä tulostin ei ole käyttävissä juuri nyt."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Esikatselua valmistellaan…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index b7c0247..7212319 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Taille du papier :"</string>
<string name="label_color" msgid="1108690305218188969">"Couleur"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
- <string name="label_pages" msgid="6300874667546617333">"Pages (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"p. ex. 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Aperçu avant impression"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Installer un lecteur PDF pour voir l\'aperçu"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"L\'application à l\'origine de l\'impression a planté"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Pages"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Génération tâche impression…"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Enregistrer en format PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Toutes les imprimantes…"</string>
<string name="print_dialog" msgid="32628687461331979">"Boîte de dialogue d\'impression"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> sur <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Rechercher"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Toutes les imprimantes"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Ajouter le service"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portrait"</item>
<item msgid="3199660090246166812">"Paysage"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Tous"</item>
- <item msgid="6812869625222503603">"Plage"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Impossible d\'écrire dans le fichier"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Impossible de générer la tâche d\'impression"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Échec de l\'action. Réessayez."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Réessayer"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Imprimante indisponible"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Annulation en cours..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Cette imprimante n\'est pas accessible pour le moment."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Préparation de l\'aperçu en cours…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 3150269..7d11cb7 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Taille du papier :"</string>
<string name="label_color" msgid="1108690305218188969">"Couleur"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientation"</string>
- <string name="label_pages" msgid="6300874667546617333">"Pages (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"ex. : 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Aperçu avant impression"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Installer un lecteur PDF pour afficher l\'aperçu"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"L\'application à l\'origine de l\'impression a planté"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Pages"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Génération tâche impression…"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Enregistrer au format .PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Toutes les imprim."</string>
<string name="print_dialog" msgid="32628687461331979">"Boîte de dialogue d\'impression"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Rechercher"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Toutes les imprimantes"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Ajouter un service"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portrait"</item>
<item msgid="3199660090246166812">"Paysage"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Tout"</item>
- <item msgid="6812869625222503603">"Plage"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Impossible d\'écrire dans le fichier."</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Impossible de générer la tâche d\'impression."</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Échec de l\'opération. Veuillez réessayer."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Réessayer"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Imprimante indisponible."</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Annulation en cours…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Cette imprimante n\'est pas disponible actuellement."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Préparation de l\'aperçu en cours…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index ab331a1..c58383a 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"काग़ज़ का आकार:"</string>
<string name="label_color" msgid="1108690305218188969">"रंग"</string>
<string name="label_orientation" msgid="2853142581990496477">"अभिविन्यास"</string>
- <string name="label_pages" msgid="6300874667546617333">"पृष्ठ (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"उदा. 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"प्रिंट पूर्वावलोकन"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"पूर्वावलोकन के लिए PDF व्यूअर इंस्टॉल करें"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"प्रिंटिंग ऐप्लिकेशन क्रैश हो गया"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"पृष्ठ"</string>
<string name="generating_print_job" msgid="3119608742651698916">"प्रिंट कार्य जनरेट हो रहा है"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF के रूप में सहेजें"</string>
<string name="all_printers" msgid="5018829726861876202">"सभी प्रिंटर..."</string>
<string name="print_dialog" msgid="32628687461331979">"प्रिंट संवाद"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"खोजें"</string>
<string name="all_printers_label" msgid="3178848870161526399">"सभी प्रिंटर"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"सेवा जोड़ें"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"पोर्ट्रेट"</item>
<item msgid="3199660090246166812">"लैंडस्केप"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"सभी"</item>
- <item msgid="6812869625222503603">"सीमा"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"फ़ाइल पर नहीं लिखा जा सका"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"प्रिंट कार्य जनरेट नहीं किया जा सका"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"क्षमा करें, उससे बात नहीं बनी. पुन: प्रयास करें."</string>
<string name="print_error_retry" msgid="1426421728784259538">"पुनः प्रयास करें"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"प्रिंटर अनुपलब्ध है"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"रद्द किया जा रहा है..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"यह प्रिंटर इस समय उपलब्ध नहीं है."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"पूर्वावलोकन तैयार हो रहा है..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-hr/strings.xml b/packages/PrintSpooler/res/values-hr/strings.xml
index 215c46b..58f761d 100644
--- a/packages/PrintSpooler/res/values-hr/strings.xml
+++ b/packages/PrintSpooler/res/values-hr/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Veličina papira:"</string>
<string name="label_color" msgid="1108690305218188969">"U boji"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orijentacija"</string>
- <string name="label_pages" msgid="6300874667546617333">"Stranice (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"npr. 1 – 5,8,11 – 13"</string>
<string name="print_preview" msgid="8010217796057763343">"Pregled ispisa"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Instaliraj PDF preglednik za pregled"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Srušila se aplikacija za ispis"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Stranice"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generiranje zadatka ispisa"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Spremi kao PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Svi pisači…"</string>
<string name="print_dialog" msgid="32628687461331979">"Dijaloški okvir za ispis"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Pretraživanje"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Svi pisači"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Dodaj uslugu"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portret"</item>
<item msgid="3199660090246166812">"Pejzaž"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Sve"</item>
- <item msgid="6812869625222503603">"Raspon"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Zapisivanje u datoteku nije uspjelo"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Zadatak ispisa nije generiran"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Nažalost, to nije uspjelo. Pokušajte ponovo."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Pokušajte ponovno"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Pisač nije dostupan"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Otkazivanje…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Pisač trenutačno nije dostupan."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Priprema pregleda…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-hu/strings.xml b/packages/PrintSpooler/res/values-hu/strings.xml
index 314025d..6c587db 100644
--- a/packages/PrintSpooler/res/values-hu/strings.xml
+++ b/packages/PrintSpooler/res/values-hu/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Papírméret:"</string>
<string name="label_color" msgid="1108690305218188969">"Szín"</string>
<string name="label_orientation" msgid="2853142581990496477">"Tájolás"</string>
- <string name="label_pages" msgid="6300874667546617333">"Oldalszám (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"pl. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Előnézet nyomtatása"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Az előnézethez telepítse a PDF-megtekintőt."</string>
<string name="printing_app_crashed" msgid="854477616686566398">"A nyomtatási alkalmazás összeomlott."</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Oldalak"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Nyomtatási feladat létrehozása"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Mentés PDF-ként"</string>
<string name="all_printers" msgid="5018829726861876202">"Az összes nyomtató…"</string>
<string name="print_dialog" msgid="32628687461331979">"Nyomtatási párbeszédablak"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Keresés"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Az összes nyomtató"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Szolgáltatás hozzáadása"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Álló"</item>
<item msgid="3199660090246166812">"Fekvő"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Összes"</item>
- <item msgid="6812869625222503603">"Tartomány"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Nem sikerült írni a fájlba"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Nem sikerült létrehozni a nyomtatási feladatot."</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Sajnáljuk, de nem sikerült. Próbálja újra."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Újra"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"A nyomtató nem érhető el"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Megszakítás..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Ez a nyomtató jelenleg nem érhető el."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Előnézet előkészítése…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-hy-rAM/strings.xml b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
index de5c2bfb..3377abd 100644
--- a/packages/PrintSpooler/res/values-hy-rAM/strings.xml
+++ b/packages/PrintSpooler/res/values-hy-rAM/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Թղթի չափը՝"</string>
<string name="label_color" msgid="1108690305218188969">"Գույնը"</string>
<string name="label_orientation" msgid="2853142581990496477">"Դիրքավորում"</string>
- <string name="label_pages" msgid="6300874667546617333">"Էջեր (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"օր.՝ 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Տպելու նախադիտում"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Նախադիտման համար տեղադրեք PDF դիտարկիչ"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Տպելու ծրագիրը վթարի է ենթարկվել"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Էջեր"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Ձևավորվում է տպելու աշխատանքը"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Պահել որպես PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Բոլոր տպիչները..."</string>
<string name="print_dialog" msgid="32628687461331979">"Տպելու երկխոսության պատուհան"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Որոնել"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Բոլոր տպիչները"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Ավելացնել ծառայություն"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Դիմանկար"</item>
<item msgid="3199660090246166812">"Լանդշաֆտ"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Բոլորը"</item>
- <item msgid="6812869625222503603">"Միջակայք"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Հնարավոր չէ գրել ֆայլում"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Չկարողացանք մշակել տպման աշխատանքը"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Չստացվեց: Նորից փորձեք:"</string>
<string name="print_error_retry" msgid="1426421728784259538">"Կրկնել"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Տպիչն անհասանելի է"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Չեղարկվում է..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Տվյալ տպիչն այս պահին հասանելի չէ:"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Նախադիտումը պատրաստվում է…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-in/strings.xml b/packages/PrintSpooler/res/values-in/strings.xml
index 77180c4..5dc2f5d 100644
--- a/packages/PrintSpooler/res/values-in/strings.xml
+++ b/packages/PrintSpooler/res/values-in/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Ukuran kertas:"</string>
<string name="label_color" msgid="1108690305218188969">"Warna"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientasi"</string>
- <string name="label_pages" msgid="6300874667546617333">"(<xliff:g id="PAGE_COUNT">%1$s</xliff:g>) halaman"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"misalnya 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"Pratinjau cetak"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Pasang penampil PDF untuk pratinjau"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Aplikasi pencetakan mogok"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Halaman"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Membuat tugas pencetakan"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Simpan sebagai PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Semua printer…"</string>
<string name="print_dialog" msgid="32628687461331979">"Cetak dialog"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Cari"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Semua printer"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Tambahkan layanan"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Potret"</item>
<item msgid="3199660090246166812">"Lanskap"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Semua"</item>
- <item msgid="6812869625222503603">"Rentang"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Tidak dapat menulis ke file"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Tidak dapat membuat tugas cetak"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Maaf, tidak berhasil. Coba lagi."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Coba lagi"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Printer tidak tersedia"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Membatalkan…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Saat ini printer ini tidak tersedia."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Menyiapkan pratinjau..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml
index f0ef878..0696f66 100644
--- a/packages/PrintSpooler/res/values-it/strings.xml
+++ b/packages/PrintSpooler/res/values-it/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Dimensioni carta:"</string>
<string name="label_color" msgid="1108690305218188969">"A colori"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientamento"</string>
- <string name="label_pages" msgid="6300874667546617333">"Pagine (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"Es.: 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Anteprima di stampa"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Installa visualizzatore PDF per anteprima"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Arresto anomalo dell\'app di stampa"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Pagine"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generazione processo di stampa"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Salva in PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Tutte le stampanti…"</string>
<string name="print_dialog" msgid="32628687461331979">"Finestra di dialogo Stampa"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Cerca"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Tutte le stampanti"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Aggiungi servizio"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Verticale"</item>
<item msgid="3199660090246166812">"Orizzontale"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Tutte"</item>
- <item msgid="6812869625222503603">"Intervallo"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Impossibile scrivere sul file"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Impossibile generare processo di stampa"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Non ha funzionato. Riprova."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Riprova"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Stampante non disponibile"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Annullamento in corso…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Al momento la stampante non è disponibile."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Preparazione anteprima…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index e69221a..59a4eaf 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"גודל נייר:"</string>
<string name="label_color" msgid="1108690305218188969">"צבע"</string>
<string name="label_orientation" msgid="2853142581990496477">"כיוון"</string>
- <string name="label_pages" msgid="6300874667546617333">"עמודים (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"למשל 1–5,8,11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"תצוגה מקדימה של הדפסה"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"התקן מציג PDF ליצירת תצוגה מקדימה"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"אפליקציית ההדפסה קרסה"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"עמודים"</string>
<string name="generating_print_job" msgid="3119608742651698916">"יוצר עבודת הדפסה"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"שמור כ-PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"כל המדפסות…"</string>
<string name="print_dialog" msgid="32628687461331979">"תיבת דו שיח של מדפסת"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"חפש"</string>
<string name="all_printers_label" msgid="3178848870161526399">"כל המדפסות"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"הוסף שירות"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"לאורך"</item>
<item msgid="3199660090246166812">"לרוחב"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"הכל"</item>
- <item msgid="6812869625222503603">"טווח"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"לא ניתן היה לכתוב לקובץ"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"לא ניתן היה ליצור את עבודת ההדפסה"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"מצטערים, אך זה לא עבד. נסה שוב."</string>
<string name="print_error_retry" msgid="1426421728784259538">"נסה שוב"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"המדפסת אינה זמינה"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"מבטל…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"המדפסת הזו אינה זמינה כעת."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"מכין תצוגה מקדימה…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index 4cc6466..c38a094 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"用紙サイズ:"</string>
<string name="label_color" msgid="1108690305218188969">"カラー選択"</string>
<string name="label_orientation" msgid="2853142581990496477">"方向"</string>
- <string name="label_pages" msgid="6300874667546617333">"ページ(<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"例: 1-5,8,11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"印刷プレビュー"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"プレビュー用PDFビューアをインストール"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"印刷アプリでの障害発生"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"ページ数"</string>
<string name="generating_print_job" msgid="3119608742651698916">"印刷ジョブを生成しています"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF形式で保存"</string>
<string name="all_printers" msgid="5018829726861876202">"すべてのプリンタ…"</string>
<string name="print_dialog" msgid="32628687461331979">"印刷ダイアログ"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"検索"</string>
<string name="all_printers_label" msgid="3178848870161526399">"すべてのプリンタ"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"サービスを追加"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"縦向き"</item>
<item msgid="3199660090246166812">"横向き"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"すべて"</item>
- <item msgid="6812869625222503603">"範囲"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"ファイルに書き込めませんでした"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"印刷ジョブを生成できませんでした"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"エラーです。もう一度お試しください。"</string>
<string name="print_error_retry" msgid="1426421728784259538">"再試行"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"プリンタを使用できません"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"キャンセルしています…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"現在このプリンターは使用できません。"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"プレビューを準備しています…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ka-rGE/strings.xml b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
index 87a1711..92b99c4 100644
--- a/packages/PrintSpooler/res/values-ka-rGE/strings.xml
+++ b/packages/PrintSpooler/res/values-ka-rGE/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"ფურცლის ზომა:"</string>
<string name="label_color" msgid="1108690305218188969">"ფერი"</string>
<string name="label_orientation" msgid="2853142581990496477">"ორიენტაცია"</string>
- <string name="label_pages" msgid="6300874667546617333">"გვერდები (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"მაგ. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"ნახვა ამობეჭდვამდე"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"გადახედვისთვის დააყენეთ PDF მნახველი"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"ბეჭდვის აპი ავარიულად გაითიშა"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"გვერდები"</string>
<string name="generating_print_job" msgid="3119608742651698916">"მიმდინარეობის ბეჭდვის დავალების შექმნა"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF-ად შენახვა"</string>
<string name="all_printers" msgid="5018829726861876202">"ყველა პრინტერი…"</string>
<string name="print_dialog" msgid="32628687461331979">"ბეჭდვის სარკმელი"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"ძიება"</string>
<string name="all_printers_label" msgid="3178848870161526399">"ყველა პრინტერი"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"სერვისის დამატება"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"პორტრეტი"</item>
<item msgid="3199660090246166812">"პეიზაჟის რეჟიმი"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"ყველა"</item>
- <item msgid="6812869625222503603">"დიაპაზონი"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"ფაილში ჩაწერა ვერ მოხერხდა"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"ბეჭდვის დავალების გენერაცია ვერ ხერხდება"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"უკაცრავად, ვერ მოხერხდა. სცადეთ ისევ."</string>
<string name="print_error_retry" msgid="1426421728784259538">"გამეორება"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"პრინტერი მიუწვდომელია"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"უქმდება…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"This printer isn\'t available right now."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Preparing preview…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index cdcb21f..927bd58 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"ទំហំក្រដាស៖"</string>
<string name="label_color" msgid="1108690305218188969">"ពណ៌"</string>
<string name="label_orientation" msgid="2853142581990496477">"ទិស"</string>
- <string name="label_pages" msgid="6300874667546617333">"ទំព័រ (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"ឧ. 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"មើលមុនបោះពុម្ព"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"ដំឡើងកម្មវិធីមើល PDF សម្រាប់ការមើលជាមុន"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"កម្មវិធីបោះពុម្ពគាំង"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"ទំព័រ"</string>
<string name="generating_print_job" msgid="3119608742651698916">"បង្កើតការងារបោះពុម្ព"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"រក្សាទុកជា PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"ម៉ាស៊ីនបោះពុម្ពទាំងអស់ ..."</string>
<string name="print_dialog" msgid="32628687461331979">"ប្រអប់បោះពុម្ព"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"ស្វែងរក"</string>
<string name="all_printers_label" msgid="3178848870161526399">"ម៉ាស៊ីនបោះពុម្ពទាំងអស់"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"បន្ថែមសេវាកម្ម"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"បញ្ឈរ"</item>
<item msgid="3199660090246166812">"ផ្ដេក"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"ទាំងអស់"</item>
- <item msgid="6812869625222503603">"ជួរ"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"មិនអាចសរសេរទៅកាន់ឯកសារ"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"មិនអាចបង្កើតការងារបោះពុម្ព"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"សូមទោស វាមិនដំណើរការទេ។ ព្យាយាមម្ដងទៀត។"</string>
<string name="print_error_retry" msgid="1426421728784259538">"ព្យាយាមម្ដងទៀត"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"ម៉ាស៊ីនបោះពុម្ពមិនអាចប្រើបាន"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"កំពុងបោះបង់..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"ឥឡូវនេះ ម៉ាស៊ីនបោះពុម្ពនេះមិនអាចប្រើបាន។"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"កំពុងរៀបចំមើលជាមុន…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ko/strings.xml b/packages/PrintSpooler/res/values-ko/strings.xml
index 65df4fb..73858dc 100644
--- a/packages/PrintSpooler/res/values-ko/strings.xml
+++ b/packages/PrintSpooler/res/values-ko/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"용지 크기:"</string>
<string name="label_color" msgid="1108690305218188969">"색상"</string>
<string name="label_orientation" msgid="2853142581990496477">"방향"</string>
- <string name="label_pages" msgid="6300874667546617333">"페이지 수(<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"예: 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"인쇄 미리보기"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"미리보기용 PDF 뷰어 설치"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"인쇄 앱에 오류 발생"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"페이지"</string>
<string name="generating_print_job" msgid="3119608742651698916">"인쇄 작업 생성 중"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF로 저장"</string>
<string name="all_printers" msgid="5018829726861876202">"모든 프린터…"</string>
<string name="print_dialog" msgid="32628687461331979">"인쇄 대화상자"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"검색"</string>
<string name="all_printers_label" msgid="3178848870161526399">"모든 프린터"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"서비스 추가"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"세로"</item>
<item msgid="3199660090246166812">"가로"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"모두"</item>
- <item msgid="6812869625222503603">"범위"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"PDF 파일을 생성하지 못했습니다."</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"인쇄 작업을 생성할 수 없습니다."</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"죄송합니다. 오류가 발생했습니다. 다시 시도해 보세요."</string>
<string name="print_error_retry" msgid="1426421728784259538">"다시 시도"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"선택한 프린터를 사용할 수 없음"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"취소 중..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"현재 이 프린터를 사용할 수 없습니다."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"미리보기 준비 중…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-lo-rLA/strings.xml b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
index d06660c..555f92f 100644
--- a/packages/PrintSpooler/res/values-lo-rLA/strings.xml
+++ b/packages/PrintSpooler/res/values-lo-rLA/strings.xml
@@ -25,16 +25,18 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"ຂະໜາດເຈ້ຍ:"</string>
<string name="label_color" msgid="1108690305218188969">"ສີ"</string>
<string name="label_orientation" msgid="2853142581990496477">"ລວງ"</string>
- <string name="label_pages" msgid="6300874667546617333">"(<xliff:g id="PAGE_COUNT">%1$s</xliff:g>) ໜ້າ"</string>
+ <string name="label_pages" msgid="7768589729282182230">"ໜ້າ"</string>
+ <string name="template_all_pages" msgid="3322235982020148762">"ທັງໝົດ <xliff:g id="PAGE_COUNT">%1$s</xliff:g> ໜ້າ"</string>
+ <string name="template_page_range" msgid="428638530038286328">"ໄລຍະ <xliff:g id="PAGE_COUNT">%1$s</xliff:g> ໜ້າ"</string>
<string name="pages_range_example" msgid="8558694453556945172">"ຕົວຢ່າງ: 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"ເບິ່ງກ່ອນພິມ"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"ຕິດຕັ້ງໂປຼແກຼມເບິ່ງ PDF ເພື່ອເບິ່ງຕົວຢ່າງ"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"ແອັບຯພິມລົ້ມເຫລວ"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"ໜ້າ"</string>
<string name="generating_print_job" msgid="3119608742651698916">"ກຳລັງສ້າງວຽກພິມ"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"ບັນທຶກເປັນ PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"ທຸກເຄື່ອງພິມ..."</string>
<string name="print_dialog" msgid="32628687461331979">"ໜ້າຕ່າງການພິມ"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"ຊອກຫາ"</string>
<string name="all_printers_label" msgid="3178848870161526399">"ທຸກເຄື່ອງພິມ"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"ເພີ່ມບໍລິການ"</string>
@@ -71,13 +73,9 @@
<item msgid="4061931020926489228">"ລວງຕັ້ງ"</item>
<item msgid="3199660090246166812">"ລວງນອນ"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"ທັງໝົດ"</item>
- <item msgid="6812869625222503603">"ໄລຍະ"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"ບໍ່ສາມາດຂຽນໄຟລ໌ໄດ້"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"ບໍ່ສາມາດສ້າງວຽກພິມໄດ້"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"ຂໍອະໄພ, ໃຊ້ບໍ່ໄດ້. ໃຫ້ລອງໃໝ່ອີກເທື່ອນຶ່ງ."</string>
<string name="print_error_retry" msgid="1426421728784259538">"ລອງໃໝ່"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"ເຄື່ອງພິມບໍ່ສາມາດໃຊ້ໄດ້"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"ກຳລັງຍົກເລີກ…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"ບໍ່ສາມາດໃຊ້ເຄື່ອງພິມນີ້ໃນເວລານີ້ໄດ້."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"ກຳລັງກະກຽມຕົວຢ່າງ…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-lt/strings.xml b/packages/PrintSpooler/res/values-lt/strings.xml
index a42bdd9..97607f2 100644
--- a/packages/PrintSpooler/res/values-lt/strings.xml
+++ b/packages/PrintSpooler/res/values-lt/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Popieriaus dydis:"</string>
<string name="label_color" msgid="1108690305218188969">"Spalva"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientacija"</string>
- <string name="label_pages" msgid="6300874667546617333">"Puslapiai (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"pvz., 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Spaudinio peržiūra"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Įdiegti PDF peržiūros priemonę"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Spausdinimo programa užstrigo"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Puslapiai"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generuojama spausd. užduotis"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Išsaugoti kaip PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Visi spausdintuvai…"</string>
<string name="print_dialog" msgid="32628687461331979">"Spausdinimo dialogo langas"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> / <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Ieškoti"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Visi spausdintuvai"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Pridėti paslaugą"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Stačias"</item>
<item msgid="3199660090246166812">"Gulsčias"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Visi"</item>
- <item msgid="6812869625222503603">"Diapazonas"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Nepavyko įrašyti į failą"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Nepavyko sukurti spausdinimo užduoties"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Deja, tai neveikia. Bandykite dar kartą."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Bandykite dar kartą"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Spausdintuvas nepasiekiamas"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Atšaukiama…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Šis spausdintuvas šiuo metu nepasiekiamas."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Ruošiama peržiūra…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-lv/strings.xml b/packages/PrintSpooler/res/values-lv/strings.xml
index 3afba54..294654e 100644
--- a/packages/PrintSpooler/res/values-lv/strings.xml
+++ b/packages/PrintSpooler/res/values-lv/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Papīra izmērs:"</string>
<string name="label_color" msgid="1108690305218188969">"Krāsa"</string>
<string name="label_orientation" msgid="2853142581990496477">"Virziens"</string>
- <string name="label_pages" msgid="6300874667546617333">"Lapas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"piem., 1–5,8,11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Drukas priekšskatījums"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Instalēt PDF skatītāju priekšskatīšanai"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Drukas lietotne avarēja"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Lapas"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Ģenerē drukas darbu…"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Saglabāt kā PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Visi printeri…"</string>
<string name="print_dialog" msgid="32628687461331979">"Drukāšanas dialoglodziņš"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>. no <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Meklēt"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Visi printeri"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Pievienot pakalpojumu"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portrets"</item>
<item msgid="3199660090246166812">"Ainava"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Visi"</item>
- <item msgid="6812869625222503603">"Diapazons"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Nevarēja ierakstīt failā."</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Nevarēja ģenerēt drukas darbu"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Diemžēl tas neizdevās. Mēģiniet vēlreiz."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Mēģināt vēlreiz"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Printeris nav pieejams."</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Notiek atcelšana…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Šis printeris šobrīd nav pieejams."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Notiek priekšskatījuma sagatavošana..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-mn-rMN/strings.xml b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
index ffe98fe..6bb571f 100644
--- a/packages/PrintSpooler/res/values-mn-rMN/strings.xml
+++ b/packages/PrintSpooler/res/values-mn-rMN/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Цаасны хэмжээ:"</string>
<string name="label_color" msgid="1108690305218188969">"Өнгө"</string>
<string name="label_orientation" msgid="2853142581990496477">"Чиглэл"</string>
- <string name="label_pages" msgid="6300874667546617333">"(<xliff:g id="PAGE_COUNT">%1$s</xliff:g>) хуудас"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"ж.нь. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Хэвлэхээр урьдчилан харах"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Урьдчилан харахын тулд PDF харагчийг суулгах"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Хэвлэгч апп гацсан"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Хуудас"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Хэвлэх ажил үүсгэж байна"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF болгож хадгалах"</string>
<string name="all_printers" msgid="5018829726861876202">"Бүх принтерүүд…"</string>
<string name="print_dialog" msgid="32628687461331979">"Хэвлэх диалоги"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Хайх"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Бүх принтерүүд"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Үйлчилгээ нэмэх"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Босоо"</item>
<item msgid="3199660090246166812">"Хэвтээ"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Бүгд"</item>
- <item msgid="6812869625222503603">"Хүрээ"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Файл руу бичиж чадсангүй"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Хэвлэх ажлыг үүсгэж чадсангүй"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Уучлаарай, ажилласангүй. Дахин оролдоно уу."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Дахин оролдох"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Принтер байхгүй"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Цуцлаж байна..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Одоо хэвлэгч ашиглах боломжгүй."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Урьдчилан харахыг бэлтгэж байна…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ms-rMY/strings.xml b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
index 7141aeb..5ee274f 100644
--- a/packages/PrintSpooler/res/values-ms-rMY/strings.xml
+++ b/packages/PrintSpooler/res/values-ms-rMY/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Saiz kertas:"</string>
<string name="label_color" msgid="1108690305218188969">"Warna"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientasi"</string>
- <string name="label_pages" msgid="6300874667546617333">"Halaman (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"cth. 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"Pratonton cetak"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Pasang pemapar PDF untuk pratonton"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Apl percetakan ranap"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Halaman"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Menjana kerja cetak"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Simpan sebagai PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Semua pencetak..."</string>
<string name="print_dialog" msgid="32628687461331979">"Dialog cetakan"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Cari"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Semua pencetak"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Tambahkan perkhidmatan"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Potret"</item>
<item msgid="3199660090246166812">"Landskap"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Semua"</item>
- <item msgid="6812869625222503603">"Julat"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Tidak dapat menulis ke fail"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Tidak dapat menjana kerja cetakan"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Maaf, itu tidak berjaya. Cuba lagi."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Cuba semula"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Pencetak tidak tersedia"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Membatalkan..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Pencetak ini tidak tersedia sekarang."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Menyediakan pratonton..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-nb/strings.xml b/packages/PrintSpooler/res/values-nb/strings.xml
index 8c66bfb..88d45ef 100644
--- a/packages/PrintSpooler/res/values-nb/strings.xml
+++ b/packages/PrintSpooler/res/values-nb/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Papirstørrelse:"</string>
<string name="label_color" msgid="1108690305218188969">"Farge"</string>
<string name="label_orientation" msgid="2853142581990496477">"Retning"</string>
- <string name="label_pages" msgid="6300874667546617333">"Sider (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"f.eks. 1–5, 8,11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Utskriftsforhåndsvisning"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Installer PDF-leser for forhåndsvisning"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Utskriftsappen krasjet"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Sider"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Genererer utskriftsjobb"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Lagre som PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Alle skrivere"</string>
<string name="print_dialog" msgid="32628687461331979">"Skriv ut dialog"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Søk"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Alle skrivere"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Legg til tjeneste"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Stående"</item>
<item msgid="3199660090246166812">"Liggende"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Alle"</item>
- <item msgid="6812869625222503603">"Område"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Kunne ikke skrive til filen"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Kunne ikke generere utskriftsjobben"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Beklager, det fungerte ikke. Prøv på nytt."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Prøv på nytt"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Skriveren er utilgjengelig"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Avbryter …"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Denne skriveren er ikke tilgjengelig akkurat nå."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Forbereder forhåndsvisningen …"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-nl/strings.xml b/packages/PrintSpooler/res/values-nl/strings.xml
index caa5c80..8273fd5 100644
--- a/packages/PrintSpooler/res/values-nl/strings.xml
+++ b/packages/PrintSpooler/res/values-nl/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Papierformaat:"</string>
<string name="label_color" msgid="1108690305218188969">"Kleur"</string>
<string name="label_orientation" msgid="2853142581990496477">"Stand"</string>
- <string name="label_pages" msgid="6300874667546617333">"Pagina\'s (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"bijv. 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"Afdrukvoorbeeld"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Pdf-viewer installeren voor voorbeeld"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Afdruk-app gecrasht"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Pagina\'s"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Afdruktaak genereren"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Opslaan als pdf"</string>
<string name="all_printers" msgid="5018829726861876202">"Alle printers…"</string>
<string name="print_dialog" msgid="32628687461331979">"Afdrukdialoogvenster"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Zoeken"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Alle printers"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Service toevoegen"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portret"</item>
<item msgid="3199660090246166812">"Landschap"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Alle"</item>
- <item msgid="6812869625222503603">"Bereik"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Kan niet naar bestand schrijven"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Kan de afdruktaak niet genereren"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Dat werkte niet. Probeer het opnieuw."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Opnieuw proberen"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Printer niet beschikbaar"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Annuleren…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Deze printer is momenteel niet beschikbaar."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Voorbeeld voorbereiden…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index d19f2ac..a12c02c 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Rozmiar papieru:"</string>
<string name="label_color" msgid="1108690305218188969">"Kolor"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientacja"</string>
- <string name="label_pages" msgid="6300874667546617333">"Strony (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"np. 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Podgląd wydruku"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Zainstaluj przeglądarkę PDF, by zobaczyć podgląd"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Aplikacja drukująca uległa awarii"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Strony"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generowanie zadania wydruku"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Zapisz jako PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Wszystkie drukarki…"</string>
<string name="print_dialog" msgid="32628687461331979">"Okno drukowania"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Szukaj"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Wszystkie drukarki"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Dodaj usługę"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Pionowa"</item>
<item msgid="3199660090246166812">"Pozioma"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Wszystkie"</item>
- <item msgid="6812869625222503603">"Zakres"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Nie można zapisać pliku"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Nie udało się wygenerować zadania drukowania"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"To nie zadziałało. Spróbuj jeszcze raz."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Ponów próbę"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Drukarka niedostępna"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Anuluję…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Drukarka nie jest teraz dostępna."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Przygotowuję podgląd…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
index 6970730..8c3635b 100644
--- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml
+++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Tamanho do papel:"</string>
<string name="label_color" msgid="1108690305218188969">"Cor"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientação"</string>
- <string name="label_pages" msgid="6300874667546617333">"Páginas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"p. ex. 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Pré-visualização de impressão"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Instalar o leitor de PDF para pré-visualização"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"A aplicação de impressão bloqueou"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Páginas"</string>
<string name="generating_print_job" msgid="3119608742651698916">"A gerar tarefa de impressão"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Guardar como PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Todas as impressoras..."</string>
<string name="print_dialog" msgid="32628687461331979">"Caixa de diálogo de impressão"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Pesquisar"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Todas as impressoras"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Adicionar serviço"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Vertical"</item>
<item msgid="3199660090246166812">"Horizontal"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Todas"</item>
- <item msgid="6812869625222503603">"Intervalo"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Não foi possível gravar no ficheiro"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Não foi possível gerar a tarefa de impressão"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Lamentamos, mas isso não funcionou. Tente novam."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Tentar novamente"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Impressora não disponível"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"A cancelar…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Esta impressora não está atualmente disponível."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"A preparar a pré-visualização..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml
index 8b2a6fb..2c8e78e 100644
--- a/packages/PrintSpooler/res/values-pt/strings.xml
+++ b/packages/PrintSpooler/res/values-pt/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Tamanho do papel:"</string>
<string name="label_color" msgid="1108690305218188969">"Cor"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientação"</string>
- <string name="label_pages" msgid="6300874667546617333">"Páginas (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"Ex.: 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Visualização de impressão"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Instalar o visualizador de PDF"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"O aplicativo de impressão falhou"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Páginas"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Gerando trabalho de impressão"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Salvar como PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Todas as impressoras…"</string>
<string name="print_dialog" msgid="32628687461331979">"Diálogo de impressão"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Pesquisar"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Todas as impressoras"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Adicionar serviço"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Retrato"</item>
<item msgid="3199660090246166812">"Paisagem"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Todas"</item>
- <item msgid="6812869625222503603">"Intervalo"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Não foi possível gravar no arquivo"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Não foi possível gerar o trabalho de impressão"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Falhou. Tente novamente."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Tentar novamente"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Impressora indisponível"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Cancelando..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Esta impressora não está disponível no momento."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Preparando visualização…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ro/strings.xml b/packages/PrintSpooler/res/values-ro/strings.xml
index 6706cf6..fab4e0a 100644
--- a/packages/PrintSpooler/res/values-ro/strings.xml
+++ b/packages/PrintSpooler/res/values-ro/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Formatul hârtiei:"</string>
<string name="label_color" msgid="1108690305218188969">"Color"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientare"</string>
- <string name="label_pages" msgid="6300874667546617333">"Pagini (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"de ex. 1-5, 8, 11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Previzualizați printarea"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Instalați PDF viewer pentru previzualizare"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Aplicația de printare s-a blocat"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Pagini"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Se generează sarcină printare"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Salvați ca PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Toate imprimantele..."</string>
<string name="print_dialog" msgid="32628687461331979">"Caseta de dialog de printare"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Căutați"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Toate imprimantele"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Adăugați un serviciu"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portret"</item>
<item msgid="3199660090246166812">"Peisaj"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Toate"</item>
- <item msgid="6812869625222503603">"Interval"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Nu s-a putut scrie în fișier."</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Nu s-a putut genera sarcina de printare"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Ne pare rău, operațiunea nu a reușit. Încercați din nou."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Reîncercați"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Imprimanta nu este disponibilă"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"În curs de anulare..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Această imprimantă nu este disponibilă momentan."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Se pregătește previzualizarea..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-ru/strings.xml b/packages/PrintSpooler/res/values-ru/strings.xml
index 2256be4..3a8a231 100644
--- a/packages/PrintSpooler/res/values-ru/strings.xml
+++ b/packages/PrintSpooler/res/values-ru/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Размер бумаги:"</string>
<string name="label_color" msgid="1108690305218188969">"Печать"</string>
<string name="label_orientation" msgid="2853142581990496477">"Ориентация"</string>
- <string name="label_pages" msgid="6300874667546617333">"СТРАНИЦЫ (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"напр., 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Предварительный просмотр"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Установить средство просмотра PDF"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Сбой приложения печати"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Количество страниц"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Создание задания печати…"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Сохранить как PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Все принтеры"</string>
<string name="print_dialog" msgid="32628687461331979">"Диалоговое окно печати"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Поиск"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Все принтеры"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Добавить службу печати"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Книга"</item>
<item msgid="3199660090246166812">"Альбом"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Все"</item>
- <item msgid="6812869625222503603">"Диапазон"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Не удалось записать в файл"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Не удалось отправить документ на печать."</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Ошибка. Повторите попытку."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Повторить"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Принтер недоступен"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Отмена…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Принтер не готов."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Подготовка изображения…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-sk/strings.xml b/packages/PrintSpooler/res/values-sk/strings.xml
index a4f0444..47b4f06 100644
--- a/packages/PrintSpooler/res/values-sk/strings.xml
+++ b/packages/PrintSpooler/res/values-sk/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Veľkosť papiera:"</string>
<string name="label_color" msgid="1108690305218188969">"Farba"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientácia"</string>
- <string name="label_pages" msgid="6300874667546617333">"STRÁNKY (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"napr. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Ukážka pred tlačou"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Inštalovať zobrazovač PDF na zobrazenie ukážky"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Aplikácia pre tlač zlyhala"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Strany"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Generuje sa tlačová úloha"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Uložiť ako PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Všetky tlačiarne..."</string>
<string name="print_dialog" msgid="32628687461331979">"Dialógové okno tlače"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"VYHĽADÁVANIE"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Všetky tlačiarne"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Pridať službu"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Na výšku"</item>
<item msgid="3199660090246166812">"Na šírku"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Všetky"</item>
- <item msgid="6812869625222503603">"Rozsah"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Do súboru nie je možné zapisovať"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Tlačovú úlohu nie je možné vytvoriť"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Je nám to ľúto, nefungovalo to. Skúste to znova."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Opakovať"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Tlačiareň nie je k dispozícii"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Ruší sa..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Táto tlačiareň nie je momentálne k dispozícii."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Pripravuje sa ukážka..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index 672af526..dfdd5e6 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Velikost papirja:"</string>
<string name="label_color" msgid="1108690305218188969">"Barvno"</string>
<string name="label_orientation" msgid="2853142581990496477">"Postavitev"</string>
- <string name="label_pages" msgid="6300874667546617333">"Št. strani (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"npr. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Predogled tiskanja"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Za predogled namestite pregledovalnik za PDF-je"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Aplikacija za tiskanje se je zrušila"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Št. strani:"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Ustvarjanje zahteve za tisk"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Shrani kot PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Vsi tiskalniki …"</string>
<string name="print_dialog" msgid="32628687461331979">"Pogovorno okno za tiskanje"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Iskanje"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Vsi tiskalniki"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Dodaj storitev"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Pokončno"</item>
<item msgid="3199660090246166812">"Ležeče"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Vse"</item>
- <item msgid="6812869625222503603">"Obseg"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"V datoteko ni bilo mogoče zapisovati"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Tiskalnega opravila ni bilo mogoče ustvariti"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"To žal ni delovalo. Poskusite znova."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Poskusi znova"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Tiskalnik ni na voljo"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Preklic …"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Ta tiskalnik trenutno ni na voljo."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Priprava predogleda …"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-sr/strings.xml b/packages/PrintSpooler/res/values-sr/strings.xml
index ad45a93..7de3adf 100644
--- a/packages/PrintSpooler/res/values-sr/strings.xml
+++ b/packages/PrintSpooler/res/values-sr/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Величина папира:"</string>
<string name="label_color" msgid="1108690305218188969">"Боја"</string>
<string name="label_orientation" msgid="2853142581990496477">"Положај"</string>
- <string name="label_pages" msgid="6300874667546617333">"Странице (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"нпр. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Преглед пре штампања"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Инсталирај PDF приказивач за преглед"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Апликација за штампање је отказала"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Странице"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Генерисање задатка за штампање"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Сачувај као PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Сви штампачи…"</string>
<string name="print_dialog" msgid="32628687461331979">"Дијалог за штампање"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Претражи"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Сви штампачи"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Додај услугу"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Усправно"</item>
<item msgid="3199660090246166812">"Водоравно"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Све"</item>
- <item msgid="6812869625222503603">"Опсег"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Уписивање у датотеку није могуће"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Није могуће генерисати задатак за штампање"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Жао нам је, ово није успело. Покушајте поново."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Покушајте поново"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Штампач није доступан"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Отказивање..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Овај штампач тренутно није доступан."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Припрема прегледа..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-sv/strings.xml b/packages/PrintSpooler/res/values-sv/strings.xml
index a777165..0c6bbbe 100644
--- a/packages/PrintSpooler/res/values-sv/strings.xml
+++ b/packages/PrintSpooler/res/values-sv/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Pappersstorlek:"</string>
<string name="label_color" msgid="1108690305218188969">"Färg"</string>
<string name="label_orientation" msgid="2853142581990496477">"Orientering"</string>
- <string name="label_pages" msgid="6300874667546617333">"Sidor (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"t.ex. 1–5,8,11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Förhandsgranskning"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Installera PDF-läsare för förhandsgranskning"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Utskriftsappen kraschade"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Sidor"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Genererar utskriftsjobb"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Spara som PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Alla skrivare ..."</string>
<string name="print_dialog" msgid="32628687461331979">"Dialogrutan Skriv ut"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Sök"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Alla skrivare"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Lägg till tjänst"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Stående"</item>
<item msgid="3199660090246166812">"Liggande"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Alla"</item>
- <item msgid="6812869625222503603">"Intervall"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Det gick inte att skriva till filen"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Det gick inte att skapa utskriftsjobbet"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Det fungerade tyvärr inte. Försök igen."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Försök igen"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Skrivaren är inte tillgänglig"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Avbryter ..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Den här skrivaren är inte tillgänglig just nu."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Förbereder förhandsvisning ..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 4c7b3c3..8e63095 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Ukubwa wa karatasi:"</string>
<string name="label_color" msgid="1108690305218188969">"Rangi"</string>
<string name="label_orientation" msgid="2853142581990496477">"Mkao"</string>
- <string name="label_pages" msgid="6300874667546617333">"Kurasa (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"k.m. 1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Chungulia kwanza kabla ya kuchapisha"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Sakinisha kitazamaji cha PDF kwa onyesho la kuchungulia"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Programu ya kuchapisha imeacha kufanya kazi"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Kurasa"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Inaleta kazi ya kuchapisha"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Hifadhi kama PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Printa zote..."</string>
<string name="print_dialog" msgid="32628687461331979">"Chapisha mazungumzo"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Tafuta"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Printa zote"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Ongeza huduma"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Wima"</item>
<item msgid="3199660090246166812">"Mlalo"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Zote"</item>
- <item msgid="6812869625222503603">"Masafa"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Haikuweza kuandika kwenye faili"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Haikuweza kuleta kazi ya kuchapisha"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Samahani, hiyo haikufanya kazi. Jaribu tena."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Jaribu tena"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Printa haipatikani"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Inaghairi..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Printa hii haipatikani kwa sasa."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Inaandaa onyesho la kuchungulia..."</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-th/strings.xml b/packages/PrintSpooler/res/values-th/strings.xml
index e3e09d3..921bfca 100644
--- a/packages/PrintSpooler/res/values-th/strings.xml
+++ b/packages/PrintSpooler/res/values-th/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"ขนาดของกระดาษ:"</string>
<string name="label_color" msgid="1108690305218188969">"สี"</string>
<string name="label_orientation" msgid="2853142581990496477">"การวางแนว"</string>
- <string name="label_pages" msgid="6300874667546617333">"หน้า (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"เช่น 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"ตัวอย่างก่อนพิมพ์"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"ติดตั้งโปรแกรมดู PDF เพื่อดูหน้าตัวอย่าง"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"แอปการพิมพ์ขัดข้อง"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"หน้า"</string>
<string name="generating_print_job" msgid="3119608742651698916">"กำลังสร้างงานพิมพ์"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"บันทึกเป็น PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"เครื่องพิมพ์ทั้งหมด…"</string>
<string name="print_dialog" msgid="32628687461331979">"ช่องโต้ตอบการพิมพ์"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"ค้นหา"</string>
<string name="all_printers_label" msgid="3178848870161526399">"เครื่องพิมพ์ทั้งหมด"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"เพิ่มบริการ"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"แนวตั้ง"</item>
<item msgid="3199660090246166812">"แนวนอน"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"ทั้งหมด"</item>
- <item msgid="6812869625222503603">"ช่วง"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"ไม่สามารถเขียนไปยังไฟล์ได้"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"ไม่สามารถสร้างงานพิมพ์"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"ขออภัย ไม่สามารถใช้งานได้ ลองอีกครั้ง"</string>
<string name="print_error_retry" msgid="1426421728784259538">"ลองอีกครั้ง"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"ไม่สามารถใช้งานเครื่องพิมพ์ได้"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"กำลังยกเลิก…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"เครื่องพิมพ์นี้ไม่พร้อมใช้งานในขณะนี้"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"กำลังเตรียมการแสดงตัวอย่าง…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-tl/strings.xml b/packages/PrintSpooler/res/values-tl/strings.xml
index bb7d0bf..d94627e 100644
--- a/packages/PrintSpooler/res/values-tl/strings.xml
+++ b/packages/PrintSpooler/res/values-tl/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Laki ng papel:"</string>
<string name="label_color" msgid="1108690305218188969">"Kulay"</string>
<string name="label_orientation" msgid="2853142581990496477">"Oryentasyon"</string>
- <string name="label_pages" msgid="6300874667546617333">"Mga Pahina (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"hal. 1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"Preview sa pag-print"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Mag-install ng PDF viewer para sa pag-preview"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Nag-crash ang app sa pag-print"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Mga Pahina"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Gumagawa ng pag-print"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"I-save bilang PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Lahat ng printer…"</string>
<string name="print_dialog" msgid="32628687461331979">"Dialog ng pag-print"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Hanapin"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Lahat ng printer"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Magdagdag ng serbisyo"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Portrait"</item>
<item msgid="3199660090246166812">"Landscape"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Lahat"</item>
- <item msgid="6812869625222503603">"Sakop"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Hindi makapag-write sa file"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Hindi mabuo ang pag-print"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Paumanhin, hindi iyon gumana. Subukang muli."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Subukang muli"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Hindi available ang printer"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Kinakansela…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Hindi available ang printer na ito sa ngayon."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Inihahanda ang preview…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-tr/strings.xml b/packages/PrintSpooler/res/values-tr/strings.xml
index 5f81654..fab011e 100644
--- a/packages/PrintSpooler/res/values-tr/strings.xml
+++ b/packages/PrintSpooler/res/values-tr/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Kağıt boyutu:"</string>
<string name="label_color" msgid="1108690305218188969">"Renkli"</string>
<string name="label_orientation" msgid="2853142581990496477">"Sayfa yönü"</string>
- <string name="label_pages" msgid="6300874667546617333">"Sayfa (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"ör. 1-5,8,11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"Yazdırmayı önizle"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Önizlemek için PDF görüntüleyici yükleyin"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Yazdırma uygulaması kilitlendi"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Sayfa"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Yazdırma işi oluşturuluyor"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"PDF olarak kaydet"</string>
<string name="all_printers" msgid="5018829726861876202">"Tüm yazıcılar…"</string>
<string name="print_dialog" msgid="32628687461331979">"Yazdırma iletişim kutusu"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Ara"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Tüm yazıcılar"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Hizmet ekle"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Dikey"</item>
<item msgid="3199660090246166812">"Yatay"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Tümü"</item>
- <item msgid="6812869625222503603">"Aralık"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Dosyaya yazılamadı"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Yazdırma işi oluşturulamadı"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Maalesef bu işe yaramadı. Tekrar deneyin."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Yeniden dene"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Yazıcı kullanılamıyor"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"İptal ediliyor…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Bu yazı şu anda kullanılamıyor."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Önizleme hazırlanıyor…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-uk/strings.xml b/packages/PrintSpooler/res/values-uk/strings.xml
index 81be680..d7f8f73 100644
--- a/packages/PrintSpooler/res/values-uk/strings.xml
+++ b/packages/PrintSpooler/res/values-uk/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Розмір паперу:"</string>
<string name="label_color" msgid="1108690305218188969">"Колір"</string>
<string name="label_orientation" msgid="2853142581990496477">"Орієнтація"</string>
- <string name="label_pages" msgid="6300874667546617333">"Сторінки (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"напр.,1–5, 8, 11–13"</string>
<string name="print_preview" msgid="8010217796057763343">"Версія для друку"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Установити засіб перегляду PDF"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Програма друку аварійно завершила роботу"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Сторінки"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Створюється завдання друку"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Зберегти як PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Усі принтери…"</string>
<string name="print_dialog" msgid="32628687461331979">"Діалогове вікно друку"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> з <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Пошук"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Усі принтери"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Додати службу"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Книжкова"</item>
<item msgid="3199660090246166812">"Альбомна"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Усі"</item>
- <item msgid="6812869625222503603">"Діапазон"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Не вдається записати у файл"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Не вдалося створити завдання друку"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"На жаль, сталася помилка. Повторіть спробу."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Повторити"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Принтер недоступний"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Скасування…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Цей принтер зараз недоступний."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Підготовка до попереднього перегляду…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-vi/strings.xml b/packages/PrintSpooler/res/values-vi/strings.xml
index 84e97fd..d9e4adb 100644
--- a/packages/PrintSpooler/res/values-vi/strings.xml
+++ b/packages/PrintSpooler/res/values-vi/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Khổ giấy:"</string>
<string name="label_color" msgid="1108690305218188969">"Màu"</string>
<string name="label_orientation" msgid="2853142581990496477">"Hướng"</string>
- <string name="label_pages" msgid="6300874667546617333">"Trang (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"Ví dụ: 1—5, 8, 11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"Xem trước bản in"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Cài đặt trình xem PDF để xem trước"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Ứng dụng in gặp lỗi"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Trang"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Đang tạo lệnh in"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Lưu dưới dạng PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Tất cả máy in…"</string>
<string name="print_dialog" msgid="32628687461331979">"Hộp thoại in"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Tìm kiếm"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Tất cả máy in"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Thêm dịch vụ"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Dọc"</item>
<item msgid="3199660090246166812">"Ngang"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Tất cả"</item>
- <item msgid="6812869625222503603">"Dãy"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Không thể ghi vào tệp"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Không thể tạo lệnh in"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Rất tiếc, tính năng đó không hoạt động. Hãy thử lại."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Thử lại"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Máy in không khả dụng"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Đang hủy…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Máy in này hiện không khả dụng."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Đang chuẩn bị xem trước…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-zh-rCN/strings.xml b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
index a904388..4718dc1 100644
--- a/packages/PrintSpooler/res/values-zh-rCN/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rCN/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"纸张尺寸:"</string>
<string name="label_color" msgid="1108690305218188969">"颜色"</string>
<string name="label_orientation" msgid="2853142581990496477">"方向"</string>
- <string name="label_pages" msgid="6300874667546617333">"页数 (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"例如:1-5、8、11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"打印预览"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"安装 PDF 查看器以便预览"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"打印应用崩溃了"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"页数"</string>
<string name="generating_print_job" msgid="3119608742651698916">"正在生成打印作业"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"保存为 PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"所有打印机…"</string>
<string name="print_dialog" msgid="32628687461331979">"打印对话框"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> / <xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"搜索"</string>
<string name="all_printers_label" msgid="3178848870161526399">"所有打印机"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"添加服务"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"纵向"</item>
<item msgid="3199660090246166812">"横向"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"全部"</item>
- <item msgid="6812869625222503603">"范围"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"无法写入文件"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"无法生成打印作业"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"抱歉,操作失败。请重试。"</string>
<string name="print_error_retry" msgid="1426421728784259538">"重试"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"打印机不可用"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"正在取消…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"该打印机目前无法使用。"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"即将显示预览…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-zh-rHK/strings.xml b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
index 534d4bf..3f2f6a7 100644
--- a/packages/PrintSpooler/res/values-zh-rHK/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rHK/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"紙張大小:"</string>
<string name="label_color" msgid="1108690305218188969">"顏色"</string>
<string name="label_orientation" msgid="2853142581990496477">"方向"</string>
- <string name="label_pages" msgid="6300874667546617333">"頁數 (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"例如:1-5,8,11-13"</string>
<string name="print_preview" msgid="8010217796057763343">"預覽列印"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"安裝預覽所需的 PDF 檢視器"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"列印應用程式當機了"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"頁數"</string>
<string name="generating_print_job" msgid="3119608742651698916">"正在產生列印工作"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"儲存為 PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"所有打印機…"</string>
<string name="print_dialog" msgid="32628687461331979">"列印對話方塊"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"搜尋"</string>
<string name="all_printers_label" msgid="3178848870161526399">"所有打印機"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"新增服務"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"直向"</item>
<item msgid="3199660090246166812">"橫向"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"全部"</item>
- <item msgid="6812869625222503603">"範圍"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"無法寫入檔案"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"無法產生列印工作"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"很抱歉,行不通。請再試一次。"</string>
<string name="print_error_retry" msgid="1426421728784259538">"重試"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"印表機無法使用"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"取消中…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"這部打印機目前無法使用。"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"正在準備預覽…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-zh-rTW/strings.xml b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
index 95960c4..3cf1173 100644
--- a/packages/PrintSpooler/res/values-zh-rTW/strings.xml
+++ b/packages/PrintSpooler/res/values-zh-rTW/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"紙張大小:"</string>
<string name="label_color" msgid="1108690305218188969">"色彩"</string>
<string name="label_orientation" msgid="2853142581990496477">"方向"</string>
- <string name="label_pages" msgid="6300874667546617333">"頁數 (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"例如:1—5,8,11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"列印預覽"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"安裝預覽所需的 PDF 檢視器"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"列印應用程式當機了"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"頁數"</string>
<string name="generating_print_job" msgid="3119608742651698916">"正在產生列印工作"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"儲存為 PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"所有印表機…"</string>
<string name="print_dialog" msgid="32628687461331979">"印表機對話方塊"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"搜尋"</string>
<string name="all_printers_label" msgid="3178848870161526399">"所有印表機"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"新增服務"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"縱向"</item>
<item msgid="3199660090246166812">"橫向"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"全部"</item>
- <item msgid="6812869625222503603">"範圍"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"無法寫入檔案"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"無法產生列印工作"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"很抱歉,無法執行這項操作。請再試一次。"</string>
<string name="print_error_retry" msgid="1426421728784259538">"重試"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"印表機無法使用"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"取消中..."</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"這台印表機目前無法使用。"</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"正在準備預覽…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values-zu/strings.xml b/packages/PrintSpooler/res/values-zu/strings.xml
index f46d2db9a..8500d28 100644
--- a/packages/PrintSpooler/res/values-zu/strings.xml
+++ b/packages/PrintSpooler/res/values-zu/strings.xml
@@ -25,16 +25,21 @@
<string name="label_paper_size_summary" msgid="5668204981332138168">"Usayizi wekhasi"</string>
<string name="label_color" msgid="1108690305218188969">"Umbala"</string>
<string name="label_orientation" msgid="2853142581990496477">"Umumo"</string>
- <string name="label_pages" msgid="6300874667546617333">"Amakhasi (<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
+ <!-- no translation found for label_pages (7768589729282182230) -->
+ <skip />
+ <!-- no translation found for template_all_pages (3322235982020148762) -->
+ <skip />
+ <!-- no translation found for template_page_range (428638530038286328) -->
+ <skip />
<string name="pages_range_example" msgid="8558694453556945172">"isb. 1—5, 8, 11—13"</string>
<string name="print_preview" msgid="8010217796057763343">"Ukubuka kuqala kokuphrinta"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"Faka isibukeli se-PDF ukuze uhlole kuqala"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Ukuphrinta uhlelo lokusebenza kukhubazekile"</string>
- <string name="page_count_unknown" msgid="6058852665954511124">"Amakhasi"</string>
<string name="generating_print_job" msgid="3119608742651698916">"Ikhiqiza umsebenzi wokuphrinta"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Londoloza njenge-PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Wonke amaphrinta…"</string>
<string name="print_dialog" msgid="32628687461331979">"Ingxoxo yokuphrinta"</string>
+ <string name="current_page_template" msgid="1386638343571771292">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g> /<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
<string name="search" msgid="5421724265322228497">"Sesha"</string>
<string name="all_printers_label" msgid="3178848870161526399">"Wonke amaphrinta"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"Engeza isevisi"</string>
@@ -71,13 +76,9 @@
<item msgid="4061931020926489228">"Ukuma ngobude"</item>
<item msgid="3199660090246166812">"Ukwakheka kwezwe"</item>
</string-array>
- <string-array name="page_options_labels">
- <item msgid="7421377442011699994">"Konke"</item>
- <item msgid="6812869625222503603">"Ibanga"</item>
- </string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Ayikwazanga ukubhala kufayela"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Ayikwazanga ukukhiqiza umsebenzi wokuphrinta"</string>
+ <string name="print_error_default_message" msgid="8602678405502922346">"Uxolo, lokho akusebenzanga. Zama futhi."</string>
<string name="print_error_retry" msgid="1426421728784259538">"Zama futhi"</string>
- <string name="print_error_printer_unavailable" msgid="6653128543854282851">"Iphrinta ayitholakali"</string>
- <string name="print_operation_canceling" msgid="5274571823242489160">"Iyakhansela…"</string>
+ <string name="print_error_printer_unavailable" msgid="8985614415253203381">"Le phrinta ayitholakali khona manje."</string>
+ <string name="print_preparing_preview" msgid="3939930735671364712">"Ilungiselela ukubuka kuqala…"</string>
</resources>
diff --git a/packages/PrintSpooler/res/values/colors.xml b/packages/PrintSpooler/res/values/colors.xml
index 677fda7..de74a41 100644
--- a/packages/PrintSpooler/res/values/colors.xml
+++ b/packages/PrintSpooler/res/values/colors.xml
@@ -22,4 +22,6 @@
<color name="print_preview_background_color">#F2F1F2</color>
+ <color name="promoted_action_background_color">#FF80CBC4</color>
+
</resources>
diff --git a/packages/PrintSpooler/res/values/constants.xml b/packages/PrintSpooler/res/values/constants.xml
index c17c73b..faad527 100644
--- a/packages/PrintSpooler/res/values/constants.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -42,4 +42,7 @@
<integer name="print_option_column_count">2</integer>
+ <fraction name="page_selected_alpha">100%</fraction>
+ <fraction name="page_unselected_alpha">50%</fraction>
+
</resources>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index dd90bec..5b7fda3 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -44,7 +44,13 @@
<string name="label_orientation">Orientation</string>
<!-- Label of the page selection widget. [CHAR LIMIT=20] -->
- <string name="label_pages">Pages (<xliff:g id="page_count" example="5">%1$s</xliff:g>)</string>
+ <string name="label_pages">Pages</string>
+
+ <!-- Template for the all pages option in the page selection widget. [CHAR LIMIT=20] -->
+ <string name="template_all_pages">All <xliff:g id="page_count" example="100">%1$s</xliff:g></string>
+
+ <!-- Template for the page range option in the page selection widget. [CHAR LIMIT=20] -->
+ <string name="template_page_range">Range of <xliff:g id="page_count" example="100">%1$s</xliff:g></string>
<!-- Page range exmple used as a hint of how to specify such. [CHAR LIMIT=20] -->
<string name="pages_range_example">e.g. 1—5,8,11—13</string>
@@ -58,9 +64,6 @@
<!-- Title of the message that the printing application crashed. [CHAR LIMIT=50] -->
<string name="printing_app_crashed">Printing app crashed</string>
- <!-- Title if the number of pages in a printed document is unknown. [CHAR LIMIT=20] -->
- <string name="page_count_unknown">Pages</string>
-
<!-- Title for the temporary dialog show while an app is generating a print job. [CHAR LIMIT=30] -->
<string name="generating_print_job">Generating print job</string>
@@ -174,14 +177,6 @@
<item>Landscape</item>
</string-array>
- <!-- Page options labels. -->
- <string-array name="page_options_labels">
- <!-- Page range option label: Print all pages [CHAR LIMIT=30] -->
- <item>All</item>
- <!-- Page range option label: Print a page range [CHAR LIMIT=30] -->
- <item>Range</item>
- </string-array>
-
<!-- Permissions -->
<!-- Title of an application permission, listed so the user can choose whether they want
diff --git a/packages/PrintSpooler/res/values/styles.xml b/packages/PrintSpooler/res/values/styles.xml
deleted file mode 100644
index 9637847..0000000
--- a/packages/PrintSpooler/res/values/styles.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources>
-
- <style name="PrintOptionSpinnerStyle">
- <item name="android:paddingTop">0dip</item>
- <item name="android:paddingBottom">0dip</item>
- <item name="android:minHeight">?android:attr/listPreferredItemHeightSmall</item>
- </style>
-
- <style name="PrintOptionEditTextStyle">
-
- <item name="android:singleLine">true</item>
- <item name="android:ellipsize">end</item>
- </style>
-
-</resources>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index e1e6c44..7d0da14 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,19 +16,16 @@
<resources>
- <style name="PrintActivity" parent="@android:style/Theme.DeviceDefault.NoActionBar">
+ <style name="PrintActivity" parent="@android:style/Theme.Material">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">false</item>
- </style>
-
- <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.DeviceDefault.Light">
- <item name="android:actionBarStyle">@style/SelectPrinterActivityActionBarStyle</item>
- </style>
-
- <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.DeviceDefault.Light.ActionBar">
- <item name="android:displayOptions">showTitle</item>
+ <item name="android:colorPrimary">@*android:color/material_blue_grey_900</item>
+ <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_950</item>
+ <item name="android:colorAccent">@*android:color/material_dark_teal_A400</item>
</style>
</resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
index d37ccc0..3134e93 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
@@ -56,8 +56,6 @@
private static final String INTENT_ACTION_RESTART_PRINTJOB = "INTENT_ACTION_RESTART_PRINTJOB";
private static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID";
- private static final String EXTRA_PRINTJOB_LABEL = "EXTRA_PRINTJOB_LABEL";
- private static final String EXTRA_PRINTER_NAME = "EXTRA_PRINTER_NAME";
private final Context mContext;
private final NotificationManager mNotificationManager;
@@ -69,7 +67,7 @@
}
public void onUpdateNotifications(List<PrintJobInfo> printJobs) {
- List<PrintJobInfo> notifyPrintJobs = new ArrayList<PrintJobInfo>();
+ List<PrintJobInfo> notifyPrintJobs = new ArrayList<>();
final int printJobCount = printJobs.size();
for (int i = 0; i < printJobCount; i++) {
@@ -252,8 +250,6 @@
Intent intent = new Intent(mContext, NotificationBroadcastReceiver.class);
intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + printJob.getId().flattenToString());
intent.putExtra(EXTRA_PRINT_JOB_ID, printJob.getId());
- intent.putExtra(EXTRA_PRINTJOB_LABEL, printJob.getLabel());
- intent.putExtra(EXTRA_PRINTER_NAME, printJob.getPrinterName());
return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
}
@@ -302,17 +298,14 @@
String action = intent.getAction();
if (action != null && action.startsWith(INTENT_ACTION_CANCEL_PRINTJOB)) {
PrintJobId printJobId = intent.getExtras().getParcelable(EXTRA_PRINT_JOB_ID);
- String printJobLabel = intent.getExtras().getString(EXTRA_PRINTJOB_LABEL);
- String printerName = intent.getExtras().getString(EXTRA_PRINTER_NAME);
- handleCancelPrintJob(context, printJobId, printJobLabel, printerName);
+ handleCancelPrintJob(context, printJobId);
} else if (action != null && action.startsWith(INTENT_ACTION_RESTART_PRINTJOB)) {
PrintJobId printJobId = intent.getExtras().getParcelable(EXTRA_PRINT_JOB_ID);
handleRestartPrintJob(context, printJobId);
}
}
- private void handleCancelPrintJob(final Context context, final PrintJobId printJobId,
- final String printJobLabel, final String printerName) {
+ private void handleCancelPrintJob(final Context context, final PrintJobId printJobId) {
if (DEBUG) {
Log.i(LOG_TAG, "handleCancelPrintJob() printJobId:" + printJobId);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index d802cd8..8a65a2e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -27,6 +27,7 @@
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.printservice.PrintServiceInfo;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -68,10 +69,10 @@
private static final int MAX_FAVORITE_PRINTER_COUNT = 4;
private final List<PrinterInfo> mPrinters =
- new ArrayList<PrinterInfo>();
+ new ArrayList<>();
private final List<PrinterInfo> mFavoritePrinters =
- new ArrayList<PrinterInfo>();
+ new ArrayList<>();
private final PersistenceManager mPersistenceManager;
@@ -92,7 +93,7 @@
private void computeAndDeliverResult(ArrayMap<PrinterId, PrinterInfo> discoveredPrinters,
ArrayMap<PrinterId, PrinterInfo> favoritePrinters) {
- List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ List<PrinterInfo> printers = new ArrayList<>();
// Add the updated favorite printers.
final int favoritePrinterCount = favoritePrinters.size();
@@ -142,7 +143,7 @@
// The contract is that if we already have a valid,
// result the we have to deliver it immediately.
if (!mPrinters.isEmpty()) {
- deliverResult(new ArrayList<PrinterInfo>(mPrinters));
+ deliverResult(new ArrayList<>(mPrinters));
}
// Always load the data to ensure discovery period is
// started and to make sure obsolete printers are updated.
@@ -184,11 +185,12 @@
+ mDiscoverySession.getPrinters().size()
+ " " + FusedPrintersProvider.this.hashCode());
}
+
updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters);
}
});
final int favoriteCount = mFavoritePrinters.size();
- List<PrinterId> printerIds = new ArrayList<PrinterId>(favoriteCount);
+ List<PrinterId> printerIds = new ArrayList<>(favoriteCount);
for (int i = 0; i < favoriteCount; i++) {
printerIds.add(mFavoritePrinters.get(i).getId());
}
@@ -208,16 +210,19 @@
mPrintersUpdatedBefore = true;
- ArrayMap<PrinterId, PrinterInfo> printersMap =
- new ArrayMap<PrinterId, PrinterInfo>();
+ // Some of the found printers may have be a printer that is in the
+ // history but with its name changed. Hence, we try to update the
+ // printer to use its current name instead of the historical one.
+ mPersistenceManager.updatePrintersHistoricalNamesIfNeeded(printers);
+
+ ArrayMap<PrinterId, PrinterInfo> printersMap = new ArrayMap<>();
final int printerCount = printers.size();
for (int i = 0; i < printerCount; i++) {
PrinterInfo printer = printers.get(i);
printersMap.put(printer.getId(), printer);
}
- ArrayMap<PrinterId, PrinterInfo> favoritePrintersMap =
- new ArrayMap<PrinterId, PrinterInfo>();
+ ArrayMap<PrinterId, PrinterInfo> favoritePrintersMap = new ArrayMap<>();
final int favoritePrinterCount = favoritePrinters.size();
for (int i = 0; i < favoritePrinterCount; i++) {
PrinterInfo favoritePrinter = favoritePrinters.get(i);
@@ -271,6 +276,10 @@
onStopLoading();
}
+ public boolean areHistoricalPrintersLoaded() {
+ return mPersistenceManager.mReadHistoryCompleted;
+ }
+
public void setTrackedPrinter(PrinterId printerId) {
if (isStarted() && mDiscoverySession != null
&& mDiscoverySession.isPrinterDiscoveryStarted()) {
@@ -306,7 +315,7 @@
for (int i = 0; i < favoritePrinterCount; i++) {
PrinterInfo favoritePrinter = mFavoritePrinters.get(i);
if (favoritePrinter.getId().equals(printerId)) {
- newFavoritePrinters = new ArrayList<PrinterInfo>();
+ newFavoritePrinters = new ArrayList<>();
newFavoritePrinters.addAll(mPrinters);
newFavoritePrinters.remove(i);
break;
@@ -340,7 +349,7 @@
private final AtomicFile mStatePersistFile;
- private List<PrinterInfo> mHistoricalPrinters = new ArrayList<PrinterInfo>();
+ private List<PrinterInfo> mHistoricalPrinters = new ArrayList<>();
private boolean mReadHistoryCompleted;
private boolean mReadHistoryInProgress;
@@ -378,17 +387,42 @@
mReadTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
- @SuppressWarnings("unchecked")
+ public void updatePrintersHistoricalNamesIfNeeded(List<PrinterInfo> printers) {
+ boolean writeHistory = false;
+
+ final int printerCount = printers.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo printer = printers.get(i);
+ writeHistory |= renamePrinterIfNeeded(printer);
+ }
+
+ if (writeHistory) {
+ writePrinterHistory();
+ }
+ }
+
+ public boolean renamePrinterIfNeeded(PrinterInfo printer) {
+ boolean renamed = false;
+ final int printerCount = mHistoricalPrinters.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo historicalPrinter = mHistoricalPrinters.get(i);
+ if (historicalPrinter.getId().equals(printer.getId())
+ && !TextUtils.equals(historicalPrinter.getName(), printer.getName())) {
+ mHistoricalPrinters.set(i, printer);
+ renamed = true;
+ }
+ }
+ return renamed;
+ }
+
public void addPrinterAndWritePrinterHistory(PrinterInfo printer) {
if (mHistoricalPrinters.size() >= MAX_HISTORY_LENGTH) {
mHistoricalPrinters.remove(0);
}
mHistoricalPrinters.add(printer);
- new WriteTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,
- new ArrayList<PrinterInfo>(mHistoricalPrinters));
+ writePrinterHistory();
}
- @SuppressWarnings("unchecked")
public void removeHistoricalPrinterAndWritePrinterHistory(PrinterId printerId) {
boolean writeHistory = false;
final int printerCount = mHistoricalPrinters.size();
@@ -400,18 +434,22 @@
}
}
if (writeHistory) {
- new WriteTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,
- new ArrayList<PrinterInfo>(mHistoricalPrinters));
+ writePrinterHistory();
}
}
+ @SuppressWarnings("unchecked")
+ private void writePrinterHistory() {
+ new WriteTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR,
+ new ArrayList<>(mHistoricalPrinters));
+ }
+
public boolean isHistoryChanged() {
return mLastReadHistoryTimestamp != mStatePersistFile.getBaseFile().lastModified();
}
private List<PrinterInfo> computeFavoritePrinters(List<PrinterInfo> printers) {
- Map<PrinterId, PrinterRecord> recordMap =
- new ArrayMap<PrinterId, PrinterRecord>();
+ Map<PrinterId, PrinterRecord> recordMap = new ArrayMap<>();
// Recompute the weights.
float currentWeight = 1.0f;
@@ -429,14 +467,14 @@
}
// Soft the favorite printers.
- List<PrinterRecord> favoriteRecords = new ArrayList<PrinterRecord>(
+ List<PrinterRecord> favoriteRecords = new ArrayList<>(
recordMap.values());
Collections.sort(favoriteRecords);
// Write the favorites to the output.
final int favoriteCount = Math.min(favoriteRecords.size(),
MAX_FAVORITE_PRINTER_COUNT);
- List<PrinterInfo> favoritePrinters = new ArrayList<PrinterInfo>(favoriteCount);
+ List<PrinterInfo> favoritePrinters = new ArrayList<>(favoriteCount);
for (int i = 0; i < favoriteCount; i++) {
PrinterInfo printer = favoriteRecords.get(i).printer;
favoritePrinters.add(printer);
@@ -478,7 +516,7 @@
List<PrintServiceInfo> services = printManager
.getEnabledPrintServices();
- Set<ComponentName> enabledComponents = new ArraySet<ComponentName>();
+ Set<ComponentName> enabledComponents = new ArraySet<>();
final int installedServiceCount = services.size();
for (int i = 0; i < installedServiceCount; i++) {
ServiceInfo serviceInfo = services.get(i).getResolveInfo().serviceInfo;
@@ -524,28 +562,23 @@
Log.i(LOG_TAG, "No existing printer history "
+ FusedPrintersProvider.this.hashCode());
}
- return new ArrayList<PrinterInfo>();
+ return new ArrayList<>();
}
try {
- List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ List<PrinterInfo> printers = new ArrayList<>();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(in, null);
parseState(parser, printers);
// Take a note which version of the history was read.
mLastReadHistoryTimestamp = mStatePersistFile.getBaseFile().lastModified();
return printers;
- } catch (IllegalStateException ise) {
- Slog.w(LOG_TAG, "Failed parsing ", ise);
- } catch (NullPointerException npe) {
- Slog.w(LOG_TAG, "Failed parsing ", npe);
- } catch (NumberFormatException nfe) {
- Slog.w(LOG_TAG, "Failed parsing ", nfe);
- } catch (XmlPullParserException xppe) {
- Slog.w(LOG_TAG, "Failed parsing ", xppe);
- } catch (IOException ioe) {
- Slog.w(LOG_TAG, "Failed parsing ", ioe);
- } catch (IndexOutOfBoundsException iobe) {
- Slog.w(LOG_TAG, "Failed parsing ", iobe);
+ } catch (IllegalStateException
+ | NullPointerException
+ | NumberFormatException
+ | XmlPullParserException
+ | IOException
+ | IndexOutOfBoundsException e) {
+ Slog.w(LOG_TAG, "Failed parsing ", e);
} finally {
IoUtils.closeQuietly(in);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index 8885a7b..30808ba 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -90,7 +90,10 @@
private int mSelectedPageCount;
private float mSelectedPageElevation;
+ private float mSelectedPageAlpha;
+
private float mUnselectedPageElevation;
+ private float mUnselectedPageAlpha;
private int mPreviewPageMargin;
private int mPreviewListPadding;
@@ -127,8 +130,13 @@
mSelectedPageElevation = mContext.getResources().getDimension(
R.dimen.selected_page_elevation);
+ mSelectedPageAlpha = mContext.getResources().getFraction(
+ R.fraction.page_selected_alpha, 1, 1);
+
mUnselectedPageElevation = mContext.getResources().getDimension(
R.dimen.unselected_page_elevation);
+ mUnselectedPageAlpha = mContext.getResources().getFraction(
+ R.fraction.page_unselected_alpha, 1, 1);
mPreviewPageMargin = mContext.getResources().getDimensionPixelSize(
R.dimen.preview_page_margin);
@@ -326,22 +334,24 @@
content.init(provider, mMediaSize, mMinMargins);
- CheckBox checkbox = (CheckBox) page.findViewById(R.id.page_selector);
- checkbox.setTag(myHolder);
+ View pageSelector = page.findViewById(R.id.page_selector);
+ pageSelector.setTag(myHolder);
if (pageCount > 1) {
- checkbox.setOnClickListener(mPageClickListener);
- checkbox.setVisibility(View.VISIBLE);
+ pageSelector.setOnClickListener(mPageClickListener);
+ pageSelector.setVisibility(View.VISIBLE);
} else {
- checkbox.setOnClickListener(null);
- checkbox.setVisibility(View.GONE);
+ pageSelector.setOnClickListener(null);
+ pageSelector.setVisibility(View.GONE);
}
if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) >= 0) {
- checkbox.setChecked(true);
+ pageSelector.setSelected(true);
page.setTranslationZ(mSelectedPageElevation);
+ page.setAlpha(mSelectedPageAlpha);
} else {
- checkbox.setChecked(false);
+ pageSelector.setSelected(false);
page.setTranslationZ(mUnselectedPageElevation);
+ page.setAlpha(mUnselectedPageAlpha);
}
TextView pageNumberView = (TextView) page.findViewById(R.id.page_number);
@@ -379,6 +389,7 @@
mSelectedPages = selectedPages;
mSelectedPageCount = PageRangeUtils.getNormalizedPageCount(
mSelectedPages, mDocumentPageCount);
+ updatePreviewAreaAndPageSize();
notifyDataSetChanged();
}
return mSelectedPages;
@@ -756,15 +767,17 @@
MyViewHolder holder = (MyViewHolder) page.getTag();
final int pageInAdapter = holder.mPageInAdapter;
final int pageInDocument = computePageIndexInDocument(pageInAdapter);
- CheckBox pageSelector = (CheckBox) page.findViewById(R.id.page_selector);
+ View pageSelector = page.findViewById(R.id.page_selector);
if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) < 0) {
mConfirmedPagesInDocument.put(pageInDocument, null);
- pageSelector.setChecked(true);
- page.animate().translationZ(mSelectedPageElevation);
+ pageSelector.setSelected(true);
+ page.animate().translationZ(mSelectedPageElevation)
+ .alpha(mSelectedPageAlpha);
} else {
mConfirmedPagesInDocument.remove(pageInDocument);
- pageSelector.setChecked(false);
- page.animate().translationZ(mUnselectedPageElevation);
+ pageSelector.setSelected(false);
+ page.animate().translationZ(mUnselectedPageElevation)
+ .alpha(mUnselectedPageAlpha);
}
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 5ec2111..a01e45c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -157,7 +157,6 @@
private EditText mCopiesEditText;
- private TextView mPageRangeOptionsTitle;
private TextView mPageRangeTitle;
private EditText mPageRangeEditText;
@@ -190,12 +189,14 @@
private MediaSizeComparator mMediaSizeComparator;
- private PrinterInfo mOldCurrentPrinter;
+ private PrinterInfo mCurrentPrinter;
private PageRange[] mSelectedPages;
private String mCallingPackageName;
+ private int mCurrentPageCount;
+
private int mState;
private int mUiState = UI_STATE_PREVIEW;
@@ -576,7 +577,7 @@
}
}
- PrinterId printerId = mOldCurrentPrinter.getId();
+ PrinterId printerId = mCurrentPrinter.getId();
final int index = mDestinationSpinnerAdapter.getPrinterIndex(printerId);
mDestinationSpinner.setSelection(index);
}
@@ -810,7 +811,7 @@
}
private void requestCreatePdfFileOrFinish() {
- if (getCurrentPrinter() == mDestinationSpinnerAdapter.getPdfPrinter()) {
+ if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
startCreateDocumentActivity();
} else {
finish();
@@ -898,19 +899,14 @@
}
private void addCurrentPrinterToHistory() {
- PrinterInfo currentPrinter = getCurrentPrinter();
- if (currentPrinter != null) {
+ if (mCurrentPrinter != null) {
PrinterId fakePdfPrinterId = mDestinationSpinnerAdapter.getPdfPrinter().getId();
- if (!currentPrinter.getId().equals(fakePdfPrinterId)) {
- mPrinterRegistry.addHistoricalPrinter(currentPrinter);
+ if (!mCurrentPrinter.getId().equals(fakePdfPrinterId)) {
+ mPrinterRegistry.addHistoricalPrinter(mCurrentPrinter);
}
}
}
- private PrinterInfo getCurrentPrinter() {
- return ((PrinterHolder) mDestinationSpinner.getSelectedItem()).printer;
- }
-
private void cancelPrint() {
setState(STATE_PRINT_CANCELED);
updateOptionsUi();
@@ -970,7 +966,6 @@
mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
mDestinationSpinner.setOnItemSelectedListener(itemSelectedListener);
- mDestinationSpinner.setSelection(0);
// Media size.
mMediaSizeSpinnerAdapter = new ArrayAdapter<>(
@@ -1002,19 +997,10 @@
// Range options
ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter =
new ArrayAdapter<>(this, R.layout.spinner_dropdown_item, R.id.title);
- final int[] rangeOptionsValues = getResources().getIntArray(
- R.array.page_options_values);
- String[] rangeOptionsLabels = getResources().getStringArray(
- R.array.page_options_labels);
- final int rangeOptionsCount = rangeOptionsLabels.length;
- for (int i = 0; i < rangeOptionsCount; i++) {
- rangeOptionsSpinnerAdapter.add(new SpinnerItem<>(
- rangeOptionsValues[i], rangeOptionsLabels[i]));
- }
- mPageRangeOptionsTitle = (TextView) findViewById(R.id.range_options_title);
mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
mRangeOptionsSpinner.setAdapter(rangeOptionsSpinnerAdapter);
mRangeOptionsSpinner.setOnItemSelectedListener(itemSelectedListener);
+ updatePageRangeOptions(PrintDocumentInfo.PAGE_COUNT_UNKNOWN);
// Page range
mPageRangeTitle = (TextView) findViewById(R.id.page_range_title);
@@ -1036,16 +1022,14 @@
@Override
public void onClick(View view) {
if (view == mPrintButton) {
- PrinterInfo currentPrinter = getCurrentPrinter();
- if (currentPrinter != null) {
+ if (mCurrentPrinter != null) {
confirmPrint();
} else {
cancelPrint();
}
} else if (view == mMoreOptionsButton) {
- PrinterInfo currentPrinter = getCurrentPrinter();
- if (currentPrinter != null) {
- startAdvancedPrintOptionsActivity(currentPrinter);
+ if (mCurrentPrinter != null) {
+ startAdvancedPrintOptionsActivity(mCurrentPrinter);
}
}
}
@@ -1090,8 +1074,7 @@
// If no current printer, or it has no capabilities, or it is not
// available, we disable all print options except the destination.
- PrinterInfo currentPrinter = getCurrentPrinter();
- if (currentPrinter == null || !canPrint(currentPrinter)) {
+ if (mCurrentPrinter == null || !canPrint(mCurrentPrinter)) {
mCopiesEditText.setEnabled(false);
mMediaSizeSpinner.setEnabled(false);
mColorModeSpinner.setEnabled(false);
@@ -1103,7 +1086,7 @@
return;
}
- PrinterCapabilitiesInfo capabilities = currentPrinter.getCapabilities();
+ PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
PrintAttributes defaultAttributes = capabilities.getDefaults();
// Destination.
@@ -1274,24 +1257,25 @@
mPageRangeTitle.setVisibility(View.INVISIBLE);
}
}
- String title = (pageCount != PrintDocumentInfo.PAGE_COUNT_UNKNOWN)
- ? getString(R.string.label_pages, String.valueOf(pageCount))
- : getString(R.string.page_count_unknown);
- mPageRangeOptionsTitle.setText(title);
} else {
if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
mRangeOptionsSpinner.setSelection(0);
mPageRangeEditText.setText("");
}
mRangeOptionsSpinner.setEnabled(false);
- mPageRangeOptionsTitle.setText(getString(R.string.page_count_unknown));
mPageRangeEditText.setEnabled(false);
mPageRangeEditText.setVisibility(View.INVISIBLE);
mPageRangeTitle.setVisibility(View.INVISIBLE);
}
+ final int newPageCount = getAdjustedPageCount(info);
+ if (newPageCount != mCurrentPageCount) {
+ mCurrentPageCount = newPageCount;
+ updatePageRangeOptions(newPageCount);
+ }
+
// Advanced print options
- ComponentName serviceName = currentPrinter.getId().getServiceName();
+ ComponentName serviceName = mCurrentPrinter.getId().getServiceName();
if (!TextUtils.isEmpty(PrintOptionUtils.getAdvancedOptionsActivityName(
this, serviceName))) {
mAdvancedPrintOptionsContainer.setVisibility(View.VISIBLE);
@@ -1302,7 +1286,7 @@
}
// Print
- if (mDestinationSpinnerAdapter.getPdfPrinter() != currentPrinter) {
+ if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
mPrintButton.setImageResource(com.android.internal.R.drawable.ic_print);
} else {
mPrintButton.setImageResource(com.android.internal.R.drawable.ic_menu_save);
@@ -1317,7 +1301,7 @@
}
// Copies
- if (mDestinationSpinnerAdapter.getPdfPrinter() != currentPrinter) {
+ if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
mCopiesEditText.setEnabled(true);
} else {
mCopiesEditText.setEnabled(false);
@@ -1329,6 +1313,27 @@
}
}
+ private void updatePageRangeOptions(int pageCount) {
+ ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter =
+ (ArrayAdapter) mRangeOptionsSpinner.getAdapter();
+ rangeOptionsSpinnerAdapter.clear();
+
+ final int[] rangeOptionsValues = getResources().getIntArray(
+ R.array.page_options_values);
+
+ String pageCountLabel = (pageCount > 0) ? String.valueOf(pageCount) : "";
+ String[] rangeOptionsLabels = new String[] {
+ getString(R.string.template_all_pages, pageCountLabel),
+ getString(R.string.template_page_range, pageCountLabel)
+ };
+
+ final int rangeOptionsCount = rangeOptionsLabels.length;
+ for (int i = 0; i < rangeOptionsCount; i++) {
+ rangeOptionsSpinnerAdapter.add(new SpinnerItem<>(
+ rangeOptionsValues[i], rangeOptionsLabels[i]));
+ }
+ }
+
private PageRange[] computeSelectedPages() {
if (hasErrors()) {
return null;
@@ -1395,8 +1400,7 @@
}
public void onPrinterAvailable(PrinterInfo printer) {
- PrinterInfo currentPrinter = getCurrentPrinter();
- if (currentPrinter.equals(printer)) {
+ if (mCurrentPrinter.equals(printer)) {
setState(STATE_CONFIGURING);
if (canUpdateDocument()) {
updateDocument(true, false);
@@ -1407,7 +1411,7 @@
}
public void onPrinterUnavailable(PrinterInfo printer) {
- if (getCurrentPrinter().getId().equals(printer.getId())) {
+ if (mCurrentPrinter.getId().equals(printer.getId())) {
setState(STATE_PRINTER_UNAVAILABLE);
if (mPrintedDocument.isUpdating()) {
mPrintedDocument.cancel();
@@ -1444,15 +1448,14 @@
return false;
}
- PrinterInfo currentPrinter = getCurrentPrinter();
- if (currentPrinter == null) {
+ if (mCurrentPrinter == null) {
return false;
}
- PrinterCapabilitiesInfo capabilities = currentPrinter.getCapabilities();
+ PrinterCapabilitiesInfo capabilities = mCurrentPrinter.getCapabilities();
if (capabilities == null) {
return false;
}
- if (currentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) {
+ if (mCurrentPrinter.getStatus() == PrinterInfo.STATUS_UNAVAILABLE) {
return false;
}
@@ -1560,8 +1563,13 @@
private final PrinterHolder mFakePdfPrinterHolder;
+ private boolean mHistoricalPrintersLoaded;
+
public DestinationAdapter() {
- addPrinters(mPrinterHolders, mPrinterRegistry.getPrinters());
+ mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
+ if (mHistoricalPrintersLoaded) {
+ addPrinters(mPrinterHolders, mPrinterRegistry.getPrinters());
+ }
mPrinterRegistry.setOnPrintersChangeListener(this);
mFakePdfPrinterHolder = new PrinterHolder(createFakePdfPrinter());
}
@@ -1602,7 +1610,10 @@
@Override
public int getCount() {
- return Math.min(mPrinterHolders.size() + 2, DEST_ADAPTER_MAX_ITEM_COUNT);
+ if (mHistoricalPrintersLoaded) {
+ return Math.min(mPrinterHolders.size() + 2, DEST_ADAPTER_MAX_ITEM_COUNT);
+ }
+ return 0;
}
@Override
@@ -1731,6 +1742,12 @@
// not shown in the initial short list. Therefore, we have
// to keep the printer order.
+ // Check if historical printers are loaded as this adapter is open
+ // for busyness only if they are. This member is updated here and
+ // when the adapter is created because the historical printers may
+ // be loaded before or after the adapter is created.
+ mHistoricalPrintersLoaded = mPrinterRegistry.areHistoricalPrintersLoaded();
+
// No old printers - do not bother keeping their position.
if (mPrinterHolders.isEmpty()) {
addPrinters(mPrinterHolders, printers);
@@ -1839,7 +1856,7 @@
private final class PrintersObserver extends DataSetObserver {
@Override
public void onChanged() {
- PrinterInfo oldPrinterState = mOldCurrentPrinter;
+ PrinterInfo oldPrinterState = mCurrentPrinter;
if (oldPrinterState == null) {
return;
}
@@ -1927,14 +1944,15 @@
return;
}
- PrinterInfo currentPrinter = getCurrentPrinter();
+ PrinterHolder currentItem = (PrinterHolder) mDestinationSpinner.getSelectedItem();
+ PrinterInfo currentPrinter = (currentItem != null) ? currentItem.printer : null;
// Why on earth item selected is called if no selection changed.
- if (mOldCurrentPrinter == currentPrinter) {
+ if (mCurrentPrinter == currentPrinter) {
return;
}
- mOldCurrentPrinter = currentPrinter;
+ mCurrentPrinter = currentPrinter;
PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
currentPrinter.getId());
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
index 7816d66..a3d7f01 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrinterRegistry.java
@@ -83,6 +83,10 @@
getPrinterProvider().setTrackedPrinter(printerId);
}
+ public boolean areHistoricalPrintersLoaded() {
+ return getPrinterProvider().areHistoricalPrintersLoaded();
+ }
+
private FusedPrintersProvider getPrinterProvider() {
Loader<?> loader = mActivity.getLoaderManager().getLoader(LOADER_ID_PRINTERS_LOADER);
return (FusedPrintersProvider) loader;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index afdbb2a..efb030e 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -22,6 +22,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
import com.android.printspooler.R;
/**
@@ -147,6 +148,7 @@
mExpandCollapseIcon = findViewById(R.id.expand_collapse_icon);
mExpandCollapseHandle.setOnClickListener(this);
+ mSummaryContent.setOnClickListener(this);
// Make sure we start in a closed options state.
onDragProgress(1.0f);
@@ -154,7 +156,7 @@
@Override
public void onClick(View view) {
- if (view == mExpandCollapseHandle) {
+ if (view == mExpandCollapseHandle || view == mSummaryContent) {
if (isOptionsClosed() && mOptionsStateController.canOpenOptions()) {
openOptions();
} else if (isOptionsOpened() && mOptionsStateController.canCloseOptions()) {
@@ -300,6 +302,7 @@
mSummaryContent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mDraggableContent.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mMoreOptionsContainer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ensureImeClosedAndInputFocusCleared();
}
if ((mDragProgress > 0 && progress == 0)
|| (mDragProgress < 1.0f && progress == 1.0f)) {
@@ -350,6 +353,18 @@
}
}
+ private void ensureImeClosedAndInputFocusCleared() {
+ View focus = findFocus();
+ if (focus != null) {
+ InputMethodManager imm = (InputMethodManager) mContext.getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ if (imm.isActive(focus)) {
+ imm.hideSoftInputFromWindow(getWindowToken(), 0);
+ }
+ focus.clearFocus();
+ }
+ }
+
private final class DragCallbacks extends ViewDragHelper.Callback {
@Override
public boolean tryCaptureView(View child, int pointerId) {
diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml
index 3dc6a0f..ef7d7b3 100644
--- a/packages/Shell/res/values-af/strings.xml
+++ b/packages/Shell/res/values-af/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Tuisskerm"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Foutverslag vasgevang"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Raak om jou foutverslag te deel"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Raak om jou foutverslag te deel"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Foutverslae bevat data van die stelsel se verskillende loglêers af, insluitend persoonlike en private inligting. Deel foutverslae net met programme en mense wat jy vertrou."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Wys hierdie boodskap volgende keer"</string>
</resources>
diff --git a/packages/Shell/res/values-am/strings.xml b/packages/Shell/res/values-am/strings.xml
index c90a5f5..fa86993 100644
--- a/packages/Shell/res/values-am/strings.xml
+++ b/packages/Shell/res/values-am/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"ቀፎ"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"የሳንካ ሪፖርት ተይዟል"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"የሳንካ ሪፖርትዎን ለማጋራት ይንክኩ"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"የሳንካ ሪፖርትዎን ለማጋራት ይንክኩ"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"የሳንካ ሪፖርቶች የግል መረጃን ጨምሮ ከበርካታ የስርዓቱ ምዝግብ ማስታወሻዎች የመጣ ውሂብን ይዟል። የሳንካ ሪፖርቶች ለሚያምኗቸው መተግበሪያዎችን እና ሰዎችን ብቻ ያጋሩ።"</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ይህን መልዕክት በሚቀጥለው ጊዜ አሳይ"</string>
</resources>
diff --git a/packages/Shell/res/values-ar/strings.xml b/packages/Shell/res/values-ar/strings.xml
index 6a595d5..69d7d3f 100644
--- a/packages/Shell/res/values-ar/strings.xml
+++ b/packages/Shell/res/values-ar/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"تم الحصول على تقرير الأخطاء"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"المس لمشاركة تقرير الأخطاء"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"مرر بسرعة لليمين لمشاركة تقرير الخطأ"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"المس لمشاركة تقرير الأخطاء"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"تحتوي تقارير الأخطاء على بيانات من ملفات سجلات النظام المتنوعة، بما في ذلك معلومات شخصية وخاصة. لا تشارك تقارير الأخطاء إلا مع التطبيقات والأشخاص الموثوق بهم."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"إظهار هذه الرسالة في المرة القادمة"</string>
</resources>
diff --git a/packages/Shell/res/values-bg/strings.xml b/packages/Shell/res/values-bg/strings.xml
index 2fae953..d1fbd4b 100644
--- a/packages/Shell/res/values-bg/strings.xml
+++ b/packages/Shell/res/values-bg/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Команден ред"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Отчетът за програмни грешки е записан"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Докоснете, за да споделите отчета си за програмни грешки"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Докоснете, за да споделите отчета си за програмни грешки"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Отчетите за програмни грешки съдържат данни от различни регистрационни файлове на системата, включително лична и поверителна информация. Споделяйте ги само с приложения и хора, на които имате доверие."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Това съобщение да се показва следващия път"</string>
</resources>
diff --git a/packages/Shell/res/values-ca/strings.xml b/packages/Shell/res/values-ca/strings.xml
index 8bf368a..520a299 100644
--- a/packages/Shell/res/values-ca/strings.xml
+++ b/packages/Shell/res/values-ca/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Protecció"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"S\'ha registrat l\'informe d\'error"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Toca aquí per compartir el teu informe d\'error."</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca aquí per compartir el teu informe d\'error."</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Els informes d\'error contenen dades dels diferents fitxers de registre del sistema, inclosa informació privada i personal. Comparteix els informes d\'error només amb les aplicacions i amb les persones en qui confies."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostra aquest missatge la propera vegada"</string>
</resources>
diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml
index 3f1c921..e96b704 100644
--- a/packages/Shell/res/values-cs/strings.xml
+++ b/packages/Shell/res/values-cs/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Prostředí"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Bylo vytvořeno chybové hlášení"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Chybové hlášení můžete sdílet klepnutím."</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Chybové hlášení můžete sdílet klepnutím."</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Chybová hlášení obsahují data z různých souborů protokolů systému včetně osobních a soukromých informací. Chybová hlášení sdílejte pouze s aplikacemi a uživateli, kterým důvěřujete."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobrazit tuto zprávu příště"</string>
</resources>
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index fa30c96..ab6323f 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Fejlrapporten er registreret"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Tryk for at dele din fejlrapport"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tryk for at dele din fejlrapport"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Fejlrapporter indeholder data fra systemets forskellige logfiler, f.eks. personlige og private oplysninger. Del kun fejlrapporter med apps og personer, du har tillid til."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Vis denne underretning næste gang"</string>
</resources>
diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml
index 34481ba..a2b1e04 100644
--- a/packages/Shell/res/values-de/strings.xml
+++ b/packages/Shell/res/values-de/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Fehlerbericht erfasst"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Tippen, um Fehlerbericht zu teilen"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tippen, um Fehlerbericht zu teilen"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Fehlerberichte enthalten Daten aus verschiedenen Protokolldateien des Systems, darunter auch personenbezogene und private Daten. Teilen Sie Fehlerberichte nur mit Apps und Personen, denen Sie vertrauen."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Diese Nachricht nächstes Mal zeigen"</string>
</resources>
diff --git a/packages/Shell/res/values-el/strings.xml b/packages/Shell/res/values-el/strings.xml
index 9b1eb7b..2bcddb4 100644
--- a/packages/Shell/res/values-el/strings.xml
+++ b/packages/Shell/res/values-el/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Κέλυφος"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Η λήψη της αναφοράς ήταν επιτυχής"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Αγγίξτε για να μοιραστείτε τη αναφορά σφαλμάτων"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Αγγίξτε για να μοιραστείτε τη αναφορά σφαλμάτων"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Οι αναφορές σφαλμάτων περιέχουν δεδομένα από τα διάφορα αρχεία καταγραφής του συστήματος, συμπεριλαμβανομένων προσωπικών και ιδιωτικών πληροφοριών. Να μοιράζεστε αναφορές σφαλμάτων μόνο με εφαρμογές και άτομα που εμπιστεύεστε."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Εμφάνιση αυτού του μηνύματος την επόμενη φορά"</string>
</resources>
diff --git a/packages/Shell/res/values-en-rGB/strings.xml b/packages/Shell/res/values-en-rGB/strings.xml
index 68708e0..fab4223 100644
--- a/packages/Shell/res/values-en-rGB/strings.xml
+++ b/packages/Shell/res/values-en-rGB/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Bug report captured"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Touch to share your bug report"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Touch to share your bug report"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
</resources>
diff --git a/packages/Shell/res/values-en-rIN/strings.xml b/packages/Shell/res/values-en-rIN/strings.xml
index 68708e0..fab4223 100644
--- a/packages/Shell/res/values-en-rIN/strings.xml
+++ b/packages/Shell/res/values-en-rIN/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Bug report captured"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Touch to share your bug report"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swipe left to share your bug report"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Touch to share your bug report"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people that you trust."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Show this message next time"</string>
</resources>
diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml
index f1ec75c..2eeda78 100644
--- a/packages/Shell/res/values-es-rUS/strings.xml
+++ b/packages/Shell/res/values-es-rUS/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Informe de errores capturado"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Toca para compartir tu informe de errores."</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca para compartir tu informe de errores."</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Los informes de errores contienen datos de los distintos archivos de registro del sistema, incluida la información personal y privada. Comparte los informes de errores únicamente con aplicaciones y personas en las que confíes."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar este mensaje la próxima vez"</string>
</resources>
diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml
index 7990672..f5901b2 100644
--- a/packages/Shell/res/values-es/strings.xml
+++ b/packages/Shell/res/values-es/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Informe de error capturado"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Toca para compartir tu informe de error"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toca para compartir tu informe de error"</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>
</resources>
diff --git a/packages/Shell/res/values-et-rEE/strings.xml b/packages/Shell/res/values-et-rEE/strings.xml
index 7788158..d6e3170 100644
--- a/packages/Shell/res/values-et-rEE/strings.xml
+++ b/packages/Shell/res/values-et-rEE/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Kest"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Veaaruanne jäädvustati"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Veaaruande jagamiseks puudutage"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Veaaruande jagamiseks puudutage"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Veaaruanded sisaldavad andmeid erinevatest süsteemi logifailidest, sh isiklikku ja privaatset teavet. Jagage veaaruandeid ainult usaldusväärsete rakenduste ja inimestega."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Kuva see sõnum järgmisel korral"</string>
</resources>
diff --git a/packages/Shell/res/values-fa/strings.xml b/packages/Shell/res/values-fa/strings.xml
index 2d2c223..3e5a5a4 100644
--- a/packages/Shell/res/values-fa/strings.xml
+++ b/packages/Shell/res/values-fa/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"گزارش اشکال دریافت شد"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"جهت اشتراکگذاری گزارش اشکال خود لمس کنید"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"جهت اشتراکگذاری گزارش اشکال خود لمس کنید"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"گزارشهای اشکال حاوی دادههایی از فایلهای گزارش مختلف در سیستم هستند، شامل اطلاعات شخصی و خصوصی. گزارشهای اشکال را فقط با افراد و برنامههای مورد اعتماد خود به اشتراک بگذارید."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"دفعه بعد این پیام نشان داده شود"</string>
</resources>
diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml
index ee57279..fbb1c2d 100644
--- a/packages/Shell/res/values-fi/strings.xml
+++ b/packages/Shell/res/values-fi/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Komentotulkki"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Virheraportti tallennettu"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Jaa virheraportti koskettamalla tätä"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Jaa virheraportti koskettamalla tätä"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Virheraportit sisältävät järjestelmän lokitietoja, ja niihin voi sisältyä henkilökohtaisia ja yksityisiä tietoja. Jaa virheraportteja vain luotettaville sovelluksille ja käyttäjille."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Näytä tämä viesti seuraavalla kerralla"</string>
</resources>
diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml
index c672f23..caf9e37 100644
--- a/packages/Shell/res/values-fr-rCA/strings.xml
+++ b/packages/Shell/res/values-fr-rCA/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Rapport de bogue enregistré"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Appuyer ici pour partager votre rapport de bogue"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Appuyer ici pour partager votre rapport de bogue"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bogue contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bogue qu\'avec les applications et les personnes que vous estimez fiables."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
</resources>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index 12f5e88..67ce3bc 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Rapport de bug enregistré"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Appuyez ici pour partager le rapport de bug"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Appuyez ici pour partager le rapport de bug"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bug contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bug qu\'avec les applications et les personnes que vous estimez fiables."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
</resources>
diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml
index f889311..daf6553 100644
--- a/packages/Shell/res/values-hi/strings.xml
+++ b/packages/Shell/res/values-hi/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"शेल"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"बग रिपोर्ट कैप्चर कर ली गई"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"अपनी बग रिपोर्ट साझा करने के लिए स्पर्श करें"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"अपनी बग रिपोर्ट साझा करने के लिए बाएं स्वाइप करें"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"अपनी बग रिपोर्ट साझा करने के लिए स्पर्श करें"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"बग रिपोर्ट में व्यक्तिगत और निजी जानकारी सहित, सिस्टम की विभिन्न लॉग फ़ाइलों का डेटा होता है. बग रिपोर्ट केवल विश्वसनीय ऐप्स और व्यक्तियों से ही साझा करें."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"यह संदेश अगली बार दिखाएं"</string>
</resources>
diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml
index 2c4ea23..8b1fb42 100644
--- a/packages/Shell/res/values-hr/strings.xml
+++ b/packages/Shell/res/values-hr/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Ljuska"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Prijava programske pogreške snimljena je"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Dodirnite za dijeljenje prijave programske pogreške"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Dodirnite za dijeljenje prijave programske pogreške"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Prijave programskih pogrešaka sadržavaju podatke iz različitih datoteka zapisnika sustava, uključujući osobne i privatne informacije. Prijave programskih pogrešaka dijelite samo s aplikacijama i osobama koje smatrate pouzdanima."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Prikaži tu poruku sljedeći put"</string>
</resources>
diff --git a/packages/Shell/res/values-hu/strings.xml b/packages/Shell/res/values-hu/strings.xml
index 8d684da..ebd77b1 100644
--- a/packages/Shell/res/values-hu/strings.xml
+++ b/packages/Shell/res/values-hu/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Héj"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Programhiba-jelentés rögzítve"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Érintse meg a programhiba-jelentés megosztásához"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Érintse meg a programhiba-jelentés megosztásához"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"A programhiba-jelentések a rendszer különféle naplófájljaiból származó adatokat tartalmaznak, köztük személyes és magánjellegű információkat is. Csak olyan alkalmazásokkal és személyekkel osszon meg programhiba-jelentéseket, amelyekben vagy akikben megbízik."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Üzenet mutatása legközelebb"</string>
</resources>
diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml
index ea7fa9f..974f5b0 100644
--- a/packages/Shell/res/values-hy-rAM/strings.xml
+++ b/packages/Shell/res/values-hy-rAM/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Խեցի"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Վրիպակի զեկույց ստացվեց"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Հպեք` ձեր վրիպակի մասին զեկույցը տարածելու համար"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Հպեք` ձեր վրիպակի մասին զեկույցը տարածելու համար"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Վրիպակի զեկույցները պարունակում են տվյալներ համակարգի տարբեր մուտքի ֆայլերից, այդ թվում նաև անհատական և գաղտնի տեղեկություններ: Վրիպակի զեկույցները կիսեք միայն այն հավելվածների և մարդկանց հետ, որոնց վստահում եք:"</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Այս հաղորդագրությունը ցույց տալ հաջորդ անգամ"</string>
</resources>
diff --git a/packages/Shell/res/values-in/strings.xml b/packages/Shell/res/values-in/strings.xml
index 8ea2584..abe7abf 100644
--- a/packages/Shell/res/values-in/strings.xml
+++ b/packages/Shell/res/values-in/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Kerangka"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Laporan bug tercatat"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Sentuh untuk membagikan laporan bug Anda"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Sentuh untuk membagikan laporan bug Anda"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Laporan bug berisi data dari berbagai file log sistem, termasuk informasi pribadi dan rahasia. Hanya bagikan laporan bug dengan aplikasi dan orang yang Anda percaya."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Tampilkan pesan ini lain kali"</string>
</resources>
diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index 18a03fe..9e86aff 100644
--- a/packages/Shell/res/values-it/strings.xml
+++ b/packages/Shell/res/values-it/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Segnalazione di bug acquisita"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Tocca per condividere la segnalazione di bug"</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="3559904746859400732">"Tocca per condividere la segnalazione di bug"</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>
</resources>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index ded860c..4e06d03 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"מעטפת"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"דוח הבאגים צולם"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"גע כדי לשתף את דוח הבאגים שלך"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"החלק שמאלה כדי לשתף את דוח הבאגים"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"גע כדי לשתף את דוח הבאגים שלך"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"דוחות על באגים כוללים נתונים מקובצי היומן השונים במערכת, כולל מידע אישי ופרטי. שתף דוחות באגים רק עם אפליקציות ואנשים שאתה סומך עליהם."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"הצג את ההודעה הזו בפעם הבאה"</string>
</resources>
diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml
index db34041..9e3c9ab 100644
--- a/packages/Shell/res/values-ja/strings.xml
+++ b/packages/Shell/res/values-ja/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"シェル"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"バグレポートが記録されました"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"バグレポートを共有するにはタップします"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"バグレポートを共有するにはタップします"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"バグレポートには、個人の非公開情報など、システムのさまざまなログファイルのデータが含まれます。共有する場合は信頼するアプリとユーザーのみを選択してください。"</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"このメッセージを次回も表示する"</string>
</resources>
diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml
index 7d9c72a..48da1b46 100644
--- a/packages/Shell/res/values-ka-rGE/strings.xml
+++ b/packages/Shell/res/values-ka-rGE/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"გარეკანი"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"ანგარიში ხარვეზების შესახებ შექმნილია"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"შეეხეთ თქვენი ხარვეზების ანგარიშის გასაზიარებლად"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"შეეხეთ თქვენი ხარვეზების ანგარიშის გასაზიარებლად"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"ხარვეზის ანგარიშები მოიცავს მონაცემებს სხვადასხვა სისტემური ჟურნალის ფაილებიდან, მათ შორის პირად და კონფიდენციალურ ინფორმაციას."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"შემდგომში აჩვენე ეს შეტყობინება"</string>
</resources>
diff --git a/packages/Shell/res/values-km-rKH/strings.xml b/packages/Shell/res/values-km-rKH/strings.xml
index efb345c..04e3170 100644
--- a/packages/Shell/res/values-km-rKH/strings.xml
+++ b/packages/Shell/res/values-km-rKH/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"សែល"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"បានចាប់យករបាយការណ៍កំហុស"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"ប៉ះ ដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នក"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"អូសទៅឆ្វេង ដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នក"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"ប៉ះ ដើម្បីចែករំលែករបាយការណ៍កំហុសរបស់អ្នក"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"របាយការណ៍កំហុសរួមមានឯកសារកំណត់ហេតុផ្សេងៗរបស់ប្រព័ន្ធ រួមមានព័ត៌មានផ្ទាល់ខ្លួន និងឯកជន។ ចែករំលែករបាយការណ៍កំហុសជាមួយកម្មវិធី និងមនុស្សដែលអ្នកទុកចិត្ត។"</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"បង្ហាញសារនេះពេលក្រោយ"</string>
</resources>
diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml
index d22a8b0..d415d93 100644
--- a/packages/Shell/res/values-ko/strings.xml
+++ b/packages/Shell/res/values-ko/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"셸"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"버그 신고서 캡처됨"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"버그 신고서를 공유하려면 터치하세요."</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"버그 신고서를 공유하려면 터치하세요."</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"버그 신고서는 시스템의 다양한 로그 파일 데이터(예: 개인 및 비공개 정보)를 포함합니다. 신뢰할 수 있는 앱과 사용자에게만 버그 신고서를 공유합니다."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"다음에 이 메시지 표시"</string>
</resources>
diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml
index a237d48..b2724ad 100644
--- a/packages/Shell/res/values-lo-rLA/strings.xml
+++ b/packages/Shell/res/values-lo-rLA/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"ລາຍງານຈຸດບົກພ່ອງຖືກເກັບກຳແລ້ວ"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"ແຕະເພື່ອສົ່ງການລາຍງານປັນຫາຂອງທ່ານ"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"ປັດໄປຊ້າຍເພື່ອສົ່ງລາຍງານຂໍ້ຜິດພາດຂອງທ່ານ"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"ແຕະເພື່ອສົ່ງການລາຍງານປັນຫາຂອງທ່ານ"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"ການລາຍງານຂໍ້ຜິດພາດປະກອບມີ ຂໍ້ມູນຈາກໄຟລ໌ບັນທຶກຂອງລະບົບຫຼາຍໄຟລ໌, ຮວມທັງຂໍ້ມູນສ່ວນໂຕນຳ. ທ່ານຕ້ອງແບ່ງປັນລາຍງານຂໍ້ຜິດພາດໃຫ້ແອັບຯ ແລະຄົນທີ່ທ່ານເຊື່ອຖືໄດ້ເທົ່ານັ້ນ."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"ສະແດງຂໍ້ຄວາມນີ້ອີກໃນເທື່ອຕໍ່ໄປ"</string>
</resources>
diff --git a/packages/Shell/res/values-lt/strings.xml b/packages/Shell/res/values-lt/strings.xml
index 3ac4820..914ef46 100644
--- a/packages/Shell/res/values-lt/strings.xml
+++ b/packages/Shell/res/values-lt/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Apvalkalas"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Trikčių ataskaita užfiksuota"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Palieskite, kad bendrintumėte trikčių ataskaitą"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Perbraukite kairėn, kad bendrintumėte trikties ataskaitą"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Palieskite, kad bendrintumėte trikčių ataskaitą"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Trikčių ataskaitose pateikiami duomenys iš įvairių sistemos žurnalo failų, įskaitant asmeninę ir privačią informaciją. Trikčių ataskaitas bendrinkite tik su patikimomis programomis ir žmonėmis."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rodyti šį pranešimą kitą kartą"</string>
</resources>
diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml
index 3f7f7c1..1a75b32 100644
--- a/packages/Shell/res/values-lv/strings.xml
+++ b/packages/Shell/res/values-lv/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Aizsargs"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Izveidots kļūdu pārskats"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Pieskarieties, lai kopīgotu kļūdu pārskatu."</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Pieskarieties, lai kopīgotu kļūdu pārskatu."</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Kļūdu pārskatā ir iekļauti dati no dažādiem sistēmas žurnālfailiem, tostarp personas dati un privāta informācija. Kļūdu pārskatus ieteicams kopīgot tikai ar uzticamām lietotnēm un lietotājiem."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Rādīt šo ziņojumu nākamajā reizē"</string>
</resources>
diff --git a/packages/Shell/res/values-mn-rMN/strings.xml b/packages/Shell/res/values-mn-rMN/strings.xml
index f74298d..4637f2d 100644
--- a/packages/Shell/res/values-mn-rMN/strings.xml
+++ b/packages/Shell/res/values-mn-rMN/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Шел"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Алдааны мэдээлэл хүлээн авав"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Та алдааны мэдэгдлийг хуваалцах бол хүрнэ үү"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Өөрийн согог репортыг хуваалцахын тулд зүүн шудрана уу"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Та алдааны мэдэгдлийг хуваалцах бол хүрнэ үү"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Алдааны репорт нь хувийн болон нууц мэдээлэл зэргийг агуулсан системийн төрөл бүрийн лог файлын датаг агуулна. Алдааны репортыг зөвхөн итгэлтэй апп болон хүмүүст хуваалцана уу."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Энэ мессежийг дараагийн удаа харуулах"</string>
</resources>
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index 8d1e4a2..cbb4190 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Laporan pepijat telah ditangkap"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Sentuh untuk berkongsi laporan pepijat anda"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Sentuh untuk berkongsi laporan pepijat anda"</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>
</resources>
diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml
index 96d53a6..43e776c 100644
--- a/packages/Shell/res/values-nb/strings.xml
+++ b/packages/Shell/res/values-nb/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Kommandoliste"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Feilrapporten er lagret"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Trykk for å dele feilrapporten din"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Trykk for å dele feilrapporten din"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Feilrapporter inkluderer data fra systemets forskjellige loggfiler. Dette omfatter personlig og privat informasjon. Du bør bare dele feilrapporter ned apper og folk du stoler på."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Vis denne meldingen neste gang"</string>
</resources>
diff --git a/packages/Shell/res/values-nl/strings.xml b/packages/Shell/res/values-nl/strings.xml
index 5c32c73..51ae329 100644
--- a/packages/Shell/res/values-nl/strings.xml
+++ b/packages/Shell/res/values-nl/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Foutenrapport vastgelegd"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Raak aan om uw foutenrapport te delen"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Veeg naar links om uw bugmelding te delen"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Raak aan om uw foutenrapport te delen"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Foutenrapporten bevatten gegevens uit de verschillende logbestanden van het systeem, waaronder persoonlijke en privégegevens. Deel foutenrapporten alleen met apps en mensen die u vertrouwt."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Dit bericht de volgende keer weergeven"</string>
</resources>
diff --git a/packages/Shell/res/values-pl/strings.xml b/packages/Shell/res/values-pl/strings.xml
index 2e28f8d..2c810d6 100644
--- a/packages/Shell/res/values-pl/strings.xml
+++ b/packages/Shell/res/values-pl/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Powłoka"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Raport o błędach został zapisany"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Kliknij, by udostępnić raport o błędach"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Przesuń palcem w lewo, by udostępnić swoje zgłoszenie błędu"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Kliknij, by udostępnić raport o błędach"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Raporty o błędach zawierają dane z różnych plików dzienników systemu, w tym dane osobowe i prywatne. Udostępniaj je tylko aplikacjom i osobom, którym ufasz."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaż ten komunikat następnym razem"</string>
</resources>
diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml
index 1c465e0..4f55b24 100644
--- a/packages/Shell/res/values-pt-rPT/strings.xml
+++ b/packages/Shell/res/values-pt-rPT/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Relatório de erros capturado"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Toque para partilhar o relatório de erros"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toque para partilhar o relatório de erros"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de erros incluem dados de vários ficheiros de registo do sistema, nomeadamente informações pessoais e privadas. Partilhe relatórios de erros apenas com aplicações e pessoas fidedignas."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
</resources>
diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml
index 20f4cc9..8080ee4 100644
--- a/packages/Shell/res/values-pt/strings.xml
+++ b/packages/Shell/res/values-pt/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Relatório de bugs capturado"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Toque para compartilhar seu relatório de bugs"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Toque para compartilhar seu relatório de bugs"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Os relatórios de bugs contêm dados de diversos arquivos de registro do sistema, inclusive informações pessoais e particulares. Compartilhe relatórios de bugs somente com aplicativos e pessoas nos quais você confia."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Mostrar esta mensagem da próxima vez"</string>
</resources>
diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml
index 45c2b0a..5c4862d 100644
--- a/packages/Shell/res/values-ro/strings.xml
+++ b/packages/Shell/res/values-ro/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Raportul despre erori a fost creat"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Atingeți pentru a permite accesul la raportul despre erori"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Atingeți pentru a permite accesul la raportul despre erori"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Rapoartele despre erori conțin date din diferite fișiere de jurnal ale sistemului, inclusiv informații private și personale. Permiteți accesul la rapoartele despre erori numai aplicațiilor și persoanelor în care aveți încredere."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afișați acest mesaj data viitoare"</string>
</resources>
diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml
index 153e972..c117f54 100644
--- a/packages/Shell/res/values-ru/strings.xml
+++ b/packages/Shell/res/values-ru/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Оболочка"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Отчет об ошибках сохранен"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Нажмите, чтобы отправить отчет об ошибках"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Нажмите, чтобы отправить отчет об ошибках"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Отчеты об ошибках содержат данные различных системных журналов и могут включать личную информацию. Рекомендуем открывать к ним доступ только лицам и приложениям, заслуживающим доверие."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показать это сообщение в следующий раз"</string>
</resources>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 59c3ccf..341fb8b 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Prostredie"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Hlásenie o chybách bolo vytvorené"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Hlásenie o chybách môžete zdielať klepnutím"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Hlásenie o chybách môžete zdielať klepnutím"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Správy o chybách obsahujú údaje z rôznych súborov denníkov systému vrátane osobných a súkromných informácií. Zdieľajte ich iba s dôveryhodnými aplikáciami a ľuďmi."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobraziť túto správu nabudúce"</string>
</resources>
diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml
index 8522d1b..1265b3a 100644
--- a/packages/Shell/res/values-sl/strings.xml
+++ b/packages/Shell/res/values-sl/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Lupina"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Poročilo o napaki je posneto"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Dotaknite se, če želite deliti sporočilo o napaki z drugimi"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Dotaknite se, če želite deliti sporočilo o napaki z drugimi"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Poročila o napakah vsebujejo podatke iz različnih dnevniških datotek sistema, vključno z osebnimi in zasebnimi podatki. Poročila o napakah delite samo z aplikacijami in ljudmi, ki jim zaupate."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Pokaži to sporočilo naslednjič"</string>
</resources>
diff --git a/packages/Shell/res/values-sr/strings.xml b/packages/Shell/res/values-sr/strings.xml
index bef6ff4..ca8ae18 100644
--- a/packages/Shell/res/values-sr/strings.xml
+++ b/packages/Shell/res/values-sr/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Извештај о грешци је снимљен"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Додирните да бисте делили извештај о грешци"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Додирните да бисте делили извештај о грешци"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Извештаји о грешкама садрже податке из различитих системских датотека евиденције, укључујући личне и приватне податке. Делите извештаје о грешкама само са апликацијама и људима у које имате поверења."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Прикажи ову поруку следећи пут"</string>
</resources>
diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml
index 055dc41..67de765 100644
--- a/packages/Shell/res/values-sv/strings.xml
+++ b/packages/Shell/res/values-sv/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Skal"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Felrapporten har skapats"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Tryck om du vill dela felrapporten"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Tryck om du vill dela felrapporten"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Felrapporter innehåller data från systemets olika loggfiler, inklusive personliga och privata uppgifter. Dela bara felrapporter med personer du litar på."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Visa det här meddelandet nästa gång"</string>
</resources>
diff --git a/packages/Shell/res/values-sw/strings.xml b/packages/Shell/res/values-sw/strings.xml
index b1d4407..cb2c00c 100644
--- a/packages/Shell/res/values-sw/strings.xml
+++ b/packages/Shell/res/values-sw/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Ganda"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Ripoti ya hitilafu imenaswa"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Gusa ili ushiriki ripoti yako ya hitilafu"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Gusa ili ushiriki ripoti yako ya hitilafu"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Ripoti ya hitilafu ina data kutoka kwenye faili za kumbukumbu mbalimbali za mfumo, pamoja na maelezo ya kibinafsi na faragha. Shiriki ripoti ya hitilafu na programu na watu unaowaamini pekee."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Onyesha ujumbe huu wakati mwingine"</string>
</resources>
diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml
index b484a42..e9f8efe 100644
--- a/packages/Shell/res/values-th/strings.xml
+++ b/packages/Shell/res/values-th/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"จับภาพรายงานข้อบกพร่องแล้ว"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณ"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"แตะเพื่อแชร์รายงานข้อบกพร่องของคุณ"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"รายงานข้อบกพร่องมีข้อมูลจากไฟล์บันทึกต่างๆ ของระบบ รวมถึงข้อมูลส่วนตัว แชร์รายงานข้อบกพร่องกับแอปและบุคคลที่คุณไว้ใจเท่านั้น"</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"แสดงข้อความนี้ในครั้งต่อไป"</string>
</resources>
diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml
index 20d1b09..c5f18975 100644
--- a/packages/Shell/res/values-tl/strings.xml
+++ b/packages/Shell/res/values-tl/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Na-capture ang ulat ng bug"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Pindutin upang ibahagi ang iyong ulat ng bug"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Pindutin upang ibahagi ang iyong ulat ng bug"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Naglalaman ang mga ulat ng bug ng data mula sa iba\'t ibang file ng log ng system, kabilang ang personal at pribadong impormasyon. Magbahagi lang ng mga ulat ng bug sa apps at mga tao na pinagkakatiwalaan mo."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Ipakita ang mensaheng ito sa susunod"</string>
</resources>
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index 56db3fc..c3c0395 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Kabuk"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Hata raporu kaydedildi"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Hata raporunuzu paylaşmak için dokunun"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Hata raporunuzu paylaşmak için dokunun"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Hata raporları, kişisel ve özel bilgiler dahil olmak üzere sistemin çeşitli günlük dosyalarından veriler içerir. Hata raporlarını sadece güvendiğiniz uygulamalar ve kişilerle paylaşın."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bir dahaki sefere bu mesajı göster"</string>
</resources>
diff --git a/packages/Shell/res/values-uk/strings.xml b/packages/Shell/res/values-uk/strings.xml
index 68e68a8..f9f5bb3 100644
--- a/packages/Shell/res/values-uk/strings.xml
+++ b/packages/Shell/res/values-uk/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Оболонка"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Звіт про помилки створено"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Торкніться, щоб надіслати звіт про помилки"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Проведіть пальцем ліворуч, щоб надіслати звіт про помилки"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Торкніться, щоб надіслати звіт про помилки"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Звіти про помилки містять дані з різних файлів журналу системи, зокрема особисті та конфіденційні. Надсилайте звіт про помилки лише тим, кому довіряєте."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Показати це повідомлення наступного разу"</string>
</resources>
diff --git a/packages/Shell/res/values-vi/strings.xml b/packages/Shell/res/values-vi/strings.xml
index ca4fcaa..4c227c7 100644
--- a/packages/Shell/res/values-vi/strings.xml
+++ b/packages/Shell/res/values-vi/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Báo cáo lỗi đã được chụp"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Chạm để chia sẻ báo cáo lỗi của bạn"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Chạm để chia sẻ báo cáo lỗi của bạn"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Các báo cáo lỗi chứa dữ liệu từ nhiều tệp nhật ký khác nhau của hệ thống, bao gồm cả thông tin cá nhân và riêng tư. Chỉ chia sẻ báo cáo lỗi với các ứng dụng và những người mà bạn tin tưởng."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Hiển thị thông báo này vào lần tới"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml
index f1c385f..3485b4c 100644
--- a/packages/Shell/res/values-zh-rCN/strings.xml
+++ b/packages/Shell/res/values-zh-rCN/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"已抓取错误报告"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"触摸即可分享您的错误报告"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"触摸即可分享您的错误报告"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"错误报告包含的数据来自于系统的各个日志文件,其中包含个人信息和隐私信息。请务必只与您信任的应用和用户分享错误报告。"</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再显示这条讯息"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml
index b5f1935..1ab09a3 100644
--- a/packages/Shell/res/values-zh-rHK/strings.xml
+++ b/packages/Shell/res/values-zh-rHK/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"命令介面"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"已擷取錯誤報告"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"輕觸即可分享您的錯誤報告"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"輕觸即可分享您的錯誤報告"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告中有來自系統各個記錄檔案的資料,包括個人和私人資料。請只與您信任的應用程式和用戶分享錯誤報告。"</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次再顯示這則訊息"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml
index d3d3140..d0f7faa 100644
--- a/packages/Shell/res/values-zh-rTW/strings.xml
+++ b/packages/Shell/res/values-zh-rTW/strings.xml
@@ -18,7 +18,9 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"殼層"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"已擷取錯誤報告"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"輕觸即可分享您的錯誤報告"</string>
+ <!-- no translation found for bugreport_finished_text (8389172248433597683) -->
+ <skip />
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"輕觸即可分享您的錯誤報告"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"錯誤報告的資料來自系統各個紀錄檔,包括個人和私密資訊。請務必只與您信任的應用程式和使用者分享錯誤報告。"</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"下次仍顯示這則訊息"</string>
</resources>
diff --git a/packages/Shell/res/values-zu/strings.xml b/packages/Shell/res/values-zu/strings.xml
index e524b80..38e9595 100644
--- a/packages/Shell/res/values-zu/strings.xml
+++ b/packages/Shell/res/values-zu/strings.xml
@@ -18,7 +18,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"I-Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Umbiko wesiphazamisi uthwetshuliwe"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Thinta ukuze wabelane ngombiko wakho wesiphazamisi"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="8389172248433597683">"Swayiphela kwesokunxele ukuze wabelane umbiko wesiphazamiso sakho"</string>
+ <string name="bugreport_finished_text" product="default" msgid="3559904746859400732">"Thinta ukuze wabelane ngombiko wakho wesiphazamisi"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Imibiko yeziphazamisi iqukethe idatha yamafayela wokungena ahlukile wesistimu, afaka ulwazi lomuntu siqu noma lobumfihlo. Yabelana kuphela ngemibiko yeziphazamisi nezinhlelo zokusebenza nabantu obathembayo."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Bonisa lo mlayezo ngesikhathi esilandelayo"</string>
</resources>
diff --git a/packages/Shell/res/values/strings.xml b/packages/Shell/res/values/strings.xml
index e5606c7..51e2c95 100644
--- a/packages/Shell/res/values/strings.xml
+++ b/packages/Shell/res/values/strings.xml
@@ -19,8 +19,12 @@
<!-- Title of notification indicating a bugreport has been successfully captured. [CHAR LIMIT=50] -->
<string name="bugreport_finished_title">Bug report captured</string>
+
+ <!-- Text of notification indicating that swipe left will share the captured bugreport. [CHAR LIMIT=100] -->
+ <string name="bugreport_finished_text" product="watch">Swipe left to share your bug report</string>
<!-- Text of notification indicating that touching will share the captured bugreport. [CHAR LIMIT=100] -->
- <string name="bugreport_finished_text">Touch to share your bug report</string>
+ <string name="bugreport_finished_text" product="default">Touch to share your bug report</string>
+
<!-- Body of dialog informing user about contents of a bugreport. [CHAR LIMIT=NONE] -->
<string name="bugreport_confirm">Bug reports contain data from the system\'s various log files, including personal and private information. Only share bug reports with apps and people you trust.</string>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_01.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_01.xml
deleted file mode 100644
index a6c2cf8..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_01.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M10.25,1.75c-0.6,-0.6 -1.5,-0.6 -2.1,0.0l-6.4,6.4c-0.6,0.6 -0.6,1.5 0.0,2.1l12.0,12.0c0.6,0.6 1.5,0.6 2.1,0.0l6.4,-6.4c0.6,-0.6 0.6,-1.5 0.0,-2.1L10.25,1.75zM14.85,21.25l-12.0,-12.0l6.4,-6.4l12.0,12.0L14.85,21.25z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M16.55,2.5c3.3,1.5 5.6,4.7 6.0,8.5l1.5,0.0c-0.6,-6.2 -5.7,-11.0 -12.0,-11.0c-0.2,0.0 -0.4,0.0 -0.7,0.0l3.8,3.8L16.55,2.5z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M7.55,21.5c-3.3,-1.5 -5.6,-4.7 -6.0,-8.5l-1.4,0.0c0.5,6.2 5.6,11.0 11.9,11.0c0.2,0.0 0.4,0.0 0.7,0.0l-3.8,-3.8L7.55,21.5z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_02.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_02.xml
deleted file mode 100644
index 4107c46..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_02.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M10.24,2.43C9.67,1.88 8.83,1.88 8.28,2.45L2.34,8.48c-0.56,0.57 -0.55,1.41 0.02,1.96l11.3,11.13c0.57,0.56 1.41,0.55 1.96,-0.02l5.93,-6.03c0.56,-0.57 0.55,-1.41 -0.02,-1.96L10.24,2.43zM14.68,20.62L3.38,9.5l5.93,-6.03l11.3,11.13L14.68,20.62z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M16.91,2.71c3.23,1.64 5.39,4.94 5.62,8.76l1.5,0.07c-0.33,-6.22 -5.21,-11.24 -11.5,-11.52c-0.2,-0.01 -0.4,-0.02 -0.7,-0.03l3.63,3.96L16.91,2.71z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M7.09,21.29c-3.23,-1.64 -5.39,-4.94 -5.62,-8.76l-1.4,-0.06c0.23,6.22 5.11,11.24 11.4,11.51c0.2,0.01 0.4,0.02 0.7,0.03l-3.63,-3.96L7.09,21.29z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_03.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_03.xml
deleted file mode 100644
index 127296c4..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_03.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M11.07,4.12c-0.43,-0.49 -1.11,-0.53 -1.6,-0.1L4.3,8.57C3.81,9.0 3.77,9.68 4.19,10.17l8.54,9.71c0.43,0.49 1.11,0.53 1.6,0.1l5.18,-4.55c0.49,-0.43 0.53,-1.11 0.1,-1.6L11.07,4.12zM13.61,19.17L5.08,9.46l5.18,-4.55l8.54,9.71L13.61,19.17z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M17.72,3.2c3.06,1.94 4.9,5.43 4.77,9.25l1.49,0.21C24.23,6.43 19.84,0.97 13.6,0.11c-0.2,-0.03 -0.4,-0.06 -0.69,-0.1l3.24,4.29L17.72,3.2z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M6.19,20.78c-3.06,-1.94 -4.9,-5.43 -4.77,-9.25l-1.39,-0.19c-0.36,6.21 4.03,11.67 10.27,12.53c0.2,0.03 0.4,0.06 0.69,0.1l-3.24,-4.29L6.19,20.78z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_04.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_04.xml
deleted file mode 100644
index d00262ab..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_04.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M11.88,5.72c-0.3,-0.42 -0.83,-0.51 -1.25,-0.21L6.19,8.69c-0.42,0.3 -0.51,0.83 -0.21,1.25l5.95,8.34c0.3,0.42 0.83,0.51 1.25,0.21l4.45,-3.17c0.42,-0.3 0.51,-0.83 0.21,-1.25L11.88,5.72zM12.68,17.79L6.73,9.45l4.45,-3.17l5.95,8.34L12.68,17.79z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M18.8,4.01c2.79,2.32 4.16,6.01 3.54,9.78l1.45,0.4c1.06,-6.14 -2.59,-12.11 -8.67,-13.78c-0.19,-0.05 -0.39,-0.11 -0.68,-0.18l2.66,4.67L18.8,4.01z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M5.11,19.96c-2.79,-2.32 -4.16,-6.01 -3.54,-9.78L0.21,9.81c-1.15,6.11 2.5,12.09 8.57,13.75c0.19,0.05 0.39,0.11 0.68,0.18L6.8,19.08L5.11,19.96z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_05.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_05.xml
deleted file mode 100644
index 570f51f..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_05.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M15.41,8.14c0.05,-0.42 -0.23,-0.78 -0.65,-0.83l-4.5,-0.54C9.84,6.72 9.48,7.0 9.43,7.42l-1.01,8.44c-0.05,0.42 0.23,0.78 0.65,0.83l4.5,0.54C14.0,17.28 14.35,17.0 14.4,16.58L15.41,8.14zM9.16,15.99l1.01,-8.44l4.5,0.54l-1.01,8.44L9.16,15.99z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M22.35,10.28c0.64,3.57 -0.69,7.28 -3.59,9.77l0.85,1.23c4.76,-4.01 5.82,-10.94 2.24,-16.12c-0.11,-0.16 -0.23,-0.33 -0.4,-0.58l-0.97,5.29L22.35,10.28z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M1.6,13.66c-0.64,-3.57 0.69,-7.28 3.59,-9.77L4.4,2.74c-4.82,3.93 -5.88,10.86 -2.3,16.04c0.11,0.16 0.23,0.33 0.4,0.58l0.97,-5.29L1.6,13.66z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_06.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_06.xml
deleted file mode 100644
index aaf9356..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_06.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M15.62,13.08c0.29,-0.1 0.44,-0.39 0.34,-0.69L14.9,9.27c-0.1,-0.29 -0.39,-0.44 -0.69,-0.34l-5.86,1.98c-0.29,0.1 -0.44,0.39 -0.34,0.69l1.06,3.12c0.1,0.29 0.39,0.44 0.69,0.34L15.62,13.08zM8.51,11.44l5.86,-1.98l1.06,3.12l-5.86,1.98L8.51,11.44z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M18.53,20.21c-2.8,2.3 -6.69,2.95 -10.27,1.64L7.6,23.2c5.83,2.2 12.39,-0.26 15.16,-5.92c0.09,-0.18 0.18,-0.36 0.31,-0.63l-5.09,1.73L18.53,20.21z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M5.45,3.76c2.8,-2.3 6.69,-2.95 10.27,-1.64l0.62,-1.26C10.56,-1.42 4.0,1.04 1.22,6.69C1.13,6.87 1.05,7.05 0.91,7.32L6.0,5.59L5.45,3.76z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_07.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_07.xml
deleted file mode 100644
index 330ce6a..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_07.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M12.23,14.48c0.13,0.16 0.35,0.17 0.5,0.04l1.66,-1.4c0.16,-0.13 0.17,-0.35 0.04,-0.5l-2.62,-3.11c-0.13,-0.16 -0.35,-0.17 -0.5,-0.04l-1.66,1.4c-0.16,0.13 -0.17,0.35 -0.04,0.5L12.23,14.48zM11.53,9.73l2.62,3.11l-1.66,1.4l-2.62,-3.11L11.53,9.73z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M6.04,20.63c-3.01,-2.02 -4.75,-5.56 -4.52,-9.37l-1.48,-0.25c-0.43,6.21 3.81,11.79 10.02,12.83c0.2,0.03 0.39,0.07 0.69,0.12l-3.12,-4.37L6.04,20.63z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M18.04,3.37c3.01,2.02 4.75,5.56 4.52,9.37l1.38,0.23c0.53,-6.2 -3.71,-11.77 -9.93,-12.81c-0.2,-0.03 -0.39,-0.07 -0.69,-0.12l3.12,4.37L18.04,3.37z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_08.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_08.xml
deleted file mode 100644
index 1c7f1a1..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_08.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M10.55,12.73c-0.06,0.12 -0.02,0.25 0.1,0.32l1.26,0.68c0.12,0.06 0.25,0.02 0.32,-0.1l1.27,-2.36c0.06,-0.12 0.02,-0.25 -0.1,-0.32l-1.26,-0.68c-0.12,-0.06 -0.25,-0.02 -0.32,0.1L10.55,12.73zM13.29,11.15l-1.27,2.36l-1.26,-0.68l1.27,-2.36L13.29,11.15z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M1.55,12.95C1.18,9.34 2.78,5.74 5.86,3.47L5.1,2.18C0.05,5.83 -1.51,12.66 1.67,18.09c0.1,0.17 0.2,0.35 0.35,0.6l1.36,-5.2L1.55,12.95z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M22.5,11.12c0.37,3.61 -1.23,7.21 -4.31,9.47l0.71,1.21c5.1,-3.56 6.67,-10.39 3.48,-15.83c-0.1,-0.17 -0.2,-0.35 -0.35,-0.6l-1.36,5.2L22.5,11.12z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_09.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_09.xml
deleted file mode 100644
index ebfbad6..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_09.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:pathData="M11.45,12c0,0.14,0.12,0.25,0.25,0.25l0.06,0l0,-0.5l-0.06,0C11.57,11.75,11.45,11.86,11.45,12z"
- android:fill="#00000000"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M11.77,11.62l-0.06,0.0c-0.21,0.0 -0.37,0.17 -0.38,0.37c0.0,0.21 0.17,0.37 0.37,0.37l0.06,0.0c0.0,0.07 0.06,0.12 0.12,0.13l0.62,0.0c0.07,0.0 0.12,-0.06 0.13,-0.12l0.0,-0.75c0.0,-0.07 -0.06,-0.12 -0.12,-0.13l-0.62,0.0C11.83,11.5 11.77,11.56 11.77,11.62zM12.33,12.0c0.0,0.07 -0.06,0.12 -0.13,0.12c-0.07,0.0 -0.12,-0.06 -0.12,-0.13c0.0,-0.07 0.06,-0.12 0.13,-0.12C12.28,11.88 12.33,11.93 12.33,12.0zM11.77,11.75l0.0,0.5l-0.06,0.0c-0.14,0.0 -0.26,-0.11 -0.25,-0.25c0.0,-0.14 0.12,-0.25 0.26,-0.25L11.77,11.75z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M3.83,5.44c2.21,-2.87 5.85,-4.38 9.64,-3.9l0.34,-1.46C7.64,-0.75 1.81,3.12 0.37,9.25C0.32,9.45 0.28,9.64 0.21,9.93L4.78,7.1L3.83,5.44zM20.28,18.53c-2.21,2.87 -5.85,4.38 -9.64,3.9l-0.32,1.36c6.15,0.93 11.99,-2.95 13.42,-9.08c0.05,-0.19 0.09,-0.39 0.16,-0.68l-4.57,2.83L20.28,18.53z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_10.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_10.xml
deleted file mode 100644
index 21dda8c..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_10.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:pathData="M10.42,9.96c-0.42,0.42,-0.39,1.12,0.03,1.54l0.19,0.19l1.51,-1.53l-0.19,-0.19 C11.54,9.55,10.84,9.54,10.42,9.96z"
- android:fill="#00000000"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M12.53,9.78l-0.19,-0.19c-0.63,-0.63 -1.66,-0.62 -2.28,0.02c-0.63,0.63 -0.62,1.66 0.02,2.28l0.19,0.19c-0.21,0.21 -0.21,0.55 0.01,0.76l1.92,1.89c0.21,0.21 0.55,0.21 0.76,-0.01l2.27,-2.3c0.21,-0.21 0.21,-0.55 -0.01,-0.76l-1.92,-1.89C13.08,9.56 12.74,9.56 12.53,9.78zM13.12,12.62c-0.21,0.21 -0.55,0.21 -0.76,0.01c-0.21,-0.21 -0.21,-0.55 -0.01,-0.76c0.21,-0.21 0.55,-0.21 0.76,-0.01C13.33,12.07 13.33,12.41 13.12,12.62zM12.15,10.16l-1.51,1.53l-0.19,-0.19c-0.42,-0.42 -0.45,-1.12 -0.03,-1.54c0.42,-0.42 1.12,-0.41 1.54,0.01L12.15,10.16z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M7.82,2.36c3.3,-1.49 7.23,-1.12 10.35,1.09l0.99,-1.13C14.09,-1.32 7.12,-0.64 2.97,4.1C2.84,4.25 2.71,4.4 2.51,4.62l5.36,-0.36L7.82,2.36zM16.18,21.64c-3.3,1.49 -7.23,1.12 -10.35,-1.09l-0.92,1.05c4.99,3.71 11.97,3.03 16.12,-1.71c0.13,-0.15 0.26,-0.3 0.46,-0.53l-5.36,0.36L16.18,21.64z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_11.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_11.xml
deleted file mode 100644
index f4186fe..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_11.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:pathData="M10.53,8.85c-0.7,0.37,-0.95,1.28,-0.58,1.98l0.17,0.32l2.55,-1.36L12.5,9.48 C12.12,8.78,11.23,8.48,10.53,8.85z"
- android:fill="#00000000"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M13.3,9.46l-0.17,-0.32c-0.56,-1.05 -1.87,-1.45 -2.93,-0.89s-1.45,1.87 -0.89,2.93l0.17,0.32c-0.35,0.19 -0.48,0.62 -0.3,0.98l1.7,3.18c0.19,0.35 0.62,0.48 0.98,0.3l3.82,-2.04c0.35,-0.19 0.48,-0.62 0.3,-0.98l-1.7,-3.18C14.09,9.4 13.65,9.27 13.3,9.46zM12.92,13.34c-0.35,0.19 -0.79,0.06 -0.98,-0.3c-0.19,-0.35 -0.05,-0.79 0.3,-0.98c0.35,-0.19 0.79,-0.05 0.98,0.3C13.41,12.72 13.27,13.15 12.92,13.34zM12.67,9.8l-2.55,1.36l-0.17,-0.32c-0.37,-0.7 -0.13,-1.61 0.58,-1.98c0.7,-0.37 1.59,-0.08 1.97,0.63L12.67,9.8z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M11.48,1.5c3.62,-0.23 7.16,1.5 9.3,4.66l1.32,-0.71C18.65,0.27 11.89,-1.55 6.34,1.42C6.16,1.51 5.98,1.61 5.72,1.75l5.14,1.56L11.48,1.5zM12.52,22.5c-3.62,0.23 -7.16,-1.5 -9.3,-4.66L1.98,18.5c3.37,5.23 10.13,7.06 15.68,4.08c0.18,-0.09 0.35,-0.19 0.62,-0.33l-5.14,-1.56L12.52,22.5z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_12.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_12.xml
deleted file mode 100644
index d408e28..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_12.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:pathData="M10.83,8.49c-0.91,0.3,-1.39,1.31,-1.09,2.22l0.13,0.41l3.28,-1.08l-0.13,-0.41 C12.72,8.72,11.73,8.19,10.83,8.49z"
- android:fill="#00000000"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M13.98,9.77l-0.13,-0.41C13.4,8.0 11.93,7.26 10.57,7.71c-1.36,0.45 -2.1,1.91 -1.65,3.27l0.13,0.41c-0.45,0.15 -0.7,0.64 -0.55,1.09l1.35,4.1c0.15,0.45 0.64,0.7 1.09,0.55l4.92,-1.62c0.45,-0.15 0.7,-0.64 0.55,-1.09l-1.35,-4.1C14.92,9.87 14.43,9.62 13.98,9.77zM12.73,14.27c-0.45,0.15 -0.94,-0.1 -1.09,-0.55c-0.15,-0.45 0.1,-0.94 0.55,-1.09c0.45,-0.15 0.94,0.1 1.09,0.55C13.43,13.64 13.18,14.12 12.73,14.27zM13.16,10.04l-3.28,1.08l-0.13,-0.41c-0.3,-0.91 0.18,-1.92 1.09,-2.22c0.91,-0.3 1.9,0.24 2.19,1.14L13.16,10.04z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M13.55,1.6c3.59,0.48 6.72,2.87 8.21,6.39l1.44,-0.44C20.82,1.8 14.54,-1.31 8.51,0.52c-0.19,0.06 -0.38,0.12 -0.67,0.2l4.74,2.53L13.55,1.6zM10.45,22.4c-3.59,-0.48 -6.72,-2.87 -8.21,-6.39L0.9,16.41c2.28,5.79 8.55,8.9 14.58,7.07c0.19,-0.06 0.38,-0.12 0.67,-0.2l-4.74,-2.53L10.45,22.4z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_13.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_13.xml
deleted file mode 100644
index 1ac6b39..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_13.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:pathData="M11.17,7.71c-1.09,0.19,-1.8,1.28,-1.61,2.37l0.09,0.49l3.94,-0.7l-0.09,-0.49C13.3,8.3,12.26,7.52,11.17,7.71 z"
- android:fill="#00000000"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M14.57,9.7l-0.09,-0.49C14.19,7.58 12.63,6.49 11.0,6.78c-1.63,0.29 -2.71,1.85 -2.43,3.48l0.08,0.49c-0.54,0.1 -0.91,0.62 -0.81,1.16l0.87,4.92c0.1,0.54 0.62,0.91 1.16,0.81l5.91,-1.05c0.54,-0.1 0.91,-0.61 0.81,-1.16l-0.87,-4.92C15.63,9.97 15.11,9.61 14.57,9.7zM12.4,14.66c-0.54,0.1 -1.06,-0.27 -1.16,-0.81c-0.1,-0.54 0.27,-1.06 0.81,-1.16s1.06,0.27 1.16,0.81C13.3,14.04 12.94,14.56 12.4,14.66zM13.58,9.88l-3.94,0.7l-0.09,-0.49c-0.19,-1.09 0.52,-2.17 1.61,-2.37s2.13,0.58 2.33,1.67L13.58,9.88z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M14.99,1.92c3.49,0.97 6.26,3.78 7.24,7.48l1.48,-0.23c-1.55,-6.03 -7.32,-9.99 -13.55,-9.02c-0.2,0.03 -0.4,0.06 -0.69,0.11l4.34,3.17L14.99,1.92zM9.01,22.08C5.52,21.1 2.76,18.3 1.78,14.6L0.4,14.82c1.45,6.05 7.22,10.01 13.45,9.04c0.2,-0.03 0.4,-0.06 0.69,-0.11l-4.34,-3.17L9.01,22.08z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_14.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_14.xml
deleted file mode 100644
index c43e363c..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_14.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:pathData="M11.72,7.61c-1.1,0.08,-1.93,1.08,-1.86,2.18l0.03,0.5l3.99,-0.27l-0.03,-0.5 C13.78,8.42,12.82,7.54,11.72,7.61z"
- android:fill="#00000000"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M14.88,9.95l-0.03,-0.5c-0.11,-1.65 -1.54,-2.9 -3.2,-2.79C10.0,6.78 8.75,8.21 8.87,9.86l0.03,0.5c-0.55,0.04 -0.97,0.52 -0.93,1.07l0.34,4.99c0.04,0.55 0.52,0.97 1.07,0.93l5.99,-0.41c0.55,-0.04 0.97,-0.51 0.93,-1.07l-0.34,-4.99C15.91,10.33 15.43,9.91 14.88,9.95zM12.2,14.64c-0.55,0.04 -1.03,-0.38 -1.07,-0.93c-0.04,-0.55 0.38,-1.03 0.93,-1.07c0.55,-0.04 1.03,0.38 1.07,0.93C13.16,14.13 12.75,14.61 12.2,14.64zM13.88,10.02l-3.99,0.27l-0.03,-0.5c-0.08,-1.1 0.75,-2.11 1.86,-2.18c1.1,-0.08 2.06,0.81 2.13,1.91L13.88,10.02z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M15.71,2.17c3.41,1.23 5.96,4.23 6.67,7.98l1.5,-0.12c-1.1,-6.13 -6.58,-10.5 -12.86,-9.99c-0.2,0.02 -0.4,0.03 -0.7,0.06l4.1,3.48L15.71,2.17zM8.29,21.83c-3.41,-1.23 -5.96,-4.23 -6.67,-7.98l-1.4,0.11c1.0,6.14 6.48,10.51 12.76,9.99c0.2,-0.02 0.4,-0.03 0.7,-0.06l-4.1,-3.48L8.29,21.83z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_15.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_15.xml
deleted file mode 100644
index 22fa428..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_15.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!--
-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" >
- <size
- android:width="64dp"
- android:height="64dp"/>
-
- <viewport
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"/>
-
- <path
- android:pathData="M12.05,7.7c-1.1,0,-2,0.94,-2,2.05v0.5h4v-0.5C14.05,8.65,13.15,7.7,12.05,7.7z"
- android:fill="#00000000"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M15.05,10.25l0.0,-0.5c0.0,-1.66 -1.34,-3.0 -3.0,-3.0s-2.99,1.34 -2.99,3.0l-0.01,0.5c-0.55,0.0 -1.0,0.45 -1.0,1.0l0.0,5.0c0.0,0.55 0.45,1.0 1.0,1.0l6.0,0.0c0.55,0.0 1.0,-0.45 1.0,-1.0l0.0,-5.0C16.05,10.7 15.6,10.25 15.05,10.25zM12.05,14.75c-0.55,0.0 -1.0,-0.45 -1.0,-1.0c0.0,-0.55 0.45,-1.0 1.0,-1.0s1.0,0.45 1.0,1.0C13.05,14.3 12.6,14.75 12.05,14.75zM14.05,10.25l-4.0,0.0l0.0,-0.5c0.0,-1.1 0.9,-2.05 2.0,-2.05s2.0,0.94 2.0,2.05L14.05,10.25z"/>
- <path
- android:fill="#FFFFFFFF"
- android:pathData="M16.5,2.5c3.3,1.5 5.6,4.7 6.0,8.5L24.0,11.0C23.4,4.8 18.3,0.0 12.0,0.0c-0.2,0.0 -0.4,0.0 -0.7,0.0l3.8,3.8L16.5,2.5zM7.5,21.5c-3.3,-1.5 -5.6,-4.7 -6.0,-8.5L0.1,13.0C0.6,19.2 5.7,24.0 12.0,24.0c0.2,0.0 0.4,0.0 0.7,0.0l-3.8,-3.8L7.5,21.5z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml
new file mode 100644
index 0000000..e4c7cb5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_rotation_landscape.xml
@@ -0,0 +1,28 @@
+<!--
+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" >
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0"/>
+
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M2.0,14.0l0.0,20.0c0.0,2.2 1.8,4.0 4.0,4.0l36.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L46.0,14.0c0.0,-2.2 -1.8,-4.0 -4.0,-4.0L6.0,10.0C3.8,10.0 2.0,11.8 2.0,14.0zM38.0,14.0l0.0,20.0L10.0,34.0L10.0,14.0L38.0,14.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_locked.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_locked.xml
deleted file mode 100644
index 75e20f0..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_locked.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<animation-list
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:oneshot="true">
- <item android:drawable="@drawable/ic_qs_rotation_01" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_02" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_03" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_04" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_05" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_06" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_07" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_08" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_09" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_10" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_11" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_12" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_13" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_14" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_15" android:duration="16" />
-</animation-list>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml
new file mode 100644
index 0000000..e4bf367
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_qs_rotation_portrait.xml
@@ -0,0 +1,28 @@
+<!--
+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" >
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0"/>
+
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M34.0,2.0L14.0,2.0c-2.2,0.0 -4.0,1.8 -4.0,4.0l0.0,36.0c0.0,2.2 1.8,4.0 4.0,4.0l20.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L38.0,6.0C38.0,3.8 36.2,2.0 34.0,2.0zM34.0,38.0L14.0,38.0L14.0,10.0l20.0,0.0L34.0,38.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml b/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
index a1cedb9..a6c2cf8 100644
--- a/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_rotation_unlocked.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 The Android Open Source Project
@@ -14,22 +13,22 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<animation-list
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:oneshot="true">
- <item android:drawable="@drawable/ic_qs_rotation_15" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_14" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_13" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_12" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_11" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_10" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_09" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_08" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_07" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_06" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_05" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_04" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_03" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_02" android:duration="16" />
- <item android:drawable="@drawable/ic_qs_rotation_01" android:duration="16" />
-</animation-list>
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"/>
+
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M10.25,1.75c-0.6,-0.6 -1.5,-0.6 -2.1,0.0l-6.4,6.4c-0.6,0.6 -0.6,1.5 0.0,2.1l12.0,12.0c0.6,0.6 1.5,0.6 2.1,0.0l6.4,-6.4c0.6,-0.6 0.6,-1.5 0.0,-2.1L10.25,1.75zM14.85,21.25l-12.0,-12.0l6.4,-6.4l12.0,12.0L14.85,21.25z"/>
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M16.55,2.5c3.3,1.5 5.6,4.7 6.0,8.5l1.5,0.0c-0.6,-6.2 -5.7,-11.0 -12.0,-11.0c-0.2,0.0 -0.4,0.0 -0.7,0.0l3.8,3.8L16.55,2.5z"/>
+ <path
+ android:fill="#FFFFFFFF"
+ android:pathData="M7.55,21.5c-3.3,-1.5 -5.6,-4.7 -6.0,-8.5l-1.4,0.0c0.5,6.2 5.6,11.0 11.9,11.0c0.2,0.0 0.4,0.0 0.7,0.0l-3.8,-3.8L7.55,21.5z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/qs_user_detail.xml b/packages/SystemUI/res/layout/qs_user_detail.xml
new file mode 100644
index 0000000..1d6df61
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_user_detail.xml
@@ -0,0 +1,29 @@
+<?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
+ -->
+
+<!-- GridView -->
+<com.android.systemui.qs.tiles.UserDetailView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:verticalSpacing="4dp"
+ android:horizontalSpacing="4dp"
+ android:numColumns="3"
+ android:listSelector="@drawable/ripple_drawable">
+
+</com.android.systemui.qs.tiles.UserDetailView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
new file mode 100644
index 0000000..00b3645
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -0,0 +1,44 @@
+<?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
+ -->
+
+<com.android.systemui.qs.tiles.UserDetailItemView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:systemui="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="top|center_horizontal"
+ android:paddingTop="16dp"
+ android:paddingBottom="20dp">
+
+ <com.android.systemui.statusbar.phone.UserAvatarView
+ android:id="@+id/user_picture"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_marginBottom="12dp"
+ systemui:frameWidth="2dp"
+ systemui:activeFrameColor="@color/current_user_border_color"/>
+
+ <TextView
+ android:id="@+id/user_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="14sp"
+ android:text="@string/guest_nickname"/>
+
+</com.android.systemui.qs.tiles.UserDetailItemView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 7e8bfd32..3e4c1f6 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -28,7 +28,7 @@
android:layout_height="@dimen/recents_task_bar_height"
android:layout_gravity="top|center_horizontal"
android:background="@color/recents_task_bar_default_background_color">
- <ImageView
+ <com.android.systemui.recents.views.FixedSizeImageView
android:id="@+id/application_icon"
android:layout_width="@dimen/recents_task_view_application_icon_size"
android:layout_height="@dimen/recents_task_view_application_icon_size"
@@ -51,7 +51,7 @@
android:maxLines="2"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
- <ImageView
+ <com.android.systemui.recents.views.FixedSizeImageView
android:id="@+id/dismiss_task"
android:layout_width="48dp"
android:layout_height="48dp"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index e84300d..e3ac1c1 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -26,6 +26,23 @@
android:fitsSystemWindows="true"
android:descendantFocusability="afterDescendants">
+ <FrameLayout
+ android:id="@+id/backdrop"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ >
+ <ImageView android:id="@+id/backdrop_back"
+ android:layout_width="match_parent"
+ android:scaleType="centerCrop"
+ android:layout_height="match_parent" />
+ <ImageView android:id="@+id/backdrop_front"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ android:visibility="invisible" />
+ </FrameLayout>
+
<View android:id="@+id/scrim_behind"
android:layout_width="match_parent"
android:layout_height="match_parent" />
diff --git a/packages/SystemUI/res/layout/user_switcher_host.xml b/packages/SystemUI/res/layout/user_switcher_host.xml
deleted file mode 100644
index 816af57..0000000
--- a/packages/SystemUI/res/layout/user_switcher_host.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ Copyright (C) 2014 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<!-- FrameLayout -->
-<com.android.systemui.settings.UserSwitcherHostView
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#dd000000"
- android:elevation="12dp">
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/volume_panel_top"
- android:background="@*android:drawable/dialog_full_holo_dark">
- <ListView android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:listitem="@layout/user_switcher_item"/>
- </FrameLayout>
-</com.android.systemui.settings.UserSwitcherHostView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/user_switcher_item.xml b/packages/SystemUI/res/layout/user_switcher_item.xml
deleted file mode 100644
index 8df2f5a..0000000
--- a/packages/SystemUI/res/layout/user_switcher_item.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2014 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="64dp"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- tools:context=".settings.UserSwitcherDialog">
- <ImageView
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_marginStart="4dp"
- android:id="@+id/user_picture"
- tools:src="@drawable/dessert_zombiegingerbread"/>
- <TextView
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:id="@+id/user_name"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:padding="8dp"
- android:gravity="center_vertical"
- tools:text="Hiroshi Lockheimer"
- />
- <ImageView
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_marginEnd="4dp"
- android:src="@*android:drawable/ic_menu_delete"
- android:id="@+id/user_delete"
- android:background="?android:attr/selectableItemBackground"/>
-</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index cbd8227..d018820 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> toestelle)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth af"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helderheid"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Outo-draai"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotasie is gesluit"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Instellings"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Tyd"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ek"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nie gekoppel nie"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk nie"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi af"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Uitsaaiskerm"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helderheid"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Keer kleure om"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Meer instellings"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Klaar"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Gekoppel"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"USB-verbinding"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Warmkol"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Kennisgewings"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flitslig"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Selfoondata"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datagebruik"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Oorblywende data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Oor die limiet"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> gebruik"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g>-limiet"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Geen onlangse programme nie"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Programinligting"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"sluit na program"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Gelaai"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Laai tans"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Soek"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Gly op vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Gly links vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Moenie steur nie"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Geen onderbrekings nie, wekkers en tydhouers inkluis"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Geen onderbrekings nie"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Net prioriteitonderbrekings"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minder dringende kennisgewings hieronder"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tik weer om oop te maak"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Sleep op om te ontsluit"</string>
<string name="phone_hint" msgid="3101468054914424646">"Sleep regs vir foon"</string>
<string name="camera_hint" msgid="5241441720959174226">"Sleep links vir kamera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Totdat jy dit afskakel"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Onbepaalde tyd"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Geen"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioriteit"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Alles"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laai tans (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tot vol)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gas"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ gas"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Batteryspaarder is aan"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Toestel se werkverrigting is verminder."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Maak batteryspaarder se instellings oop"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 00514d6..599cdef 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ብሉቱዝ"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ብሉቱዝ (<xliff:g id="NUMBER">%d</xliff:g> መሣሪያዎች)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ብሉቱዝ ጠፍቷል"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ብሩህነት"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"በራስ ሰር አሽከርክር"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"አዙሪት ተቆልፏል"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"ቅንብሮች"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"ሰዓት"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"እኔ"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"አልተገናኘም"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ምንም አውታረ መረብ የለም"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ጠፍቷል"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"ማያ ገጽ ውሰድ"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ብሩህነት"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ራስ-ሰር"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"ቀለማትን ግልብጥ"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ተጨማሪ ቅንብሮች"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"ተከናውኗል"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"ተገናኝቷል"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"በማገናኘት ላይ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"መገናኛ ነጥብ"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ማሳወቂያዎች"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"የባትሪ ብርሃን"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"የውሂብ አጠቃቀም"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ቀሪ ውሂብ"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"ከገደብ በላይ"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ጥቅም ላይ ውሏል"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ገደብ"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"ምንም የቅርብ ጊዜ መተግበሪያዎች የሉም"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"መተግበሪያ-ጋር-ቆልፍ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ባትሪ ሞልቷል"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"ኃይል በመሙላት ላይ"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"ፍለጋ"</string>
<string name="description_direction_up" msgid="7169032478259485180">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ላይ አንሸራትት።"</string>
<string name="description_direction_left" msgid="7207478719805562165">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ግራ አንሸራትት።"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"አይረብሹ"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"ምንም ማቋረጦች የሉም፣ ማንቂያዎችንና የጊዜ መያዣዎችን ጨምሮ"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"ምንም ማቋረጦች የሉም"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"ቅድሚያ የሚሰጣቸው ማቋረጦች ብቻ"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"በጣም አስቸካይ ያልሆኑ ማሳወቂያዎች ከታች"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ለመክፈት ዳግም መታ ያድርጉ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ለማስከፈት ወደ ላይ ያንሸራትቱ"</string>
<string name="phone_hint" msgid="3101468054914424646">"ለስልክ ወደቀኝ ያንሸራትቱ"</string>
<string name="camera_hint" msgid="5241441720959174226">"ለካሜራ ወደግራ ያንሸራትቱ"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"ይህን እስኪያጠፉት ድረስ"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"ያለገደብ"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"ምንም"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"ቅድሚያ"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"ሁሉም"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ሃይል በመሙላት ላይ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> እስከሚሞላ ድረስ)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"እንግዳ"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ እንግዳ"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"የባትሪ ኃይል ቆጣቢ በርቷል"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"የመሳሪያው የአሰራር ብቃት ተቀንሷል።"</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"የባትሪ ኃይል ቆጣቢ ቅንብሮች"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index e59ea7c..da09ada 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث (<xliff:g id="NUMBER">%d</xliff:g> من الأجهزة)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"إيقاف البلوتوث"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"لا يتوفر أي أجهزة مقترنة"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"السطوع"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"دوران تلقائي"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"تم قفل التدوير"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"الإعدادات"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"الوقت"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"أنا"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"المستخدم"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"مستخدم جديد"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ليست متصلة"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"لا تتوفر شبكة"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"إيقاف Wi-Fi"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"بث الشاشة"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"لا تتوفر أية شبكة محفوظة"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"إرسال الشاشة"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"جارٍ الإرسال"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"جهاز لا يحمل اسمًا"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"جاهز للإرسال"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"لا يتوفر أي جهاز"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"السطوع"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"تلقائي"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"قلب الألوان"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"المزيد من الإعدادات"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"تم"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"متصل"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"جارٍ الاتصال..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"النطاق"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطة اتصال"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"الإشعارات"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"الفلاش"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"البيانات الخلوية"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"استخدام البيانات"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"البيانات المتبقية"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"فوق القيد"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> مستخدم"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"قيد <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"تحذير <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"ليست هناك تطبيقات حديثة"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"معلومات التطبيق"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"تقييد بالتطبيق"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"تم الشحن"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"جارٍ الشحن"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"بحث"</string>
<string name="description_direction_up" msgid="7169032478259485180">"تمرير لأعلى لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"تمرير لليسار لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"الرجاء عدم الإزعاج"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"بدون مقاطعة، بما في ذلك التنبيهات والموقتات"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"بدون مقاطعات"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"المقاطعات ذات الأولوية فقط"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"الإشعارات الأقل إلحاحًا أدناه"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"انقر مرة أخرى للفتح"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"مرر سريعًا لأعلى لإلغاء القفل"</string>
<string name="phone_hint" msgid="3101468054914424646">"مرر سريعًا إلى اليسار لفتح الهاتف"</string>
<string name="camera_hint" msgid="5241441720959174226">"مرر سريعًا إلى اليمين لفتح الكاميرا"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"لحين تعطيل هذا الإعداد"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"إلى أجل غير مسمى"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"بدون"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"الأولوية"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"الكل"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"جارٍ الشحن (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> حتى الامتلاء)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"المدعو"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ مدعو"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"وضع توفير الطاقة قيد التشغيل"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"تم تقليل أداء الجهاز."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"فتح إعدادات وضع توفير الطاقة"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 60ecc57..c37306e 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> устройства)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth е изключен"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркост"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматична ориентация"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Ориентацията е заключена"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Настройки"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Време"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Аз"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Няма връзка"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Няма мрежа"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi е изключен"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Екран за предаване"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яркост"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТ."</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Обръщане на цветовете"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Още настройки"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Установена е връзка"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетъринг"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка за достъп"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известия"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Светкавица"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Мобилни данни"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Пренос на данни"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Оставащи данни"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Над ограничението"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Използвано: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ограничение от <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Няма скорошни приложения"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"заключване в приложението"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заредена"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарежда се"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Търсене"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Плъзнете нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Плъзнете наляво за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Не ме безпокойте"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Без прекъсвания, включително будилници и таймери"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Без прекъсвания"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Само приоритетни прекъсвания"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Ппоказване на по-малко спешните известия по-долу"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Докоснете отново, за да отворите"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Прекарайте пръст нагоре, за да отключите"</string>
<string name="phone_hint" msgid="3101468054914424646">"Прекарайте пръст надясно, за да използвате телефона"</string>
<string name="camera_hint" msgid="5241441720959174226">"Прекарайте пръст наляво, за да включите камерата"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Докато не изключите това"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"За неопределено време"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Няма"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Приоритет"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Всички"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарежда се (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до пълно зареждане)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Гост"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ гост"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Режимът за запазване на батерията е включен"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Ефективността на устройството е намалена."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Отваряне на настройките за режима за запазване на батерията"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5409df5..ffe18c6 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositius)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivat"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillantor"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotació automàtica"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotació bloquejada"</string>
@@ -207,11 +209,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Configuració"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Jo"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Desconnectat"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hi ha cap xarxa"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desconnectada"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Pantalla d\'emissió"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillantor"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÀTICA"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inverteix els colors"</string>
@@ -219,12 +236,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Més opcions"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Fet"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connectat"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Ancoratge a xarxa"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacions"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Llanterna"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Dades mòbils"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Ús de dades"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dades restants"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Límit excedit"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Utilitzats: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Límit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"No hi ha aplicacions recents."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloqueig d\'aplicació"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"S\'està carregant"</string>
@@ -234,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Cerca"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Fes lliscar el dit cap amunt per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Fes lliscar el dit cap a l\'esquerra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"No molesteu"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Sense interrupcions (incloses alarmes i temporitzadors)"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Cap interrupció"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Només les interrupcions prioritàries"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificacions menys urgents a continuació"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Torna a tocar per obrir-la."</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Fes lliscar el dit cap amunt per desbloquejar el teclat."</string>
<string name="phone_hint" msgid="3101468054914424646">"Fes lliscar el dit cap a la dreta per obrir el telèfon."</string>
<string name="camera_hint" msgid="5241441720959174226">"Fes lliscar el dit cap a l\'esquerra per obrir la càmera."</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Fins que no ho desactivis"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidament"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Cap"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritàries"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Totes"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregant (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> per completar la càrrega)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Convidat"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Convidat"</string>
@@ -256,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"La funció Estalvi de bateria està activada."</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"S\'ha reduït el rendiment del dispositiu."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Obre la configuració de la funció Estalvi de bateria"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 5b055f3..99fd84f 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> zařízení)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Rozhraní Bluetooth je vypnuto"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jas"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatické otáčení"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Otáčení je uzamčeno"</string>
@@ -207,11 +209,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Nastavení"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Doba"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Já"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nepřipojeno"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Žádná síť"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi vypnuta"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Odesílání obrazovky"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jas"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Převrátit barvy"</string>
@@ -219,12 +236,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Další nastavení"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Hotovo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Připojeno"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Sdílení datového připojení"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Oznámení"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svítilna"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobilní data"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Využití dat"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Zbývající data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Překročen limit"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Využito: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Žádné nedávné aplikace"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informace o aplikaci"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"uzamknout v aplikaci"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabito"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíjení"</string>
@@ -234,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Vyhledávání"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Přejeďte prstem nahoru: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
<string name="description_direction_left" msgid="7207478719805562165">"Přejeďte prstem doleva: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Nerušit"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Žádná přerušení – ani budíky a časovače"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Žádná vyrušení"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Pouze prioritní vyrušení"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Méně urgentní oznámení níže"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Oznámení otevřete opětovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Zařízení odemknete přejetím prstem nahoru"</string>
<string name="phone_hint" msgid="3101468054914424646">"Telefon otevřete přejetím prstem vpravo."</string>
<string name="camera_hint" msgid="5241441720959174226">"Fotoaparát otevřete přejetím prstem vlevo."</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Dokud tuto funkci nevypnete"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Na dobu neurčitou"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Žádné"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritní"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Vše"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíjení (plně nabito za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Host"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Přidat hosta"</string>
@@ -256,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Režim Úspora baterie je zapnutý."</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Výkon zařízení je snížen."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Otevřít nastavení režimu Úspora baterie"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 760ae05..a25cd71 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheder)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth slået fra"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Lysstyrke"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Roter automatisk"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotationen er låst"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Indstillinger"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Tid"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Mig"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ikke forbundet"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Intet netværk"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi slået fra"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Skærm til casting"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Lysstyrke"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Byt om på farver"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Flere indstillinger"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Udført"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Tilsluttet"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Netdeling"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Underretninger"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelygte"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobildata"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Dataforbrug"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Resterende data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Over grænsen"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> brugt"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Grænse: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Der er ingen seneste apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Oplysninger om applikationen"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Bliv i app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opladet"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Oplader"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Søgning"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Glid op for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Glid til venstre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Vil ikke forstyrres"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Ingen afbrydelser, herunder alarmer og timere"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Ingen afbrydelser"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Kun prioriterede afbrydelser"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre presserende underretninger nedenfor"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tryk igen for at åbne"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Stryg for at låse op"</string>
<string name="phone_hint" msgid="3101468054914424646">"Stryg til højre for at bruge telefonen"</string>
<string name="camera_hint" msgid="5241441720959174226">"Stryg til venstre for at åbne kameraet"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Indtil du slår denne indstilling fra"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Uendeligt"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Ingen"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritet"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Opladning (fuldt opladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gæst"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Gæst"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Batteribesparende er slået til"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Enhedens ydeevne reduceres."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Åbn indstillinger for Batteribesparende"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 9df283b..92b12c6 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Geräte)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth aus"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helligkeit"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatisch drehen"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Drehung gesperrt"</string>
@@ -207,11 +209,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Einstellungen"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Uhrzeit"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ich"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"WLAN"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nicht verbunden"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Kein Netz"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN aus"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Bildschirmübertragung"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helligkeit"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Farben umkehren"</string>
@@ -219,12 +236,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Weitere Einstellungen"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Fertig"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Verbunden"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Benachrichtigungen"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taschenlampe"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobilfunkdaten"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datennutzung"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Verbleibende Daten"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limit überschritten"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> verwendet"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> Datenlimit"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Keine neuen Apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"App-Info"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"App-Verriegelung"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Aufgeladen"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Wird aufgeladen"</string>
@@ -234,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Suche"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach oben schieben"</string>
<string name="description_direction_left" msgid="7207478719805562165">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach links schieben"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Nicht stören"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Unterbrechungsfrei, gilt auch für Alarme und Timer"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Keine Unterbrechungen"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Nur wichtige Unterbrechungen"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Weniger dringende Benachrichtigungen unten"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Erneut tippen, um Benachrichtigung zu öffnen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Zum Entsperren nach oben wischen"</string>
<string name="phone_hint" msgid="3101468054914424646">"Zum Öffnen des Telefons nach rechts wischen"</string>
<string name="camera_hint" msgid="5241441720959174226">"Zum Öffnen der Kamera nach links wischen"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Bis zur Deaktivierung"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Unbegrenzt"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Keine"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Wichtig"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Wird aufgeladen (voll in <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gast"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Gast"</string>
@@ -256,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Energiesparmodus ist aktiviert"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Die Geräteleistung wurde herabgesetzt."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Einstellungen für den Energiesparmodus öffnen"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 60d8225..16056661 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> συσκευές)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Απενεργοποιημένο Bluetooth"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Φωτεινότητα"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Αυτόματη περιστροφή"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Η περιστροφή είναι κλειδωμένη"</string>
@@ -207,11 +209,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Ρυθμίσεις"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Ώρα"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Εγώ"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Μη συνδεδεμένο"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Κανένα δίκτυο"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ανενεργό"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Μετάδοση οθόνης"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Φωτεινότητα"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ΑΥΤΟΜΑΤΗ"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Αντιστροφή χρωμάτων"</string>
@@ -219,12 +236,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Περισσότερες ρυθμίσεις"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Τέλος"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Συνδέθηκε"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Πρόσδεση"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Σημείο πρόσβασης Wi-Fi"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ειδοποιήσεις"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Φακός"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Δεδομένα κινητής τηλεφωνίας"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Χρήση δεδομένων"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Υπολειπόμενα δεδομένα"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Υπέρβαση ορίου"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Χρησιμοποιούνται <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Όριο <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Καμία πρόσφατη εφαρμογή"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Φορτίστηκε"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Φόρτιση"</string>
@@ -234,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Αναζήτηση"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Κύλιση προς τα επάνω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Κύλιση προς τα αριστερά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Μην ενοχλείτε"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Χωρίς διακοπές, μεταξύ των οποίων συναγερμών και χρονομέτρων"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Χωρίς διακοπές"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Μόνο διακοπές προτεραιότητας"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Λιγότερο επείγουσες ειδοποιήσεις παρακάτω"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Πατήστε ξανά για να ανοίξετε"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Σύρετε για να ξεκλειδώσετε"</string>
<string name="phone_hint" msgid="3101468054914424646">"Σύρετε προς τα δεξιά για το τηλέφωνο"</string>
<string name="camera_hint" msgid="5241441720959174226">"Σύρετε αριστερά για τη φωτογραφική μηχανή"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Μέχρι να το απενεργοποιήσετε"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Επ\' αόριστον"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Κανένα"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Προτεραιότητα"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Όλα"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Φόρτιση (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> για πλήρη φόρτιση)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Επισκέπτης"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Επισκέπτης"</string>
@@ -256,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Η Εξοικονόμηση μπαταρίας είναι ενεργή"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Η απόδοση της συσκευής μειώνεται."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Άνοιγμα ρυθμίσεων Εξοικονόμησης μπαταρίας"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 94a4592..29e3591 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No paired devices available"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Auto-rotate"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotation locked"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Settings"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Time"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Me"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"User"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"New user"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Cast screen"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"No saved networks available"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Cast screen"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"Casting"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Unnamed device"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Ready to cast"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"No devices available"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Invert colours"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"More settings"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Finished"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connected"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobile data"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Data usage"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Remaining data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Over limit"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> used"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"No recent apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Charging"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Search"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Do not disturb"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"No interruptions, including alarms and timers"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"No interruptions"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Priority interruptions only"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
<string name="phone_hint" msgid="3101468054914424646">"Swipe right for phone"</string>
<string name="camera_hint" msgid="5241441720959174226">"Swipe left for camera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinitely"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"None"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Priority"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Guest"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Guest"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Device performance is reduced."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Open battery saver settings"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 94a4592..29e3591 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"No paired devices available"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Auto-rotate"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotation locked"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Settings"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Time"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Me"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"User"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"New user"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Not Connected"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Cast screen"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"No saved networks available"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Cast screen"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"Casting"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Unnamed device"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Ready to cast"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"No devices available"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Invert colours"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"More settings"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Finished"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connected"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"Connecting..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobile data"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Data usage"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Remaining data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Over limit"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> used"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> warning"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"No recent apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Charging"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Search"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Do not disturb"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"No interruptions, including alarms and timers"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"No interruptions"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Priority interruptions only"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
<string name="phone_hint" msgid="3101468054914424646">"Swipe right for phone"</string>
<string name="camera_hint" msgid="5241441720959174226">"Swipe left for camera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Until you turn this off"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinitely"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"None"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Priority"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"All"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charging (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> until full)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Guest"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Guest"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Battery saver is on"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Device performance is reduced."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Open battery saver settings"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 2a8848f..af8ca32 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillo"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotación automática"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotación bloqueada"</string>
@@ -207,11 +209,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Configuración"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Yo"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Sin conexión"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sin red"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivada"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Transmitir pantalla"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillo"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Invertir colores"</string>
@@ -219,12 +236,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Más configuraciones"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Listo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectado"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Anclaje a red"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Datos móviles"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de datos"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Datos restantes"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Límite superado"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Utilizados: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Límite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"No hay aplicaciones recientes."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"fijar aplicación"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
@@ -234,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"No molestar"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Sin interrupciones, incluidos alarmas y temporizadores"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Sin interrupciones"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Solo interrupciones de prioridad"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificaciones menos urgentes abajo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Presionar de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslizar el dedo hacia arriba para desbloquear"</string>
<string name="phone_hint" msgid="3101468054914424646">"Desliza hacia la derecha para abrir el teléfono."</string>
<string name="camera_hint" msgid="5241441720959174226">"Desliza hacia la izquierda para acceder a la cámara."</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Hasta que lo desactives"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Ninguno"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridad"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Todo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (faltan <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> para completar)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Invitado"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Agregar invitado"</string>
@@ -256,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Ahorro de batería activado"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Rendimiento del dispositivo reducido"</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Abrir configuración del ahorro de batería"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index b2ac0fd..ff6b5fe 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desactivado"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brillo"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Girar automáticamente"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotación bloqueada"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Ajustes"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Yo"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"No conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hay red."</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivado"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Pantalla de Cast"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillo"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Invertir colores"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Más opciones"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Listo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectado"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Anclaje a red"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Linterna"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Datos móviles"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de datos"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Datos restantes"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Límite superado"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilizado"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Límite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"No hay aplicaciones recientes"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloqueo de aplicación"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Cargando"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"No molestar"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Sin interrupciones, incluidos alarmas y temporizadores"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Sin interrupciones"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Solo interrupciones de prioridad"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificaciones menos urgente abajo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toca de nuevo para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Desliza el dedo hacia arriba para desbloquear"</string>
<string name="phone_hint" msgid="3101468054914424646">"Desliza el dedo hacia la izquierda para acceder al teléfono"</string>
<string name="camera_hint" msgid="5241441720959174226">"Desliza el dedo hacia la izquierda para acceder a la cámara"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Hasta apagar el dispositivo"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Ninguno"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridad"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Todo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Cargando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hasta completar)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Invitado"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Añadir invitado"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Ahorro de batería activado"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Rendimiento del dispositivo reducido."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Abrir ajustes de la función de ahorro de batería"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 98a27ca..8024657 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> seadet)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth on väljas"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Heledus"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automaatne pööramine"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Pööramine on lukustatud"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Seaded"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Aeg"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Mina"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"WiFi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ühendus puudub"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Võrku pole"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WiFi-ühendus on väljas"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Ülekandeekraan"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Heledus"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAATNE"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Vaheta värve"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Rohkem seadeid"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Valmis"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ühendatud"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jagamine"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Leviala"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Märguanded"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taskulamp"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobiilne andmeside"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Andmekasutus"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Järelejäänud andmemaht"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Üle limiidi"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> on kasutatud"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limiit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Hiljutisi rakendusi pole"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lukusta rakendusele"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laetud"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Laadimine"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Otsing"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Lohistage üles: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Lohistage vasakule: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Mitte segada"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Mitte ühtegi katkestust, sh alarmid ja taimerid"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Mitte ühtegi katkestust"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Ainult prioriteetsed katkestused"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Vähem kiireloomulised märguanded on allpool"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Avamiseks puudutage uuesti"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Lukustuse tühistamiseks pühkige üles"</string>
<string name="phone_hint" msgid="3101468054914424646">"Telefoni kasutamiseks pühkige paremale"</string>
<string name="camera_hint" msgid="5241441720959174226">"Kaamera kasutamiseks pühkige vasakule"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Kuni lülitate selle välja"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Määramata ajaks"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Puudub"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioriteet"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Kõik"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laadimine (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>, kuni seade on täis)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Külaline"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ külaline"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Akusäästja on sisse lülitatud"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Seadme jõudlust on vähendatud."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Ava akusäästja seaded"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index f5f86a3..42ef57f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"بلوتوث"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"بلوتوث ( <xliff:g id="NUMBER">%d</xliff:g> دستگاه)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"بلوتوث خاموش"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"روشنایی"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"چرخش اتوماتیک"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"چرخش قفل شد"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"تنظیمات"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"زمان"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"من"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"متصل نیست"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"شبکهای موجود نیست"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi خاموش است"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"فرستادن صفحهنمایش"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"روشنایی"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"خودکار"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"برگردان رنگها"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"تنظیمات بیشتر"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"انجام شد"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"متصل"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"اتصال به اینترنت با تلفن همراه"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطه اتصال"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"اعلانها"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"چراغ قوه"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"دادههای شبکه تلفن همراه"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"مصرف داده"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"دادههای باقیمانده"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"بیش از حد مجاز"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> استفاده شده"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> محدودیت"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"هیچ برنامه جدیدی موجود نیست"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"اطلاعات برنامه"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"قفل در برنامه"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"شارژ کامل شد"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"در حال شارژ شدن"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"جستجو"</string>
<string name="description_direction_up" msgid="7169032478259485180">"لغزاندن به بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"لغزاندن به چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"مزاحم نشوید"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"بدون قطع شدن، شامل زنگهای هشدار و تایمرها"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"بدون وقفه"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"فقط وقفههای اولویتدار"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"اعلانهای کمتر فوری در زیر"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"برای باز کردن دوباره ضربه بزنید"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"برای باز کردن قفل سریع به بالا بکشید"</string>
<string name="phone_hint" msgid="3101468054914424646">"برای تلفن انگشت را تند به سمت چپ بکشید"</string>
<string name="camera_hint" msgid="5241441720959174226">"برای دوربین انگشت را تند به سمت راست بکشید"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"تا وقتی آن را خاموش کنید"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"نامحدود"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"هیچکدام"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"اولویت"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"همه"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"در حال شارژ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> تا شارژ کامل)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"مهمان"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ مهمان"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"ذخیره کننده باتری روشن است."</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"عملکرد دستگاه کاهش یافته است."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"باز کردن تنظیمات ذخیره کننده باتری"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>٪٪"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4827ed1..7a41bb4 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> laitetta)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth pois käytöstä"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kirkkaus"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automaattinen kääntö"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Kääntö lukittu"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Asetukset"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Aika"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Minä"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ei yhteyttä"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ei verkkoa"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi-yhteys pois käytöstä"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Lähetysnäyttö"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kirkkaus"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Käänteiset värit"</string>
@@ -217,13 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Lisäasetukset"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Valmis"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Yhdistetty"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jaettu yhteys"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ilmoitukset"</string>
- <!-- no translation found for quick_settings_flashlight_label (2133093497691661546) -->
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Taskulamppu"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobiilitiedonsiirto"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datakäyttö"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Käytettävissä"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Kiintiö ylitetty"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"käytetty <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"kiintiö <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
<skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Ei viimeaikaisia sovelluksia"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Sovellustiedot"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lukitse sovellukseen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ladattu"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Ladataan"</string>
@@ -233,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Haku"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Liu\'uta ylös ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Liu\'uta vasemmalle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Älä häiritse"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Ei keskeytyksiä, hälytyksiä tai ajastimia"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Ei häiriöitä"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Vain tärkeät häiriöt"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Vähemmän kiireelliset ilmoitukset ovat alla"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Avaa napauttamalla uudelleen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Avaa lukitus pyyhkäisemällä ylös"</string>
<string name="phone_hint" msgid="3101468054914424646">"Avaa puhelin pyyhkäisemällä oikealle"</string>
<string name="camera_hint" msgid="5241441720959174226">"Avaa kamera pyyhkäisemällä oikealle"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Kunnes poistat tämän käytöstä"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Toistaiseksi"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Ei mitään"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Tärkeät"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Kaikki"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ladataan (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kunnes täynnä)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Vieras"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Vieras"</string>
@@ -255,4 +287,9 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Virransäästö on käytössä"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Laitteen virrankulutusta vähennetään."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Avaa virransäästöasetukset"</string>
+ <!-- String.format failed for translation -->
+ <!-- no translation found for battery_level_template (1609636980292580020) -->
+ <skip />
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a776981..5cd023d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"BLUETOOTH DÉSACTIVÉ"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminosité"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotation automatique"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotation verrouillée"</string>
@@ -207,11 +209,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Paramètres"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Heures"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Moi"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connecté"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Écran de diffusion"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosité"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inverser les couleurs"</string>
@@ -219,12 +236,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Plus de paramètres"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Terminé"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connecté"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Partage de connexion"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Point d\'accès sans fil"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Données cellulaires"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilisation de données"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limite dépassée"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Quantité de données utilisées :<xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limite : <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Aucune application récente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Détails de l\'application"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"verrouiller sur l\'application"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargée"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Charge en cours..."</string>
@@ -234,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Recherche"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Faire glisser le doigt vers le haut : <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
<string name="description_direction_left" msgid="7207478719805562165">"Faites glisser votre doigt vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Ne pas déranger"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Aucune interruption (alarmes et minuteries incluses)"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Aucune interruption"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Interruptions prioritaires seulement"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes affichées ci-dessous"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Touchez à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Glissez vers le haut pour déverrouiller"</string>
<string name="phone_hint" msgid="3101468054914424646">"Balayez l\'écran vers la droite pour accéder au téléphone"</string>
<string name="camera_hint" msgid="5241441720959174226">"Balayez l\'écran vers la gauche pour accéder à l\'appareil photo"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indéfiniment"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Aucun"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Priorité"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Tous"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours... (chargée à 100 % dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Invité"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Ajouter un invité"</string>
@@ -256,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"La fonction Économie d\'énergie est activée"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Les performances de l\'appareil sont réduites."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Ouvrir les paramètres d\'économie d\'énergie"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 4254503..4c527f1 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth désactivé"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminosité"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotation automatique"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotation verrouillée"</string>
@@ -207,11 +209,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Paramètres"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Heure"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Moi"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connecté"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Caster l\'écran"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosité"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inverser les couleurs"</string>
@@ -219,12 +236,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Plus de paramètres"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"OK"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connecté"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Partage de connexion"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Point d\'accès"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Données mobiles"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Consommation des données"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limite dépassée"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilisés"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> au maximum"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Aucune application récente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informations sur l\'application"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"verrouiller sur l\'application"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargé"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"En charge"</string>
@@ -234,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Rechercher"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Faites glisser vers le haut pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Faites glisser vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Ne pas déranger"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Aucune interruption (alarmes et minuteurs inclus)"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Aucune interruption"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Interruptions prioritaires seulement"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes ci-dessous"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Appuyer à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Faire glisser pour déverrouiller"</string>
<string name="phone_hint" msgid="3101468054914424646">"Balayer l\'écran vers la droite pour accéder au téléphone"</string>
<string name="camera_hint" msgid="5241441720959174226">"Balayer l\'écran vers la gauche pour accéder à l\'appareil photo"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indéfiniment"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Aucune"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritaire"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Toutes"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Charge en cours… (chargé à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Invité"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Ajouter un invité"</string>
@@ -256,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"L\'économiseur de batterie est activé"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Les performances de l\'appareil sont réduites."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Ouvrir les paramètres de l\'économiseur de batterie"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 0b6ec13..d98e520 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> उपकरण)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth बंद"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"कोई भी युग्मित उपकरण उपलब्ध नहीं"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"स्क्रीन की रोशनी"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"स्वत: घुमाएं"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"घुमाना लॉक किया गया"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"सेटिंग"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"समय"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"मुझे"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"उपयोगकर्ता"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"नया उपयोगकर्ता"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"कनेक्ट नहीं है"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"कोई नेटवर्क नहीं"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi बंद"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"स्क्रीन कास्ट करें"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"कोई भी सहेजा गया नेटवर्क उपलब्ध नहीं"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"स्क्रीन कास्ट करें"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"कास्टिंग"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"अनाम उपकरण"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"कास्ट करने के लिए तैयार"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"कोई उपकरण उपलब्ध नहीं"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"स्क्रीन की रोशनी"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वत:"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"रंग उलटें"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"और सेटिंग"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"पूर्ण"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"कनेक्ट है"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"कनेक्ट हो रहा है..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदरिंग"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हॉटस्पॉट"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचनाएं"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"फ़्लैशलाइट"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"सेल्यूलर डेटा"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"डेटा उपयोग"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"शेष डेटा"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"सीमा से अधिक"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> उपयोग किया गया"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> सीमा"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"कोई हाल ही का ऐप्स नहीं"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्लिकेशन जानकारी"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"ऐप्स पर लॉक करें"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज हो गई है"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"चार्ज हो रही है"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"खोजें"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्लाइड करें."</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं स्लाइड करें."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"परेशान न करें"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"अलार्म और टाइमर सहित कोई बाधा नहीं है"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"कोई अवरोध नहीं"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"केवल प्राथमिक अवरोध"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"कम अत्यावश्यक सूचनाएं नीचे दी गई हैं"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"खोलने के लिए पुन: टैप करें"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करने के लिए ऊपर स्वाइप करें"</string>
<string name="phone_hint" msgid="3101468054914424646">"फ़ोन के लिए दाएं स्वाइप करें"</string>
<string name="camera_hint" msgid="5241441720959174226">"कैमरे के लिए बाएं स्वाइप करें"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"जब तक आप इसे बंद नहीं कर देते"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"अनिश्चित समय तक"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"कोई नहीं"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"प्राथमिकता"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"सभी"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"चार्ज हो रहा है (पूर्ण होने में <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> शेष)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"अतिथि"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ अतिथि"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"बैटरी सेवर चालू है"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"उपकरण का प्रदर्शन कम हो गया है."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"बैटरी सेवर सेटिंग चालू करें"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f9ce6d0..1e69412 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (broj uređaja: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth isključen"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Svjetlina"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatsko izmjenjivanje"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Izmjenjivanje je zaključano"</string>
@@ -205,26 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Postavke"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Vrijeme"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ja"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nije povezano"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nema mreže"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi isključen"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Emitirani zaslon"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Svjetlina"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATSKI"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Preokreni boje"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Način korekcije boje"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Više postavki"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Gotovo"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Povezano"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Dijeljenje veze"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Žarišna točka"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavijesti"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Bljeskalica"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobilni podaci"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Potrošnja podataka"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostali podaci"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Iznad ograničenja"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> iskorišteno"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ograničenje od <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Nema nedavnih aplikacija"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"zaključaj na aplikaciju"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Punjenje"</string>
@@ -234,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Kliznite prema gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Kliznite lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Ne ometaj"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Bez prekida, uključujući alarme i tajmere"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Bez prekida"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Samo prioritetni prekidi"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manje hitne obavijesti pri dnu"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite opet za otvaranje"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Prijeđite prstom prema gore za otključavanje"</string>
<string name="phone_hint" msgid="3101468054914424646">"Prijeđite prstom udesno za telefon"</string>
<string name="camera_hint" msgid="5241441720959174226">"Prijeđite prstom ulijevo za fotoaparat"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Dok ne isključite"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Neodređeno"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Ništa"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritet"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Sve"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Punjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napunjenosti)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gost"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ gost"</string>
@@ -256,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Štednja baterije je uključena"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Uređaj radi smanjenim intenzitetom."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Otvaranje postavki štednje baterije"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index eb4c893..9ca0b41 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> eszköz)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth kikapcsolva"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Fényerő"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatikus elforgatás"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Elforgatás zárolva"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Beállítások"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Idő"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Én"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nincs kapcsolat"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nincs hálózat"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi kikapcsolva"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Képernyőtartalom átküldése"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Fényerő"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"automatikus"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Színek invertálása"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"További beállítások"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Kész"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Csatlakoztatva"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Megosztás"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Értesítések"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zseblámpa"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobiladat-kapcsolat"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Adathasználat"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Fennmaradó adatmennyiség"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Túllépte a korlátot"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> felhasználva"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> korlát"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Nincsenek nemrég használt alkalmazások"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"alkalmazászárolás"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Feltöltve"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Töltés"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Keresés"</string>
<string name="description_direction_up" msgid="7169032478259485180">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa felfelé."</string>
<string name="description_direction_left" msgid="7207478719805562165">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa balra."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Ne zavarjanak"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Semmi sem zavarhatja, beleértve a riasztásokat és időzítőket"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Ne zavarjon"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Csak prioritást élvező zavaró üzenetek"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"A kevésbé sürgős értesítések lentebb vannak"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Koppintson rá ismét a megnyitáshoz"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Húzza felfelé az ujját a feloldáshoz"</string>
<string name="phone_hint" msgid="3101468054914424646">"A telefon eléréséhez csúsztassa ujját jobbra"</string>
<string name="camera_hint" msgid="5241441720959174226">"A fényképezőgép eléréséhez csúsztassa ujját balra"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Amíg ki nem kapcsolja ezt"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Határozatlan ideig"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Nincs"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritást élvező"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Összes"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Töltés (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> a teljes töltöttségig)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Vendég"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ vendég"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Akkumulátorkímélő mód bekapcsolva"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Az eszköz teljesítménye lecsökkentve."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Akkumulátorkímélő mód beállításainak megnyitása"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>. szint"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 32fa748..32d8730 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> սարք)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth-ն անջատված է"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Պայծառություն"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Ինքնապտտում"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Պտտումը կողպված է"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Կարգավորումներ"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Ժամանակը"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ես"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Միացված չէ"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ցանց չկա"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi-ը անջատված է"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Հեռակա էկրան"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Պայծառություն"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"Ինքնաշխատ"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Շրջել գույները"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Հավելյալ կարգավորումներ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Պատրաստ է"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Կապակցված է"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Միացում"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Թեժ կետ"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ծանուցումներ"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Լապտեր"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Բջջային տվյալներ"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Տվյալների օգտագործումը"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Մնացած տվյալները"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Եզրային սահմանաչափը"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> օգտագործված է"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Սահմանը՝ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Նոր հավելվածներ չկան"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Lock-to-app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Լիցքավորված է"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Լիցքավորվում է"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Որոնել"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Սահեցրեք վերև <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
<string name="description_direction_left" msgid="7207478719805562165">"Սահեցրեք ձախ` <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Չխանգարել"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Առանց ընդհատումների՝ ներառյալ զարթուցիչներն ու ժամաչափերը"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Առանց ընդհատումների"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Միայն կարևոր ընդհատումներ"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Պակաս հրատապ ծանուցումները ստորև"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Կրկին հպեք՝ բացելու համար"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Սահեցրեք վերև` ապակողպելու համար"</string>
<string name="phone_hint" msgid="3101468054914424646">"Հեռախոսի համար սահեցրեք աջ"</string>
<string name="camera_hint" msgid="5241441720959174226">"Խցիկի համար սահեցրեք ձախ"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Քանի դեռ չեք անջատել"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Անորոշ ժամանակով"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"-"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Կարևորություն"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Բոլորը"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Լիցքավորում (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> մինչև լրիվ լիցքավորումը)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Հյուր"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Հյուր"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Մարտկոցի տնտեսումը միացված է"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Սարքի կատարողականը նվազեցված է:"</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Բացել մարտկոցի տնտեսման կարգավորումները"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 5ef3bda..c7a911f 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Perangkat)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Mati"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kecerahan"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotasi otomatis"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotasi terkunci"</string>
@@ -205,26 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Setelan"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Waktu"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Saya"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Tidak Tersambung"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tidak Ada Jaringan"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Mati"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Layar transmisi"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kecerahan"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATIS"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inversi warna"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Mode koreksi warna"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Setelan lainnya"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Selesai"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Tersambung"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Menambatkan"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampu senter"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Data seluler"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Penggunaan data"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Data tersisa"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Melebihi batas"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> digunakan"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Batas <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Tidak ada aplikasi terkini"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Info Aplikasi"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"kunci ke aplikasi"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Terisi"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengisi daya"</string>
@@ -234,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Telusuri"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Geser ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Geser ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Jangan ganggu"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Tanpa gangguan, termasuk alarm dan pewaktu"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Tidak ada interupsi"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Hanya interupsi prioritas"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Pemberitahuan kurang darurat di bawah"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ketuk lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Gesek ke atas untuk membuka kunci"</string>
<string name="phone_hint" msgid="3101468054914424646">"Gesek ke kanan untuk menelepon"</string>
<string name="camera_hint" msgid="5241441720959174226">"Gesek ke kiri untuk kamera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Hingga Anda menonaktifkan ini"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Tidak ditentukan"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Tidak ada"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritas"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Semua"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengisi daya (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hingga penuh)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Tamu"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Tamu"</string>
@@ -256,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Penghemat baterai aktif"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Kinerja perangkat dikurangi."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Buka setelan penghemat baterai"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index efc88e0..27a31bb 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -164,7 +164,7 @@
<string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Modalità aereo: <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Posizione: <xliff:g id="STATE">%s</xliff:g>."</string>
- <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Allarme impostato per: <xliff:g id="TIME">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Sveglia impostata per le <xliff:g id="TIME">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Chiudi riquadro"</string>
<string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Più tempo"</string>
<string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Meno tempo"</string>
@@ -193,6 +193,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivi)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth spento"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nessun dispositivo accoppiato disponibile"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminosità"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotazione automatica"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotazione bloccata"</string>
@@ -207,11 +208,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Impostazioni"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Ora"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Io"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"Utente"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"Nuovo utente"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connesso"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nessuna rete"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi disattivato"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Trasmetti schermo"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nessuna rete salvata disponibile"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Trasmetti schermo"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"In trasmissione"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Dispositivo senza nome"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Pronto a trasmettere"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Nessun dispositivo disponibile"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosità"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inverti colori"</string>
@@ -219,12 +227,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Altre impostazioni"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Fine"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Connesso"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"Connessione..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifiche"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Rete dati"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilizzo dati"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dati rimanenti"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limite superato"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilizzati"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limite di <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avviso <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"Nessuna app recente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"blocca su app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carica"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"In carica"</string>
@@ -234,14 +251,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Ricerca"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Su per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"A sinistra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Non disturbare"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Senza interruzioni, inclusi sveglie e timer"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Nessuna interruzione"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Solo interruzioni con priorità"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifiche meno urgenti in basso"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tocca ancora per aprire"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Scorri verso l\'alto per sbloccare"</string>
<string name="phone_hint" msgid="3101468054914424646">"Scorri verso destra per accedere al telefono"</string>
<string name="camera_hint" msgid="5241441720959174226">"Scorri verso sinistra per accedere alla fotocamera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Fino alla disattivazione"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"In modo indefinito"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Nessuno"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Priorità"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Tutti"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"In carica (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> al termine)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Ospite"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ ospite"</string>
@@ -256,4 +278,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Risparmio batteria attivo"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Le prestazioni del dispositivo sono ridotte."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Apri impostazioni risparmio batteria"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 143bdd7..6a62b627 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> מכשירים)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth מופסק"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"אין מכשירים מותאמים זמינים"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"בהירות"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"סיבוב אוטומטי"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"סיבוב נעול"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"הגדרות"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"שעה"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"אני"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"משתמש"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"משתמש חדש"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"לא מחובר"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"אין רשת"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi כבוי"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"העבר מסך"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"אין רשתות שמורות זמינות"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"העבר מסך"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"מעביר"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"מכשיר ללא שם"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"מוכן להעביר"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"אין מכשירים זמינים"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"בהירות"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"אוטומטי"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"הפוך צבעים"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"הגדרות נוספות"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"בוצע"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"מחובר"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"מתחבר..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"שיתוף אינטרנט בין ניידים"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"נקודה לשיתוף אינטרנט"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"הודעות"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"פנס"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"נתונים סלולריים"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"שימוש בנתונים"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"מכסת נתונים נותרת"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"חריגה מההגבלה"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> בשימוש"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"הגבלה של <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"אזהרה - <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"אין אפליקציות אחרונות"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"נעל לאפליקציה"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"טעון"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"טוען"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"חיפוש"</string>
<string name="description_direction_up" msgid="7169032478259485180">"הסט למעלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"הסט שמאלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"נא לא להפריע"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"ללא הפרעות, כולל התראות וטיימרים"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"ללא הפרעות"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"רק הפרעות בעדיפות גבוהה"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"הודעות בדחיפות נמוכה יותר בהמשך"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"הקש שוב כדי לפתוח"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"החלק מעלה כדי לבטל את הנעילה"</string>
<string name="phone_hint" msgid="3101468054914424646">"החלק ימינה להפעלת הטלפון"</string>
<string name="camera_hint" msgid="5241441720959174226">"החלק שמאלה להפעלת המצלמה"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"עד שתכבה"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"ללא הגבלה"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"ללא"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"עדיפות"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"הכל"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"טוען (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> עד לסיום)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"אורח"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ אורח"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"תכונת \'חיסכון בסוללה\' פועלת"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"פעילות המכשיר צומצמה."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"פתח את ההגדרות של \'חיסכון בסוללה\'"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index fc77238..c78d42a 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth(端末数<xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth OFF"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"画面の明るさ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"自動回転"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"画面の向きをロック"</string>
@@ -207,26 +209,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"設定"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"時間"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"このユーザー"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"接続されていません"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ネットワークなし"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi OFF"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"画面のキャスト"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"画面の明るさ"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"色を反転"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"色補正モード"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"詳細設定"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"完了"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"接続済み"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"テザリング"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"アクセスポイント"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ライト"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"モバイルデータ"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"データ使用量"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"残りのデータ"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"上限オーバー"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g>使用中"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"最近使ったアプリはありません"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"アプリロック"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"充電が完了しました"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"充電しています"</string>
@@ -236,15 +262,20 @@
<string name="description_target_search" msgid="3091587249776033139">"検索します"</string>
<string name="description_direction_up" msgid="7169032478259485180">"上にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
<string name="description_direction_left" msgid="7207478719805562165">"左にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"通知を非表示"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"サイレント(アラームやタイマーなど)"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"サイレント"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"優先的な中断のみ"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"緊急度の低い通知を下に表示"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"開くにはもう一度タップしてください"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ロック解除するには上にスワイプしてください"</string>
<string name="phone_hint" msgid="3101468054914424646">"右にスワイプして電話を表示"</string>
<string name="camera_hint" msgid="5241441720959174226">"左にスワイプしてカメラを表示"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"ユーザーがOFFにするまで"</string>
- <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中(フルになるまで<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"制限なし"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"なし"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"優先的"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"すべて"</string>
+ <string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中(フル充電まで<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"ゲスト"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ ゲスト"</string>
<plurals name="zen_mode_duration_minutes">
@@ -258,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"バッテリーセーバーがON"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"端末のパフォーマンスが制限されています。"</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"バッテリーセーバーの設定を開く"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 19e5fa5..613dc54 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> მოწყობილობა)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth გამორთულია"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"სიკაშკაშე"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ავტოროტაცია"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"როტაცია ჩაკეტილია"</string>
@@ -205,27 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"პარამეტრები"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"დრო"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"მე"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"არ არის დაკავშირებული."</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ქსელი არ არის"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi გამორთულია"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"ეკრანის გადაცემა"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"განათება"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ავტომატურად"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"ფერების შებრუნება"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"ფერთა კორექციის რეჟიმი"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"დამატებითი პარამეტრები"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"დასრულდა"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"დაკავშირებულია"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"მოდემის რეჟიმი"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"წვდომის წერტილი"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"შეტყობინებები"</string>
- <!-- no translation found for quick_settings_flashlight_label (2133093497691661546) -->
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ფანარი"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"მობილური ინტერნეტი"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"მონაცემთა მოხმარება"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Remaining data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Over limit"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> used"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> limit"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
<skip />
<string name="recents_empty_message" msgid="7883614615463619450">"ბოლო აპები არ არის"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"აპლიკაციის შესახებ"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"აპზე ფიქსაცია"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"დატენილია"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"მიმდინარეობს დატენვა"</string>
@@ -235,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"ძიება"</string>
<string name="description_direction_up" msgid="7169032478259485180">"გაასრიალეთ ზემოთ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
<string name="description_direction_left" msgid="7207478719805562165">"გაასრიალეთ მარცხნივ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"არ შემაწუხოთ"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"No interruptions, including alarms and timers"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"შეწყვეტების გარეშე"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"მხოლოდ პრიორიტეტული შეწყვეტები"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"ქვემოთ მითითებულია ნაკლებად სასწრაფო შეტყობინებები"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"შეეხეთ ისევ გასახსნელად"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"გაასრიალეთ ზევით განსაბლოკად"</string>
<string name="phone_hint" msgid="3101468054914424646">"გადაფურცლეთ მარჯვნივ ტელეფონისთვის"</string>
<string name="camera_hint" msgid="5241441720959174226">"კამერისთვის მარცხენა შენაცვლება"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"სანამ ამას გამორთავდეთ"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"სამუდამოდ"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"არცერთი"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"პრიორიტეტი"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"ყველა"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>-ის შეცვლა დასრულებამდე)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"სტუმარი"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ სტუმარი"</string>
@@ -257,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"ბატარეის დამზოგი ჩართულია"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"მოწყობილობის წარმადობა შემცირებულია."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"ბატარეის დამზოგის პარამეტრების გახსნა"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 8270801..95c2319 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ប៊្លូធូស"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ប៊្លូធូស (ឧបករណ៍ <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ប៊្លូធូសបានបិទ"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"មិនមានឧបករណ៍ផ្គូផ្គងដែលអាចប្រើបាន"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ពន្លឺ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"បង្វិលស្វ័យប្រវត្តិ"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"បានចាក់សោការបង្វិល"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"ការកំណត់"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"ពេលវេលា"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"ខ្ញុំ"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"អ្នកប្រើ"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"អ្នកប្រើថ្មី"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"វ៉ាយហ្វាយ"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"មិនបានតភ្ជាប់"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"គ្មានបណ្ដាញ"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"វ៉ាយហ្វាយបានបិទ"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"ចាត់ថ្នាក់អេក្រង់"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"មិនមានបណ្ដាញដែលបានរក្សាទុក"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"ចាត់ថ្នាក់អេក្រង់"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"ការចាត់ថ្នាក់"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"ឧបករណ៍ដែលមិនមានឈ្មោះ"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"ត្រៀមរួចរាល់ដើម្បីចាត់ថ្នាក់"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"មិនមានឧបករណ៍ដែលអាចប្រើបាន"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ពន្លឺ"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ស្វ័យប្រវត្តិ"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"ដាក់បញ្ច្រាសពណ៌"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ការកំណត់ច្រើនទៀត"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"រួចរាល់"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"បានភ្ជាប់"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"កំពុងតភ្ជាប់..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ការភ្ជាប់"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ហតស្ប៉ត"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ការជូនដំណឹង"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ពិល"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"ទិន្នន័យចល័ត"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ការប្រើទិន្នន័យ"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ទិន្នន័យនៅសល់"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"លើសដែនកំណត់"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"បានប្រើ <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"ដែនកំណត់ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ការព្រមាន"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"មិនមានកម្មវិធីថ្មីៗ"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ព័ត៌មានកម្មវិធី"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"ចាក់សោទៅកម្មវិធី"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"បានបញ្ចូលថ្ម"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"កំពុងបញ្ចូលថ្ម"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"ស្វែងរក"</string>
<string name="description_direction_up" msgid="7169032478259485180">"រុញឡើងលើដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
<string name="description_direction_left" msgid="7207478719805562165">"រុញទៅឆ្វេងដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"កុំរំខាន"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"មិនមានការផ្អាក រួមទាំងការជូនដំណឹង និងកម្មវិធីកំណត់ម៉ោង"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"គ្មានការផ្អាក"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"តែការផ្អាកអាទិភាពប៉ុណ្ណោះ"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"ការជូនដំណឹងមិនសូវបន្ទាន់ខាងក្រោម"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ប៉ះម្ដងទៀត ដើម្បីបើក"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"អូសឡើងលើ ដើម្បីដោះសោ"</string>
<string name="phone_hint" msgid="3101468054914424646">"អូសទៅស្ដាំដើម្បីបើកទូរស័ព្ទ"</string>
<string name="camera_hint" msgid="5241441720959174226">"អូសទៅឆ្វេងដើម្បីប្រើម៉ាស៊ីនថត"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"រហូតដល់ពេលអ្នកបិទវា"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"គ្មានកំណត់"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"គ្មាន"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"អាទិភាព"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"ទាំងអស់"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"កំពុងបញ្ចូលថ្ម (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ទើបពេញ)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"ភ្ញៀវ"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ ភ្ញៀវ"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"កម្មវិធីសន្សំថ្មគឺបើក"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"ការអនុវត្តឧបករណ៍ត្រូវបានកាត់បន្ថយ។"</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"បើកការកំណត់កម្មវិធីសន្សំថ្ម"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index d3ae241..2c31766 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"블루투스"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"블루투스(<xliff:g id="NUMBER">%d</xliff:g>개의 기기)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"블루투스 사용 안함"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"밝기"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"자동 회전"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"방향 고정"</string>
@@ -207,26 +209,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"설정"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"시간"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"나"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"연결되어 있지 않음"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"네트워크가 연결되지 않음"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 꺼짐"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"화면 전송"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"밝기"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"자동"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"색상 반전"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"색상 보정 모드"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"설정 더보기"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"완료"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"연결됨"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"테더링"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"핫스팟"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"알림"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"손전등"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"모바일 데이터"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"데이터 사용"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"잔여 데이터"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"한도 초과"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> 사용됨"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"한도: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"최근에 사용한 앱 없음"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"애플리케이션 정보"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"앱에 잠금"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"충전됨"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"충전 중"</string>
@@ -236,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"검색"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 왼쪽으로 슬라이드"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"알림 일시중지"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"방해 금지(알람 및 타이머 포함)"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"모든 알림 차단"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"최우선 알림만 수신"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"아래에 덜 급한 알림 표시"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"다시 탭하여 열기"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"위로 스와이프하여 잠금 해제"</string>
<string name="phone_hint" msgid="3101468054914424646">"전화 기능을 사용하려면 오른쪽으로 스와이프하세요."</string>
<string name="camera_hint" msgid="5241441720959174226">"카메라를 사용하려면 왼쪽으로 스와이프하세요."</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"이 기능을 사용 중지할 때까지"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"무제한"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"수신 안함"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"최우선만 수신"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"모두 수신"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"충전 중(<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> 후 충전 완료)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"손님"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"새 손님 추가"</string>
@@ -258,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"배터리 세이버 사용 중"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"기기의 성능이 저하됩니다."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"배터리 세이버 설정 열기"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 29e4597..5d74e1a 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ອຸປະກອນ)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth ປິດ"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"ບໍ່ມີອຸປະກອນທີ່ສາມາດຈັບຄູ່ໄດ້"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ຄວາມສະຫວ່າງ"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ໝຸນອັດຕະໂນມັດ"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"ລັອກການໝຸນຈໍແລ້ວ"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"ການຕັ້ງຄ່າ"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"ເວລາ"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"ຂ້ອຍ"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"ຜູ່ໃຊ້"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"ຜູ່ໃຊ້ໃໝ່"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ບໍ່ໄດ້ເຊື່ອມຕໍ່"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ບໍ່ມີເຄືອຂ່າຍ"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ປິດ"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"ສົ່ງສັນຍານພາບ"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"ບໍ່ມີເຄືອຂ່າຍທີ່ບັນທຶກໄວ້ທີ່ສາມາດໃຊ້ໄດ້"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"ສົ່ງສັນຍານໜ້າຈໍ"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"ກຳລັງສົ່ງສັນຍານ"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"ອຸປະກອນບໍ່ມີຊື່"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"ພ້ອມສົ່ງສັນຍານແລ້ວ"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"ບໍ່ມີອຸປະກອນທີ່ສາມາດໃຊ້ໄດ້"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ຄວາມແຈ້ງ"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ອັດຕະໂນມັດ"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"ສະລັບສີ"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ການຕັ້ງຄ່າເພີ່ມເຕີມ"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"ແລ້ວໆ"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"ກຳລັງເຊື່ອມຕໍ່..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ການປ່ອນສັນຍານ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ຮັອດສະປອດ"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ການແຈ້ງເຕືອນ"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ໄຟສາຍ"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"ຂໍ້ມູນອິນເຕີເນັດມືຖື"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ການນຳໃຊ້ຂໍ້ມູນ"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ຂໍ້ມູນທີ່ຍັງເຫຼືອ"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"ເກີນຂີດຈຳກັດ"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"ໃຊ້ໄປແລ້ວ <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"ຈຳກັດ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"ຄຳເຕືອນ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"ບໍ່ມີແອັບຯທີ່ຫາກໍໃຊ້"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ຂໍ້ມູນແອັບພລິເຄຊັນ"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ສາກເຕັມແລ້ວ."</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"ກຳລັງສາກໄຟ"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"ຊອກຫາ"</string>
<string name="description_direction_up" msgid="7169032478259485180">"ເລື່ອນຂຶ້ນເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"ເລື່ອນໄປທາງຊ້າຍເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"ຫ້າມລົບກວນ"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"ບໍ່ມີການລົບກວນ ຮວມເຖິງໂມງປຸກ ແລະໂມງຈັບເວລາ"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"ບໍ່ມີການລົບກວນ"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"ການລົບກວນທີ່ສຳຄັນເທົ່ານັ້ນ"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"ການແຈ້ງເຕືອນທີ່ສຳຄັນໜ້ອຍກວ່າຢູ່ດ້ານລຸ່ມ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ແຕະອີກຄັ້ງເພື່ອເປີດ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນຂຶ້ນເພື່ອປົດລັອກ"</string>
<string name="phone_hint" msgid="3101468054914424646">"ປັດຂວາເພື່ອໃຊ້ໂທລະສັບ"</string>
<string name="camera_hint" msgid="5241441720959174226">"ປັດຊ້າຍເພື່ອໃຊ້ກ້ອງ"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າທ່ານຈະປິດ"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"ຢ່າງບໍ່ມີກຳນົດ"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"ບໍ່ມີ"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"ລະດັບຄວາມສຳຄັນ"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"ທັງໝົດ"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"ກຳລັງສາກໄຟ (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ກວ່າຈະເຕັມ)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"ແຂກ"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ ແຂກ"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"ເປີດໃຊ້ໂຕປະຢັດແບັດເຕີຣີແລ້ວ"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"ປະສິດທິພາບຂອງອຸປະກອນຖືກຫຼຸດລົງແລ້ວ."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"ເປີດການຕັ້ງຄ່າໂຕປະຢັດແບັດເຕີຣີ"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 60b806b..e3372a0 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"„Bluetooth“ (<xliff:g id="NUMBER">%d</xliff:g> įreng.)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"„Bluetooth“ išjungta"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Nėra pasiekiamų susietų įrenginių"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Šviesumas"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatinis kaitaliojimas"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Kaitaliojimas užrakintas"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Nustatymai"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Laikas"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Aš"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"Naudotojas"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"Naujas naudotojas"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Neprisijungta"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tinklo nėra"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"„Wi-Fi“ išjungta"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Perduoti ekraną"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Nėra pasiekiamų išsaugotų tinklų"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Perdavimo ekranas"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"Perduodama"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Įrenginys be pavadinimo"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Paruošta perduoti"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Nėra pasiekiamų įrenginių"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Šviesumas"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATINIS"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Pakeisti spalvas"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Daugiau nustatymų"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Atlikta"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Prijungtas"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"Prisijungiama..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Susiejimas"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Viešosios interneto prieigos taškas"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pranešimai"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobiliojo ryšio duomenys"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Duomenų naudojimas"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Likę duomenys"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Viršytas limitas"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Išnaudota: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limitas: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> įspėjimas"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"Nėra naujausių programų"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Programos užrakinimo funkcija"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Įkrautas"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Kraunamas"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Paieška"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Slyskite aukštyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Slyskite į kairę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Netrukdyti"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Jokių pertraukčių, įskaitant signalus ir laikmačius"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Jokių pertraukčių"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Tik prioritetinės pertrauktys"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mažiau skubūs pranešimai toliau"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Palieskite dar kartą, kad atidarytumėte"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Perbraukite aukštyn, kad atrakintumėte"</string>
<string name="phone_hint" msgid="3101468054914424646">"Perbraukite į dešinę, kad galėtumėte skambinti"</string>
<string name="camera_hint" msgid="5241441720959174226">"Perbraukite į kairę, kad būtų įjungtas fotoaparatas"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Kol išjungsite"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Neapibrėžta"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Nėra"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritetas"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Visi"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Kraunama (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> iki visiško įkrovimo)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Svečias"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Svečias"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Akumuliatoriaus tausojimo priemonė įjungta"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Įrenginio našumas sumažintas."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Atidaryti akumuliatoriaus tausojimo priemonės nustatymus"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index e6f28a8..7bfdba8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ierīce(-es))"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth savienojums ir izslēgts."</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Spilgtums"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automātiska pagriešana"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Pagriešana bloķēta"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Iestatījumi"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Laiks"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Es"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nav izveidots savienojums"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nav tīkla"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi ir izslēgts"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Apraides ekrāns"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Spilgtums"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMĀTISKI"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Invertēt krāsas"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Vairāk iestatījumu"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gatavs"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Pievienota"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Piesaiste"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tīklājs"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Paziņojumi"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zibspuldze"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobilie dati"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Datu lietojums"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Atlikušie dati"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Pārsniegts ierobežojums"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Tiek izmantots: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ierobežojums: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Nav nesen izmantotu lietotņu"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informācija par lietojumprogrammu"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"fiksēt lietotni"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulators uzlādēts"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Notiek uzlāde"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Meklēt"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Velciet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Velciet pa kreisi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Netraucēt"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Bez pārtraukumiem, tostarp bez signāliem un taimeriem"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Nepārtraukt"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Tikai prioritārie pārtraukumi"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mazāk steidzami paziņojumi tiek rādīti tālāk"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Pieskarieties vēlreiz, lai atvērtu"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Velciet uz augšu, lai atbloķētu"</string>
<string name="phone_hint" msgid="3101468054914424646">"Lai lietotu tālruni, velciet pa labi."</string>
<string name="camera_hint" msgid="5241441720959174226">"Lai lietotu kameru, velciet pa kreisi."</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Līdz brīdim, kad izslēgsiet"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Uz nenoteiktu laiku"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Nav"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritāte"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Visi"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Notiek uzlāde (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> līdz pilnīgai uzlādei)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Viesis"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+Viesis"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Ieslēgts akumulatora enerģijas taupīšanas režīms"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Ierīces veiktspēja ir pazemināta."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Atvērt akumulatora enerģijas taupīšanas režīma iestatījumus"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 7104bc77..6709392 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Блютүүт"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Блютүүт (<xliff:g id="NUMBER">%d</xliff:g> төхөөрөмж)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Блютүүт унтраалттай"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Хослуулсан төхөөрөмж байхгүй"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Тодрол"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматаар эргэх"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Эргэлтийг түгжсэн"</string>
@@ -205,26 +206,40 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Тохиргоо"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Цаг"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Би"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"Хэрэглэгч"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"Шинэ хэрэглэгч"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Холбогдоогүй"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Сүлжээгүй"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi унтарсан"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Дамжуулах дэлгэц"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Хадгалагдсан сүлжээ байхгүй"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Дамжуулах дэлгэц"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"Дамжуулж байна"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Нэргүй төхөөрөмж"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Дамжуулахад бэлэн"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Төхөөрөмж байхгүй"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Тодрол"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОМАТ"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Өнгийг урвуулах"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Өнгө залруулах горим"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Өөр тохиргоо"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
- <skip />
+ <string name="quick_settings_done" msgid="3402999958839153376">"Дууссан"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Холбогдсон"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"Холбогдож байна..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Модем болгох"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Сүлжээний цэг"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Мэдэгдэл"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Гар чийдэн"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Үүрэн дата"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Дата ашиглалт"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Үлдсэн дата"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Хязгаараас хэтэрсэн"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ашигласан"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> хязгаар"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> анхааруулга"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"Сүүлд ашигласан апп байхгүй"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Аппликешны мэдээлэл"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Апп-дотор-түгжих"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Цэнэглэгдсэн"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Цэнэглэж байна"</string>
@@ -234,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Хайх"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-г гулсуулах."</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> хийх зүүнлүү гулсуулах."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Бүү саад бол"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Сэрүүлэг, цаг тоологчийг оруулан тасалдахгүй"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Ямар ч тасалдалгүй"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Зөвхөн нэн тэргүүний тасалдалд"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Яаралтай биш мэдэгдлүүдийг доор"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Нээхийн тулд дахин товшино уу"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string>
<string name="phone_hint" msgid="3101468054914424646">"Утас гаргахын тулд баруун шударна уу"</string>
<string name="camera_hint" msgid="5241441720959174226">"Камер гаргахын тулд зүүн шударна уу"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Таныг унтраах хүртэл"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Тодорхойгүй"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Хоосон"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Нэн тэргүүний"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Бүгд"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Цэнэглэж байна (дүүргэхэд <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Зочин"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Зочин"</string>
@@ -256,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Батерей хэмнэгч асаалттай"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Төхөөрөмжийн ажиллагааг бууруулсан."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Батерей хэмнэгчийн тохиргоог нээх"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 30940cd..f2f3ef9 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Peranti)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Dimatikan"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Kecerahan"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Autoputar"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Putaran dikunci"</string>
@@ -205,27 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Tetapan"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Masa"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Saya"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Tidak Disambungkan"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Tiada Rangkaian"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Dimatikan"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Skrin Cast"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kecerahan"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Terbalikkan warna"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Mod pembetulan warna"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Lagi tetapan"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Selesai"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Disambungkan"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Penambatan"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tempat liputan"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
- <!-- no translation found for quick_settings_flashlight_label (2133093497691661546) -->
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampu suluh"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Data selular"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Penggunaan data"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Baki data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Melebihi had"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> digunakan"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> had"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
<skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Tiada apl terbaharu"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Maklumat Aplikasi"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"kunci ke apl"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Sudah dicas"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Mengecas"</string>
@@ -235,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Carian"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Luncurkan ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Luncurkan ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Jangan ganggu"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Tiada gangguan, termasuk penggera dan pemasa"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Tiada gangguan"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Gangguan keutamaan sahaja"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Pemberitahuan kurang penting di bawah"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ketik lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Leret ke atas untuk membuka kunci"</string>
<string name="phone_hint" msgid="3101468054914424646">"Leret ke kanan untuk telefon"</string>
<string name="camera_hint" msgid="5241441720959174226">"Leret ke kiri untuk kamera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Sehingga anda matikan"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Selama-lamanya"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Tiada"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Keutamaan"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Semua"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Mengecas (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> sehingga penuh)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Tetamu"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Tetamu"</string>
@@ -257,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Penjimat bateri dihidupkan"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Prestasi peranti dikurangkan."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Buka tetapan penjimat bateri"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 93a3848..bde8c38 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth er slått av"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Lysstyrke"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotér automatisk"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotasjonen er låst"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Innstillinger"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Tidspunkt"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Meg"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ikke tilkoblet"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ingen nettverk"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi er av"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Cast skjermen"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Lysstyrke"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inverter farger"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Flere innstillinger"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Ferdig"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Tilkoblet"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tilknytning"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Wi-Fi-sone"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Varsler"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lommelykt"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobildata"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Databruk"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Gjenværende data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Over grensen"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> brukt"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Grense på <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Ingen nylige apper"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lås til app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Oppladet"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Lader"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Søk"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Dra opp for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Dra til venstre for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Ikke forstyrr"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Ingen forstyrrelser, inkludert alarmer og tidtakere"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Ingen forstyrrelser"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Bare prioriterte forstyrrelser"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre presserende varsler nedenfor"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Trykk på nytt for å åpne"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Sveip oppover for å låse opp"</string>
<string name="phone_hint" msgid="3101468054914424646">"Sveip mot høyre for å åpne telefonen"</string>
<string name="camera_hint" msgid="5241441720959174226">"Sveip mot venstre for å åpne kameraet"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Inntil du slår av funksjonen"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"På ubestemt tid"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Ingen"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritet"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Lader (fulladet om <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gjest"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Gjest"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Batterisparing er på"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Enhetsytelsen er redusert."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Åpen innstilling for batterisparing"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 9f08914..6bd261f 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> apparaten)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth uit"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Geen gekoppelde apparaten beschikbaar"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Helderheid"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatische rotatie"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotatie vergrendeld"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Instellingen"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Tijd"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ik"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"Gebruiker"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"Nieuwe gebruiker"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wifi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Niet verbonden"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Geen netwerk"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wifi uit"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Scherm casten"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Geen opgeslagen netwerken beschikbaar"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Scherm casten"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"Casten"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Naamloos apparaat"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Klaar om te casten"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Geen apparaten beschikbaar"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Helderheid"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATISCH"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Kleuren omkeren"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Meer instellingen"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gereed"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Verbonden"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"Verbinding maken…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Meldingen"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Zaklamp"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobiele gegevens"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Gegevensgebruik"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Resterende gegevens"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limiet overschreden"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> gebruikt"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limiet van <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Waarschuwing voor <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"Geen recente apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"app-slot"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opgeladen"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Opladen"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Zoeken"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Veeg omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Veeg naar links voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Niet storen"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Geen onderbrekingen, waaronder alarmen en timers"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Geen onderbrekingen"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Alleen prioriteitsonderbrekingen"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Minder urgente meldingen onderaan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tik nogmaals om te openen"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Veeg omhoog om te ontgrendelen"</string>
<string name="phone_hint" msgid="3101468054914424646">"Veeg naar rechts voor telefoon"</string>
<string name="camera_hint" msgid="5241441720959174226">"Veeg naar links voor camera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Totdat u dit uitschakelt"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Voor onbepaalde tijd"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Geen"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioriteit"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Alle"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Opladen (vol over <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gast"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Gast"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Accubesparing is ingeschakeld"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"De prestaties van het apparaat worden beperkt."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Instellingen voor Accubesparing openen"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 8d8b9f7..6320024 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (urządzenia: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth wył."</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Brak dostępnych sparowanych urządzeń"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jasność"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Autoobracanie"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Obracanie zablokowane"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Ustawienia"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Godzina"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ja"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"Użytkownik"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"Nowy użytkownik"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Brak połączenia"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Brak sieci"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wyłącz Wi-Fi"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Ekran Cast"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Brak dostępnych zapisanych sieci"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Przesyłaj ekran"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"Przesyłam"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Urządzenie bez nazwy"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Wszystko gotowe do przesyłania"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Brak dostępnych urządzeń"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jasność"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Odwróć kolory"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Więcej ustawień"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Gotowe"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Połączono"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"Łączę..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Powiązanie"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Punkt dostępu"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Powiadomienia"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Latarka"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Transmisja danych komórkowych"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Użycie danych"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Pozostały limit"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Przekroczono limit"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Wykorzystano <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limit <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ostrzeżenie: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"Brak ostatnio uruchomionych aplikacji"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacje o aplikacji"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"zablokuj na aplikacji"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Naładowana"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Ładuje się"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Szukaj"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Przesuń w górę: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Przesuń w lewo: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Nie przeszkadzać"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Żadnego przeszkadzania, w tym alarmów i minutników"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Bez przerw"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Tylko priorytetowe przerwy"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Poniżej widać mniej pilne powiadomienia"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Kliknij ponownie, by otworzyć"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Przesuń w górę, by odblokować"</string>
<string name="phone_hint" msgid="3101468054914424646">"Przesuń w prawo, by przełączyć się na telefon"</string>
<string name="camera_hint" msgid="5241441720959174226">"Przesuń w lewo, by przełączyć się na aparat"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Dopóki nie wyłączysz"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Na czas nieokreślony"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Brak"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Priorytet"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Wszystkie"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Ładuje się (pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gość"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Dodaj gościa"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Oszczędzanie baterii jest włączone"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Urządzenie działa z ograniczoną szybkością."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Otwórz ustawienia oszczędzania baterii"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index ee93d43..7063854 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desat."</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brilho"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotação automática"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotação bloqueada"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Definições"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Eu"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Não Ligado"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sem Rede"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Desligado"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Transmitir ecrã"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brilho"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inverter cores"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mais definições"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Concluído"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ligado"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Associação"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Dados de rede móvel"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilização de dados"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dados restantes"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Acima do limite"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilizado(s)"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limite de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Nenhuma aplicação recente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloquear numa aplicação"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"A carregar"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Deslize para cima para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Deslize para a esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Não incomodar"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Sem interrupções, incluindo alarmes e temporizadores"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Sem interrupções"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Apenas interrupções com prioridade"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslizar rapidamente com o dedo para cima para desbloquear"</string>
<string name="phone_hint" msgid="3101468054914424646">"Deslize rapidamente para a direita para aceder ao telemóvel"</string>
<string name="camera_hint" msgid="5241441720959174226">"Deslize rapidamente para a esquerda para aceder à câmara"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Até que o utilizador desative"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Nenhum"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridade"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"A carregar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até à carga máxima)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Convidado"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Convidado"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"A poupança de bateria está ligada"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"O desempenho do dispositivo é reduzido."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Abrir as definições de poupança de bateria"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index f915002..f148336 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivos)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth desativado"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brilho"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotação automática"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotação bloqueada"</string>
@@ -207,27 +209,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Configurações"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Hora"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Eu"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Não conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Sem rede"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desligado"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Transmitir tela"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brilho"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inverter cores"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Modo de correção de cor"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mais configurações"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Concluído"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Conectado"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Ponto de acesso"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
- <!-- no translation found for quick_settings_flashlight_label (2133093497691661546) -->
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanterna"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Dados da rede celular"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Uso de dados"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dados restantes"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limite excedido"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Usados: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limite: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
<skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Nenhum app recente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do aplicativo"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"bloquear no app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Carregando"</string>
@@ -237,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para cima."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para a esquerda."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Não perturbe"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Sem interrupções, incluindo alarmes e temporizadores"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Sem interrupções"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Apenas interrupções prioritárias"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
<string name="phone_hint" msgid="3101468054914424646">"Deslize para a esquerda para usar o telefone"</string>
<string name="camera_hint" msgid="5241441720959174226">"Deslize para a esquerda para usar a câmera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Até você desativar"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Indefinidamente"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Nenhum"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioridade"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Tudo"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Carregando (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> até concluir)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Convidado"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ convidado"</string>
@@ -259,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"A Economia de bateria está ativada"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"O desempenho do dispositivo foi reduzido."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Abrir configurações de economia de bateria"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 342b49d..aa09ce6 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispozitive)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth dezactivat"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminozitate"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotire automată"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotire blocată"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Setări"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Ora"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Eu"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Neconectat"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Nicio reţea"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi deconectat"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Proiectați ecranul"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminozitate"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAT"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Inversați culori"</string>
@@ -217,13 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mai multe setări"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Terminat"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Conectat"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificări"</string>
- <!-- no translation found for quick_settings_flashlight_label (2133093497691661546) -->
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lanternă"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Date mobile"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Utilizarea datelor"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Date rămase"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Peste limită"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilizați"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limită de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
<skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Nicio aplicație recentă"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"blocare la aplicație"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"S-a încărcat"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Se încarcă"</string>
@@ -233,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Căutaţi"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Glisaţi spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Nu deranjaţi"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Fără întreruperi, inclusiv alarme si temporizatoare"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Fără întreruperi"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Numai întreruperi cu prioritate"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificările mai puțin urgente mai jos"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Atingeți din nou pentru a deschide"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Glisați în sus pentru a debloca"</string>
<string name="phone_hint" msgid="3101468054914424646">"Glisați la dreapta pentru a acesa telefonul"</string>
<string name="camera_hint" msgid="5241441720959174226">"Glisați la stânga pentru a accesa camera foto"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Până la dezactivare"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Nedefinit"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Niciuna"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritate"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Toate"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Se încarcă (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> până la finalizare)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Invitat"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Invitat"</string>
@@ -255,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Economisirea bateriei este activată"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Performanța dispozitivului s-a redus."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Deschideți setările pentru economisirea bateriei"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 310edc6..bca7fdc 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth выкл."</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яркость"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоповорот"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Автоповорот отключен"</string>
@@ -207,26 +209,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Настройки"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Время"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Вы"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Нет соединения"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нет сети"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi выкл."</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Беспроводной монитор"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яркость"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОНАСТРОЙКА"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Инвертировать"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Коррекция цвета"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Дополнительные настройки"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Подключено"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступа"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Уведомления"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Фонарик"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Передача данных"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Передача данных"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Остается данных"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Ограничение превышено"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Использовано: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ограничение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Ничего не найдено."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Блокировать в приложении"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Батарея заряжена"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Зарядка батареи"</string>
@@ -236,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Поиск"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Проведите влево, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Не беспокоить"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Никаких будильников, таймеров и других сигналов"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Не беспокоить"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Только приоритетные оповещения"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Показать менее важные оповещения"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Нажмите ещё раз, чтобы открыть"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Для разблокировки проведите пальцем по экрану"</string>
<string name="phone_hint" msgid="3101468054914424646">"Чтобы открыть приложение \"Телефон\", пролистните вправо"</string>
<string name="camera_hint" msgid="5241441720959174226">"Чтобы включить камеру, пролистните влево"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Пока я не отключу"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Не определено"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"–"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Приоритет"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Все"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Зарядка батареи (осталось <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Гость"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Добавить гостя"</string>
@@ -258,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Включен режим энергосбережения"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Производительность устройства снижена."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Открыть настройки режима энергосбережения"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 7d06196..e0c334c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Rozhranie Bluetooth (počet zariadení: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Rozhranie Bluetooth je vypnuté"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Jas"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Automatické otáčanie"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Otáčanie je uzamknuté"</string>
@@ -207,11 +209,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Nastavenia"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Čas"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ja"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Nepripojené"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Žiadna sieť"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Sieť Wi-Fi je vypnutá"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Vzdialená obrazovka"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Jas"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Invertovať farby"</string>
@@ -219,12 +236,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Ďalšie nastavenia"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Hotovo"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Pripojené"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Zdieľanie dátového pripojenia"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Upozornenia"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Baterka"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobilné dáta"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Využitie dát"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Zostávajúce údaje"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limit bol prekročený"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Využité: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Limit: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Žiadne nedávne aplikácie"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informácie o aplikácii"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"Uzamknutie v aplikácii"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabitá"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Nabíja sa"</string>
@@ -234,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Vyhľadávanie"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Prejdite prstom nahor: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Prejdite prstom doľava: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Nerušiť"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Žiadne prerušenia vrátane budíkov a časovačov"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Žiadne prerušenia"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Iba prioritné prerušenia"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Menej naliehavé upozornenia sa nachádzajú nižšie"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Upozornenie otvoríte opätovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Zariadenie odomknete prejdením prstom nahor"</string>
<string name="phone_hint" msgid="3101468054914424646">"Telefón otvoríte prejdením prstom doľava"</string>
<string name="camera_hint" msgid="5241441720959174226">"Fotoaparát otvoríte prejdením prstom doľava"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Dokým túto funkciu nevypnete"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Natrvalo"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Žiadne"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Priorita"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Všetky"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nabíja sa (úplné nabitie o <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Hosť"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Pridať hosťa"</string>
@@ -256,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Šetrič batérie je zapnutý"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Výkonnosť zariadenia sa znížila."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Otvorte nastavenia šetriča batérie"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g> %%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 438286d..7e0cc28 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (št. naprav: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth izklopljen"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Svetlost"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Samodejno sukanje"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Sukanje je zaklenjeno"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Nastavitve"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Čas"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Jaz"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Povezava ni vzpostavljena"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ni omrežja"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi izklopljen"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Zaslon za predvajanje"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Svetlost"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"SAMODEJNO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Obrni barve"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Več nastavitev"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Končano"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Povezava je vzpostavljena"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internet prek mobilne naprave"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Dostopna točka"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obvestila"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Svetilka"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Prenos podatkov v mobilnih omrežjih"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Poraba podatkov"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Preostala količina podatkov"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Omejitev prekoračena"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Porabljeno: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Omejitev: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Ni nedavnih aplikacij"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Podatki o aplikaciji"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"zakleni v aplikacijo"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulator napolnjen"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Polnjenje"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Iskanje"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Povlecite navzgor za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Povlecite v levo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Ne moti"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Brez prekinitev, vključno z alarmi in odštevalniki časa"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Brez prekinitev"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Samo prednostne prekinitve"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Manj nujna obvestila spodaj"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Znova se dotaknite, da odprete"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Povlecite, da odklenete"</string>
<string name="phone_hint" msgid="3101468054914424646">"Povlecite v desno za telefon"</string>
<string name="camera_hint" msgid="5241441720959174226">"Povlecite v levo za fotoaparat"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Dokler tega ne izklopite"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Za nedoločen čas"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Nič"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prednost"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Vse"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Polnjenje (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> do napolnjenosti)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gost"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Dodajanje gosta"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Varčevanje z energijo akumulatorja je vklopljeno"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Zmogljivost delovanja naprave je zmanjšana."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Odpri nastavitve varčevanja z energijo akumulatorja"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 5a06a52..9f3030f 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> уређаја)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth искључен"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Осветљеност"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Аутоматска ротација"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Ротација је закључана"</string>
@@ -205,26 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Подешавања"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Време"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ја"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Веза није успостављена"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Нема мреже"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi је искључен"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Пребацивање екрана"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Осветљеност"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АУТОМАТСКА"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Обрни боје"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Режим корекције боје"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Још подешавања"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Повезан"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Повезивање"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Хотспот"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Обавештења"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Лампа"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Подаци за мобилне уређаје"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Потрошња података"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Преостала количина података"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Преко ограничења"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Искористили сте <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Ограничење од <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Нема недавних апликација"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"закључај апликацију"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Пуњење"</string>
@@ -234,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Претрага"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Превуците нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Превуците улево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Не узнемиравај"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Без прекида, укључујући аларме и тајмере"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Без прекида"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Само приоритетни прекиди"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Мање хитна обавештења су у наставку"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Додирните поново да бисте отворили"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Превуците нагоре да бисте откључали"</string>
<string name="phone_hint" msgid="3101468054914424646">"Превуците удесно за телефон"</string>
<string name="camera_hint" msgid="5241441720959174226">"Превуците улево за камеру"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Док не искључите"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Бесконачно"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Ниједан"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Приоритет"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Све"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Пуњење (пун је за <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Гост"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Гост"</string>
@@ -256,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Штедња батерије је укључена"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Перформансе уређаја су умањене."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Отворите подешавања Штедње батерије"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 365d7ba..37ca22a 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> enheter)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth av"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ljusstyrka"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Rotera automatiskt"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Rotationen har låsts"</string>
@@ -205,11 +207,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Inställningar"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Tid"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Jag"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ej ansluten"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Inget nätverk"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi av"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Casta skärmen"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ljusstyrka"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Invertera färger"</string>
@@ -217,12 +234,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Fler inställningar"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Klart"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ansluten"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internetdelning"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Trådlös surfzon"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Aviseringar"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Ficklampa"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Mobildata"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Dataanvändning"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Återstående data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Över gräns"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> används"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Gräns: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Inga aktiva appar"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformation"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lås till app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laddat"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Laddar"</string>
@@ -232,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Sök"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Dra uppåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Dra åt vänster för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Stör ej"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Inga avbrott, inklusive alarm och timer"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Inga avbrott"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Endast prioriterade avbrott"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Mindre brådskande aviseringar nedan"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Tryck igen för att öppna"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Dra uppåt om du vill låsa upp"</string>
<string name="phone_hint" msgid="3101468054914424646">"Dra åt höger om du vill visa telefonen"</string>
<string name="camera_hint" msgid="5241441720959174226">"Dra åt vänster om du vill visa kameran"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Tills du inaktiverar detta"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"För alltid"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Ingen"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prioritet"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Alla"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Laddar (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> tills batteriet är fulladdat)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Gäst"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Lägg till gäst"</string>
@@ -254,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Batterisparläget har aktiverats"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Enhetens prestanda har minskats."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Öppna inställningarna för batterisparläget"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 942c332..f1d53c5 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -189,6 +189,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (Vifaa <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Imezimwa"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ung\'avu"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Zungusha kiotomatiki"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Mzunguko umefungwa"</string>
@@ -203,11 +205,26 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Mipangilio"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Muda"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Mimi"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Haijaunganishwa"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Hakuna Mtandao"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Imezimwa"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Utumaji wa Skrini"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ung\'avu"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Pindua rangi"</string>
@@ -215,12 +232,23 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mipangilio zaidi"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Imemaliza"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Imeunganishwa"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
+ <skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Kusambaza mtandao"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Mtandao-hewa"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Arifa"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Kurunzi"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Data ya simu ya mkononi"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Matumizi ya data"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Data iliyosalia"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Imezidi kikomo"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> imetumika"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"kikomo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Hakuna programu za karibuni"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lazimisha kutumia programu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Betri imejaa"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Inachaji"</string>
@@ -230,14 +258,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Tafuta"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Sogeza juu kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Sogeza kushoto kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Usisumbue"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Hakuna usumbufu, ikiwa ni pamoja na kengele na vipima muda"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Hakuna katizo"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Katizo za kipaumbele pekee"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>+"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Arifa zisizo za dharura sana ziko hapo chini"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Gonga tena ili ufungue"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Telezesha kidole ili ufungue"</string>
<string name="phone_hint" msgid="3101468054914424646">"Telezesha kidole kulia ili ufikie simu"</string>
<string name="camera_hint" msgid="5241441720959174226">"Telezesha kidole kushoto ili ufikie kamera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Hadi utakapozima hili"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Bila kikomo"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Hamna"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Kipaumbele"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Zote"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Inachaji ( <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hadi ijae)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Aliyealikwa"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Aliyealikwa"</string>
@@ -252,4 +285,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Kiokoa betri kimewashwa"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Utendaji wa kifaa umepunguzwa."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Fungua mipangilio ya hali inayookoa betri"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 20c4bf4..338102b 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -21,7 +21,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7164937344850004466">"ส่วนติดต่อผู้ใช้ของระบบ"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"ล้างข้อมูล"</string>
- <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"นำออกจากรายการ"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"ลบจากรายการ"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"ข้อมูลแอปพลิเคชัน"</string>
<string name="status_bar_no_recent_apps" msgid="6576392951053994640">"ไม่มีแอปพลิเคชันล่าสุด"</string>
<string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ปิดแอปพลิเคชันล่าสุด"</string>
@@ -150,7 +150,7 @@
<string name="accessibility_tty_enabled" msgid="4613200365379426561">"เปิดใช้งาน TeleTypewriter อยู่"</string>
<string name="accessibility_ringer_vibrate" msgid="666585363364155055">"เสียงเรียกเข้าแบบสั่น"</string>
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"เสียงเรียกเข้าแบบปิดเสียง"</string>
- <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกนำออกไปแล้ว"</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ถูกลบไปแล้ว"</string>
<string name="accessibility_notification_dismissed" msgid="854211387186306927">"ปิดการแจ้งเตือนแล้ว"</string>
<string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"หน้าต่างแจ้งเตือน"</string>
<string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"การตั้งค่าด่วน"</string>
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"บลูทูธ"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"บลูทูธ (<xliff:g id="NUMBER">%d</xliff:g> อุปกรณ์)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ปิดบลูทูธ"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"ความสว่าง"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"หมุนอัตโนมัติ"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"ล็อกการหมุน"</string>
@@ -205,26 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"การตั้งค่า"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"เวลา"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"ฉัน"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"WiFi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ไม่ได้เชื่อมต่อ"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ไม่มีเครือข่าย"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"ปิด WiFi"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"ส่งหน้าจอ"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ความสว่าง"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"อัตโนมัติ"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"สลับสี"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"โหมดการแก้ไขสี"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"การตั้งค่าเพิ่มเติม"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"เสร็จสิ้น"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"เชื่อมต่อ"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"การปล่อยสัญญาณ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ฮอตสปอต"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"การแจ้งเตือน"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ไฟฉาย"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"ข้อมูลมือถือ"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"การใช้ข้อมูล"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ข้อมูลที่เหลืออยู่"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"เกินขีดจำกัด"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"ใช้ไปแล้ว <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"ขีดจำกัด <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"ไม่มีแอปล่าสุด"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ข้อมูลแอปพลิเคชัน"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"การล็อกแอป"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"ชาร์จแล้ว"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"กำลังชาร์จ"</string>
@@ -234,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"ค้นหา"</string>
<string name="description_direction_up" msgid="7169032478259485180">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
<string name="description_direction_left" msgid="7207478719805562165">"เลื่อนไปทางซ้ายเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"ห้ามรบกวน"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"ไม่มีการรบกวน รวมถึงเสียงปลุกและนาฬิกาจับเวลา"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"ไม่มีการรบกวน"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"เฉพาะเรื่องสำคัญเท่านั้น"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"การแจ้งเตือนที่เร่งด่วนน้อยด้านล่าง"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"แตะอีกครั้งเพื่อเปิด"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"กวาดขึ้นเพื่อปลดล็อก"</string>
<string name="phone_hint" msgid="3101468054914424646">"กวาดไปทางขวาเพื่อใช้โทรศัพท์"</string>
<string name="camera_hint" msgid="5241441720959174226">"กวาดไปทางซ้ายเพื่อใช้กล้องถ่ายรูป"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"จนกว่าคุณจะปิดฟังก์ชันนี้"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"ไม่มีกำหนด"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"ไม่มี"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"สำคัญ"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"ทั้งหมด"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"กำลังชาร์จ (อีก <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> เต็ม)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"ผู้เข้าร่วม"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ ผู้เข้าร่วม"</string>
@@ -256,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"เปิดโหมดประหยัดแบตเตอรี่อยู่"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"ประสิทธิภาพการทำงานของอุปกรณ์ลดลง"</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"เปิดการตั้งค่าโหมดประหยัดแบตเตอรี่"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d56ae72..2bfa9c0 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> (na) Device)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Naka-off ang Bluetooth"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Awtomatikong i-rotate"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Naka-lock ang pag-ikot"</string>
@@ -205,26 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Mga Setting"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Oras"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ako"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Hindi Nakakonekta"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Walang Network"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Naka-off ang Wi-Fi"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"I-cast ang screen"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"I-invert ang mga kulay"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Mode ng pagtatama ng kulay"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Marami pang setting"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Tapos na"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Nakakonekta"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Nagte-tether"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Mga Notification"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Flashlight"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Cellular data"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Paggamit ng data"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Natitirang data"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Lumampas sa limitasyon"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> ang nagamit"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ang limitasyon"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Walang kamakailang mga app"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Impormasyon ng Application"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"lock to app"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nasingil na"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Nagcha-charge"</string>
@@ -234,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Maghanap"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Mag-slide pataas para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Mag-slide pakaliwa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Huwag istorbohin"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Walang mga pagkaantala, kabilang ang mga alarm at timer"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Walang mga paggambala"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Mga may priyoridad na paggambala lang"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Nasa ibaba ang mga notification na hindi masyadong mahalaga"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"I-tap ulit upang buksan"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Mag-swipe pataas upang i-unlock"</string>
<string name="phone_hint" msgid="3101468054914424646">"Mag-swipe pakanan para sa telepono"</string>
<string name="camera_hint" msgid="5241441720959174226">"Mag-swipe pakaliwa para sa camera"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Hanggang sa i-off mo ito"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Walang tiyak na katapusan"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Wala"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Prayoridad"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Lahat"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Nagtsa-charge (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> hanggang mapuno)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Bisita"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Bisita"</string>
@@ -256,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Naka-on ang tagatipid ng baterya"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Binawasan ang pagganap ng device."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Buksan ang mga setting ng tagatipid ng baterya"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index e20b7d7..f199a52 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Cihaz)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Kapalı"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Parlaklık"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Otomatik döndür"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Döndürme kilitlendi"</string>
@@ -205,26 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Ayarlar"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Saat"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Ben"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Kablosuz"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Bağlı Değil"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ağ yok"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Kablosuz Kapalı"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Ekranı yayınla"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Parlaklık"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATİK"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Renkleri çevir"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Renk düzeltme modu"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Diğer ayarlar"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Bitti"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Bağlı"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirimler"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Fener"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Hücresel veriler"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Veri kullanımı"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Kalan veri"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Sınır aşıldı"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> kullanıldı"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Sınır: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Yakın zamanda kullanılan uygulama yok"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Uygulama Bilgileri"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"uygulamaya kilitle"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ödeme alındı"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Şarj oluyor"</string>
@@ -234,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Ara"</string>
<string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı kaydırın."</string>
<string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sola kaydırın."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Rahatsız etmeyin"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Alarmlar ve zamanlayıcılar dahil kesinti yok"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Kesinti yok"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Sadece öncelikli kesintiler"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Daha az acil bildirimler aşağıdadır"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Açmak için tekrar hafifçe vurun"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Kilidi açmak için hızlıca yukarı kaydırın"</string>
<string name="phone_hint" msgid="3101468054914424646">"Telefon için sağa kaydırın"</string>
<string name="camera_hint" msgid="5241441720959174226">"Kamera için sola kaydırın"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Siz bunu kapatana kadar"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Süresiz"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Yok"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Öncelik"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Tümü"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Şarj oluyor (tamamen dolmasına <xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> kaldı)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Misafir"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Misafir"</string>
@@ -256,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Pil tasarrufu açık"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Cihazın performansı düşürüldü."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Pil tasarrufu ayarlarını aç"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"%%<xliff:g id="LEVEL">%d</xliff:g>"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 80c7543..65b2b09 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (пристроїв: <xliff:g id="NUMBER">%d</xliff:g>)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth вимкнено"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Немає спарених пристроїв"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Яскравість"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Автоматичне обертання"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Обертання заблоковано"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Налаштування"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Час"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Я"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"Користувач"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"Новий користувач"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Не під’єднано."</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Немає мережі"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi вимкнено"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Транслювати екран"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Немає збережених мереж"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Транслювати екран"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"Трансляція"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Пристрій без назви"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Можна транслювати"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Немає пристроїв"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Яскравість"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Інвертувати кольори"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Більше налаштувань"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Готово"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Під’єднано"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"З’єднання…"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступу"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Сповіщення"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Світловий сигнал"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Мобільні дані"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Використання даних"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Залишилося даних"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Обмеження перевищено"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Використовується: <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Обмеження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Застереження: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"Немає останніх додатків"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Інформація про додаток"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"блокування в додатку"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заряджено"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Заряджається"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Не турбувати"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Без будильників, таймерів та інших сигналів"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Без сповіщень"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Лише пріоритетні сповіщення"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Менше термінових сповіщень нижче"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Торкніться знову, щоб відкрити"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Проведіть пальцем угору, щоб розблокувати"</string>
<string name="phone_hint" msgid="3101468054914424646">"Проведіть пальцем праворуч, щоб скористатися телефоном"</string>
<string name="camera_hint" msgid="5241441720959174226">"Проведіть пальцем ліворуч, щоб скористатися камерою"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Доки ви не вимкнете"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Без обмежень"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Немає"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Пріоритетні"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Усі"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Заряджання (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> до повного зарядження)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Гість"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"Додати гостя"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Режим заощадження заряду акумулятора ввімкнено"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Продуктивність пристрою знижено."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Відкрийте налаштування режиму заощадження заряду акумулятора"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 34cb82e..73255c4 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -80,7 +80,7 @@
<string name="installer_cd_button_title" msgid="2312667578562201583">"Cài đặt ư.d Truyền tệp của Android dành cho Mac"</string>
<string name="accessibility_back" msgid="567011538994429120">"Quay lại"</string>
<string name="accessibility_home" msgid="8217216074895377641">"Trang chủ"</string>
- <string name="accessibility_menu" msgid="316839303324695949">"Trình đơn"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
<string name="accessibility_recent" msgid="8571350598987952883">"Ứng dụng gần đây"</string>
<string name="accessibility_search_light" msgid="1103867596330271848">"Tìm kiếm"</string>
<string name="accessibility_camera_button" msgid="8064671582820358152">"Máy ảnh"</string>
@@ -191,6 +191,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> thiết bị)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Đã tắt Bluetooth"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Độ sáng"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Tự động xoay"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Khóa xoay"</string>
@@ -205,26 +207,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Cài đặt"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Thời gian"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Tôi"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Chưa được kết nối"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Không có mạng nào"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Tắt Wi-Fi"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Màn hình truyền"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Độ sáng"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Đảo ngược màu"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"Chế độ hiệu chỉnh màu sắc"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"Cài đặt khác"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"Xong"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"Đã kết nối"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn nháy"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Dữ liệu di động"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Sử dụng dữ liệu"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dữ liệu còn lại"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Vượt quá giới hạn"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"Đã sử dụng <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Giới hạn <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"Không có ứng dụng nào gần đây"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Thông tin ứng dụng"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"khóa trong ứng dụng"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Đã sạc"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Đang sạc"</string>
@@ -234,14 +260,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Tìm kiếm"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Trượt lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Trượt sang trái để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Không làm phiền"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Không có gián đoạn, bao gồm báo thức và bộ hẹn giờ"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Không có gián đoạn nào"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Chỉ các gián đoạn ưu tiên"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Thông báo ít khẩn cấp hơn bên dưới"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Nhấn lại để mở"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Vuốt lên để mở khóa"</string>
<string name="phone_hint" msgid="3101468054914424646">"Vuốt sang phải để mở điện thoại"</string>
<string name="camera_hint" msgid="5241441720959174226">"Vuốt sang trái để mở máy ảnh"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Cho đến khi bạn tắt tính năng này"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Không giới hạn"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Không có"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Ưu tiên"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Tất cả"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Đang sạc (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> cho đến khi đầy)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Khách"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Khách"</string>
@@ -256,4 +287,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Trình tiết kiệm pin đang bật"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Hiệu suất của thiết bị đã giảm."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Mở cài đặt trình tiết kiệm pin"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index a5bbde1..e478932 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"蓝牙"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"蓝牙(<xliff:g id="NUMBER">%d</xliff:g> 台设备)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"蓝牙:关闭"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"自动旋转"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"屏幕方向:锁定"</string>
@@ -207,27 +209,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"设置"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"时间"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"我"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"WLAN"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未连接"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"无网络"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"WLAN:关闭"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"投射屏幕"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"反色"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"颜色校正模式"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"更多设置"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"完成"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"已连接"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"网络共享"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"热点"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
- <!-- no translation found for quick_settings_flashlight_label (2133093497691661546) -->
+ <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"手电筒"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"移动数据网络"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"数据流量消耗"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩余流量"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"超出上限"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"已使用<xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限为<xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
<skip />
<string name="recents_empty_message" msgid="7883614615463619450">"最近没有用过任何应用"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"应用信息"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"开启单应用模式"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"充电完成"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"正在充电"</string>
@@ -237,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"搜索"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
<string name="description_direction_left" msgid="7207478719805562165">"向左滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"勿扰"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"禁止打扰(包括闹钟和计时器)"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"禁止打扰"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"仅限优先打扰内容"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"不太紧急的通知会显示在下方"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次点按即可打开"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上滑动即可解锁"</string>
<string name="phone_hint" msgid="3101468054914424646">"向右滑动可打开拨号界面"</string>
<string name="camera_hint" msgid="5241441720959174226">"向左滑动可打开相机"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"直到您将其关闭"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"无限期"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"无"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"优先"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"正在充电(还需<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>才能充满)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"访客"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"添加新访客"</string>
@@ -259,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"节电助手已开启"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"设备性能已减降。"</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"打开节电助手设置"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK-land/strings.xml b/packages/SystemUI/res/values-zh-rHK-land/strings.xml
index 8d55df4..df1fc39 100644
--- a/packages/SystemUI/res/values-zh-rHK-land/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK-land/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="toast_rotation_locked" msgid="7609673011431556092">"屏幕現已鎖定為橫向模式"</string>
+ <string name="toast_rotation_locked" msgid="7609673011431556092">"螢幕現已鎖定為橫向模式"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 30ff7c4..4bd3d1b 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -34,15 +34,15 @@
<string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
<string name="battery_low_title" msgid="6456385927409742437">"電量低"</string>
<string name="battery_low_percent_format" msgid="1077244949318261761">"剩餘 <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
- <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"電量剩下 <xliff:g id="NUMBER">%d%%</xliff:g>,節約電池用量模式已啟用。"</string>
+ <string name="battery_low_percent_format_saver_started" msgid="6534746636002666456">"電量尚餘 <xliff:g id="NUMBER">%d%%</xliff:g>,省電模式已開啟。"</string>
<string name="invalid_charger" msgid="4549105996740522523">"不支援 USB 充電。\n僅能使用隨附的充電器。"</string>
<string name="invalid_charger_title" msgid="3515740382572798460">"不支援 USB 充電功能。"</string>
<string name="invalid_charger_text" msgid="5474997287953892710">"僅限使用裝置隨附的充電器。"</string>
<string name="battery_low_why" msgid="4553600287639198111">"設定"</string>
- <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"啟動節約電池用量模式?"</string>
+ <string name="battery_saver_confirmation_title" msgid="5987726159603849352">"啟動省電模式?"</string>
<string name="battery_saver_confirmation_ok" msgid="7283108887345688413">"開始"</string>
- <string name="battery_saver_start_action" msgid="7245333922937402896">"啟動節約電池用量模式"</string>
- <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"節約電池用量模式有助於延長電池壽命,但會降低裝置的效能。\n\n裝置接上電源時,節約電池用量模式會自動停用。"</string>
+ <string name="battery_saver_start_action" msgid="7245333922937402896">"啟動省電模式"</string>
+ <string name="battery_saver_confirmation_text" msgid="8417584516834617662">"省電模式可延長電池使用時間,但會降低裝置的效能。\n\n裝置充電時,省電模式會自動停用。"</string>
<string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
<string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
<string name="status_bar_settings_airplane" msgid="4879879698500955300">"飛行模式"</string>
@@ -51,7 +51,7 @@
<string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"自動"</string>
<string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string>
<string name="bluetooth_tethered" msgid="7094101612161133267">"已經由藍牙進行網絡共享"</string>
- <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"設定輸入方式"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"設定輸入法"</string>
<string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"實體鍵盤"</string>
<string name="usb_device_permission_prompt" msgid="834698001271562057">"允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式存取 USB 裝置嗎?"</string>
<string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式存取 USB 配件嗎?"</string>
@@ -67,13 +67,13 @@
<string name="usb_debugging_always" msgid="303335496705863070">"一律允許透過這部電腦進行"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
- <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在儲存屏幕擷取畫面..."</string>
- <string name="screenshot_saving_title" msgid="8242282144535555697">"正在儲存屏幕擷取畫面..."</string>
- <string name="screenshot_saving_text" msgid="2419718443411738818">"正在儲存屏幕擷取畫面。"</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"已擷取屏幕畫面。"</string>
- <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看屏幕擷取畫面。"</string>
- <string name="screenshot_failed_title" msgid="705781116746922771">"無法擷取屏幕畫面。"</string>
- <string name="screenshot_failed_text" msgid="8134011269572415402">"無法儲存屏幕擷取畫面,儲存裝置可能正在使用。"</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在儲存螢幕擷取畫面..."</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"正在儲存螢幕擷取畫面..."</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"正在儲存螢幕擷取畫面。"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"已擷取螢幕畫面。"</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看螢幕擷取畫面。"</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"無法擷取螢幕畫面。"</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"無法儲存螢幕擷取畫面,儲存裝置可能正在使用。"</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
@@ -139,7 +139,7 @@
<string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
<string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="8274017118472455155">"無 SIM 卡。"</string>
- <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"藍牙數據連線。"</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"藍牙網絡共享。"</string>
<string name="accessibility_airplane_mode" msgid="834748999790763092">"飛航模式。"</string>
<!-- String.format failed for translation -->
<!-- no translation found for accessibility_battery_level (7451474187113371965) -->
@@ -181,9 +181,9 @@
<string name="accessibility_location_active" msgid="2427290146138169014">"位置要求啟動中"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"應用程式資訊"</string>
- <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕會自動旋轉。"</string>
- <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕已鎖定為橫向模式。"</string>
- <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕已鎖定為垂直模式。"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"螢幕會自動旋轉。"</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"螢幕已鎖定為橫向模式。"</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"螢幕已鎖定為垂直模式。"</string>
<string name="dessert_case" msgid="1295161776223959221">"Dessert Case"</string>
<string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
<string name="ethernet_label" msgid="7967563676324087464">"以太網"</string>
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 部裝置)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"藍牙關閉"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"自動旋轉"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"輪流展示鎖定"</string>
@@ -207,26 +209,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"設定"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"時間"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"我"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未連線"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網絡"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 關閉"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"放送螢幕"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"反轉顏色"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"色彩校準模式"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"更多設定"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"完成"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"已連線"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
- <skip />
- <string name="quick_settings_tethering_label" msgid="7153452060448575549">"網路共用"</string>
+ <string name="quick_settings_tethering_label" msgid="7153452060448575549">"網絡共享"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"熱點"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"閃光燈"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"流動數據"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"數據用量"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩餘資料"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"超過上限"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"已使用 <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限為 <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"沒有最近使用的應用程式"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資料"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"應用程式鎖定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"已完成充電"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
@@ -236,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
<string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"請勿騷擾"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"不允許干擾 (包含鬧鐘和計時器)"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"不允許干擾"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"僅限優先干擾"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"還有 <xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g> 則通知"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"不太緊急的通知會在下方顯示"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上快速滑動即可解鎖"</string>
<string name="phone_hint" msgid="3101468054914424646">"向右快速滑動即可使用手機功能"</string>
<string name="camera_hint" msgid="5241441720959174226">"向左快速滑動即可使用相機功能"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"直至您關閉這項設定"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"無限期"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"無"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"優先順序"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後完成充電)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"訪客"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"新增訪客"</string>
@@ -255,7 +286,10 @@
<item quantity="one" msgid="3480040795582254384">"1 小時"</item>
<item quantity="other" msgid="5408537517529822157">"%d 小時"</item>
</plurals>
- <string name="battery_saver_notification_title" msgid="237918726750955859">"節約電池用量模式已啟用"</string>
+ <string name="battery_saver_notification_title" msgid="237918726750955859">"省電模式已開啟"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"裝置效能已降低。"</string>
- <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"開啟節約電池用量設定"</string>
+ <string name="battery_saver_notification_action_text" msgid="7546297220816993504">"開啟省電設定"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index bf5caae..5fa3419 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -193,6 +193,8 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 個裝置)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"關閉藍牙"</string>
+ <!-- no translation found for quick_settings_bluetooth_detail_empty_text (4910015762433302860) -->
+ <skip />
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"自動旋轉"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"已鎖定旋轉"</string>
@@ -207,26 +209,50 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"設定"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"時間"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"我"</string>
+ <!-- no translation found for quick_settings_user_title (4467690427642392403) -->
+ <skip />
+ <!-- no translation found for quick_settings_user_new_user (9030521362023479778) -->
+ <skip />
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未連線"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網路"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 已關閉"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"投放螢幕"</string>
+ <!-- no translation found for quick_settings_wifi_detail_empty_text (2831702993995222755) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_title (1893629685050355115) -->
+ <skip />
+ <!-- no translation found for quick_settings_casting (6601710681033353316) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_name (5367253104742382945) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_device_default_description (2484573682378634413) -->
+ <skip />
+ <!-- no translation found for quick_settings_cast_detail_empty_text (311785821261640623) -->
+ <skip />
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"反轉顏色"</string>
<string name="quick_settings_color_space_label" msgid="853443689745584770">"色彩校正模式"</string>
<string name="quick_settings_more_settings" msgid="326112621462813682">"更多設定"</string>
- <!-- no translation found for quick_settings_done (3402999958839153376) -->
- <skip />
- <!-- no translation found for quick_settings_connected (1722253542984847487) -->
+ <string name="quick_settings_done" msgid="3402999958839153376">"完成"</string>
+ <string name="quick_settings_connected" msgid="1722253542984847487">"已連線"</string>
+ <!-- no translation found for quick_settings_connecting (47623027419264404) -->
<skip />
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"網路共用"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"無線基地台"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"閃光燈"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"行動數據"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"數據用量"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"剩餘資料"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"超過上限"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"已使用 <xliff:g id="DATA_USED">%s</xliff:g>"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限為 <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
+ <!-- no translation found for quick_settings_cellular_detail_data_warning (2440098045692399009) -->
+ <skip />
<string name="recents_empty_message" msgid="7883614615463619450">"沒有最近使用的應用程式"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資訊"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"應用程式鎖定"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"已充飽"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"充電中"</string>
@@ -236,14 +262,19 @@
<string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
<string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
<string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"請勿打擾"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"不允許干擾 (包含鬧鐘和計時器)"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"不允許干擾"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"僅限優先干擾"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"還有 <xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g> 則通知"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"較不緊急的通知會顯示在下方"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上滑動即可解鎖"</string>
<string name="phone_hint" msgid="3101468054914424646">"向左滑動可使用手機功能"</string>
<string name="camera_hint" msgid="5241441720959174226">"向左滑動可使用相機功能"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"手動關閉這項設定前一律啟用"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"無限期"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"無"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"優先"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"全部"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"充電中 (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g>後充飽)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"訪客"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"新增訪客"</string>
@@ -258,4 +289,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"節約耗電量模式已啟用"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"裝置效能已降低。"</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"開啟節約耗電量設定"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index e82909f..deff4d1 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -191,6 +191,7 @@
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"I-Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"I-Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> amadivayisi)"</string>
<string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"I-Bluetooth ivaliwe"</string>
+ <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"Awekho amadivayisi abhanqiwe atholakalayo"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Ukugqama"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"Ukuphenduka okuzenzakalelayo"</string>
<string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"Ukuphenduka kukhiyiwe"</string>
@@ -205,11 +206,18 @@
<string name="quick_settings_settings_label" msgid="5326556592578065401">"Izilungiselelo"</string>
<string name="quick_settings_time_label" msgid="4635969182239736408">"Isikhathi"</string>
<string name="quick_settings_user_label" msgid="5238995632130897840">"Mina"</string>
+ <string name="quick_settings_user_title" msgid="4467690427642392403">"Umsebenzisi"</string>
+ <string name="quick_settings_user_new_user" msgid="9030521362023479778">"Umsebenzisi omusha"</string>
<string name="quick_settings_wifi_label" msgid="9135344704899546041">"I-Wi-Fi"</string>
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Akuxhunyiwe"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ayikho inethiwekhi"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"I-Wi-Fi icimile"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="7482103121002965053">"Isikrini sabadlali"</string>
+ <string name="quick_settings_wifi_detail_empty_text" msgid="2831702993995222755">"Awekho amanethiwekhi alondoloziwe atholakalayo"</string>
+ <string name="quick_settings_cast_title" msgid="1893629685050355115">"Isikrini sabadlali"</string>
+ <string name="quick_settings_casting" msgid="6601710681033353316">"Ukusakaza"</string>
+ <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"Idivayisi engenalo igama"</string>
+ <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"Ilungele ukusakaza"</string>
+ <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"Ayikho idivayisi etholakalayo"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Ukugqama"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OKUZENZAKALELAYO"</string>
<string name="quick_settings_inversion_label" msgid="8790919884718619648">"Faka imibala"</string>
@@ -217,12 +225,21 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Izilungiselelo eziningi"</string>
<string name="quick_settings_done" msgid="3402999958839153376">"Kwenziwe"</string>
<string name="quick_settings_connected" msgid="1722253542984847487">"Ixhunyiwe"</string>
+ <string name="quick_settings_connecting" msgid="47623027419264404">"Iyaxhuma..."</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Ukusebenzisa njengemodemu"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"I-Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Izaziso"</string>
<string name="quick_settings_flashlight_label" msgid="2133093497691661546">"I-Flashlight"</string>
+ <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Idatha yeselula"</string>
+ <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Ukusetshenziswa kwedatha"</string>
+ <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Idatha esele"</string>
+ <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Ingaphezulu komkhawulo"</string>
+ <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> isetshenzisiwe"</string>
+ <string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> umkhawulo"</string>
+ <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> isexwayiso"</string>
<string name="recents_empty_message" msgid="7883614615463619450">"Azikho izinhlelo zokusebenza zakamuva"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Ulwazi lohlelo lokusebenza"</string>
+ <string name="recents_lock_to_app_button_label" msgid="4793991421811647489">"ukukhiya kuhlelo lokusebenza"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kushajiwe"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Iyashaja"</string>
@@ -232,14 +249,19 @@
<string name="description_target_search" msgid="3091587249776033139">"Sesha"</string>
<string name="description_direction_up" msgid="7169032478259485180">"Shelelisela ngenhla ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
<string name="description_direction_left" msgid="7207478719805562165">"Shelelisela ngakwesokunxele ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
- <string name="zen_mode_title" msgid="8793432092004749188">"Ungaphazamisi"</string>
+ <string name="zen_no_interruptions_with_warning" msgid="7669163720139116154">"Azikho iziphazamiso, ezifaka ama-alamu nezisethi zesikhathi"</string>
+ <string name="zen_no_interruptions" msgid="7970973750143632592">"Azikho iziphazamiso"</string>
+ <string name="zen_important_interruptions" msgid="3477041776609757628">"Iziphazamiso ezibalulekile kuphela"</string>
<string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="1288875699658819755">"Izaziso ezingasheshi kakhulu ezingezansi"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Thepha futhi ukuze uvule"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Swayiphela phezulu ukuze uvule"</string>
<string name="phone_hint" msgid="3101468054914424646">"Swayiphela ngakwesokudla ukuze uthole ifoni"</string>
<string name="camera_hint" msgid="5241441720959174226">"Swayiphela ngakwesokunxele ukuze uthole ikhamela"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"Uze uvale lokhu"</string>
+ <string name="zen_mode_forever" msgid="4316804956488785559">"Unaphakade"</string>
+ <string name="interruption_level_none" msgid="3831278883136066646">"Lutho"</string>
+ <string name="interruption_level_priority" msgid="6517366750688942030">"Okubalulekile"</string>
+ <string name="interruption_level_all" msgid="1330581184930945764">"Konke"</string>
<string name="keyguard_indication_charging_time" msgid="1757251776872835768">"Iyashaja (<xliff:g id="CHARGING_TIME_LEFT">%s</xliff:g> ize igcwale)"</string>
<string name="guest_nickname" msgid="8059989128963789678">"Isihambeli"</string>
<string name="guest_new_guest" msgid="4259024453643879653">"+ Isihambeli"</string>
@@ -254,4 +276,7 @@
<string name="battery_saver_notification_title" msgid="237918726750955859">"Isilondolozi sebhethri sivuliwe"</string>
<string name="battery_saver_notification_text" msgid="7796554871101546872">"Ukusebenza kwedivayisi kwehlisiwe."</string>
<string name="battery_saver_notification_action_text" msgid="7546297220816993504">"Vula izilungiselelo zesilondolozi sebhethri"</string>
+ <string name="battery_level_template" msgid="1609636980292580020">"<xliff:g id="LEVEL">%d</xliff:g>%%"</string>
+ <!-- no translation found for notification_hidden_text (1135169301897151909) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bae7ed7..adab243 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -44,7 +44,8 @@
<color name="qs_detail_empty">#24B0BEC5</color><!-- 14% blue grey 200-->
<color name="data_usage_secondary">#99FFFFFF</color><!-- 60% white -->
<color name="data_usage_graph_track">#33FFFFFF</color><!-- 20% white -->
- <color name="status_bar_clock_color">#33FFFFFF</color>
+ <color name="data_usage_graph_warning">#FFFFFFFF</color>
+ <color name="status_bar_clock_color">#FFFFFFFF</color>
<!-- Tint color for the content on the notification overflow card. -->
<color name="keyguard_overflow_content_color">#ff686868</color>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6a7b450..28b0853 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -416,17 +416,17 @@
<string name="accessibility_quick_settings_less_time">Less time</string>
<!-- Title of dialog shown when 2G-3G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_3g_title">2G-3G data disabled</string>
+ <string name="data_usage_disabled_dialog_3g_title">2G-3G data is off</string>
<!-- Title of dialog shown when 4G data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_4g_title">4G data disabled</string>
+ <string name="data_usage_disabled_dialog_4g_title">4G data is off</string>
<!-- Title of dialog shown when mobile data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_mobile_title">Mobile data disabled</string>
+ <string name="data_usage_disabled_dialog_mobile_title">Cellular data is off</string>
<!-- Title of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=48] -->
- <string name="data_usage_disabled_dialog_title">Data disabled</string>
+ <string name="data_usage_disabled_dialog_title">Data is off</string>
<!-- Body of dialog shown when data usage has exceeded limit and has been disabled. [CHAR LIMIT=NONE] -->
- <string name="data_usage_disabled_dialog">You\'ve reached the specified data usage limit.\n\nIf you re-enable data, you may be charged by the operator.</string>
+ <string name="data_usage_disabled_dialog">Your device turned off data because it reached the limit you set.\n\nTurning it back on may lead to charges from your carrier.</string>
<!-- Dialog button indicating that data connection should be re-enabled. [CHAR LIMIT=28] -->
- <string name="data_usage_disabled_dialog_enable">Re-enable data</string>
+ <string name="data_usage_disabled_dialog_enable">Turn on data</string>
<!-- Text to display underneath the graphical signal strength meter when
no connection is available. [CHAR LIMIT=20] -->
@@ -516,6 +516,10 @@
<string name="quick_settings_time_label">Time</string>
<!-- QuickSettings: User [CHAR LIMIT=NONE] -->
<string name="quick_settings_user_label">Me</string>
+ <!-- QuickSettings: Title of the user detail panel [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_user_title">User</string>
+ <!-- QuickSettings: Label on the item for adding a new user [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_user_new_user">New user</string>
<!-- QuickSettings: Wifi [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_label">Wi-Fi</string>
<!-- QuickSettings: Wifi (Not connected) [CHAR LIMIT=NONE] -->
@@ -572,6 +576,8 @@
<string name="quick_settings_cellular_detail_data_used"><xliff:g id="data_used" example="2.0 GB">%s</xliff:g> used</string>
<!-- QuickSettings: Cellular detail panel, data limit format string [CHAR LIMIT=NONE] -->
<string name="quick_settings_cellular_detail_data_limit"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g> limit</string>
+ <!-- QuickSettings: Cellular detail panel, data warning format string [CHAR LIMIT=NONE] -->
+ <string name="quick_settings_cellular_detail_data_warning"><xliff:g id="data_limit" example="2.0 GB">%s</xliff:g> warning</string>
<!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
<string name="recents_empty_message">No recent apps</string>
@@ -685,4 +691,7 @@
<!-- Battery level for expanded quick settings [CHAR LIMIT=2] -->
<string name="battery_level_template"><xliff:g id="level" example="45">%d</xliff:g>%%</string>
+
+ <!-- Text shown in place of notification contents when the notification is hidden on a secure lockscreen -->
+ <string name="notification_hidden_text">Contents hidden</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 7da6c22..708d3e8 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -270,4 +270,10 @@
<item name="android:windowEnterAnimation">@*android:anim/dock_top_enter</item>
<item name="android:windowExitAnimation">@*android:anim/dock_top_exit</item>
</style>
+
+ <style name="TextAppearance.StatusBar.Material.EventContent.Parenthetical"
+ parent="@*android:style/TextAppearance.StatusBar.Material.EventContent">
+ <item name="android:textStyle">italic</item>
+ <item name="android:textColor">#60000000</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
index fa11af6..d55ceaa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
@@ -28,34 +28,34 @@
public class DataUsageGraph extends View {
- private final int mBackgroundColor;
private final int mTrackColor;
private final int mUsageColor;
private final int mOverlimitColor;
+ private final int mWarningColor;
private final int mMarkerWidth;
private final RectF mTmpRect = new RectF();
private final Paint mTmpPaint = new Paint();
- private long mMaxLevel = 1;
private long mLimitLevel;
private long mWarningLevel;
private long mUsageLevel;
+ private long mMaxLevel;
public DataUsageGraph(Context context, AttributeSet attrs) {
super(context, attrs);
final Resources res = context.getResources();
- mBackgroundColor = res.getColor(R.color.system_primary_color);
mTrackColor = res.getColor(R.color.data_usage_graph_track);
mUsageColor = res.getColor(R.color.system_accent_color);
mOverlimitColor = res.getColor(R.color.system_warning_color);
+ mWarningColor = res.getColor(R.color.data_usage_graph_warning);
mMarkerWidth = res.getDimensionPixelSize(R.dimen.data_usage_graph_marker_width);
}
- public void setLevels(long maxLevel, long limitLevel, long warningLevel, long usageLevel) {
- mMaxLevel = Math.max(maxLevel, 1);
- mLimitLevel = limitLevel;
- mWarningLevel = warningLevel;
- mUsageLevel = usageLevel;
+ public void setLevels(long limitLevel, long warningLevel, long usageLevel) {
+ mLimitLevel = Math.max(0, limitLevel);
+ mWarningLevel = Math.max(0, warningLevel);
+ mUsageLevel = Math.max(0, usageLevel);
+ mMaxLevel = Math.max(Math.max(Math.max(mLimitLevel, mWarningLevel), mUsageLevel), 1);
postInvalidate();
}
@@ -68,21 +68,22 @@
final int w = getWidth();
final int h = getHeight();
- // draw track
- r.set(0, 0, w, h);
- p.setColor(mTrackColor);
- canvas.drawRect(r, p);
-
- final boolean hasLimit = mLimitLevel > 0;
- final boolean overLimit = hasLimit && mUsageLevel > mLimitLevel;
-
- final long maxLevel = hasLimit ? Math.max(mUsageLevel, mLimitLevel) : mMaxLevel;
- final long usageLevel = hasLimit ? Math.min(mUsageLevel, mLimitLevel) : mUsageLevel;
- float usageRight = w * (usageLevel / (float) maxLevel);
+ final boolean overLimit = mLimitLevel > 0 && mUsageLevel > mLimitLevel;
+ float usageRight = w * (mUsageLevel / (float) mMaxLevel);
if (overLimit) {
- usageRight -= (mMarkerWidth / 2);
- usageRight = Math.min(usageRight, w - mMarkerWidth * 2);
- usageRight = Math.max(usageRight, mMarkerWidth);
+ // compute the gap
+ usageRight = w * (mLimitLevel / (float) mMaxLevel) - (mMarkerWidth / 2);
+ usageRight = Math.min(Math.max(usageRight, mMarkerWidth), w - mMarkerWidth * 2);
+
+ // draw overlimit
+ r.set(usageRight + mMarkerWidth, 0, w, h);
+ p.setColor(mOverlimitColor);
+ canvas.drawRect(r, p);
+ } else {
+ // draw track
+ r.set(0, 0, w, h);
+ p.setColor(mTrackColor);
+ canvas.drawRect(r, p);
}
// draw usage
@@ -90,16 +91,11 @@
p.setColor(mUsageColor);
canvas.drawRect(r, p);
- if (overLimit) {
- // draw gap
- r.set(usageRight, 0, usageRight + mMarkerWidth, h);
- p.setColor(mBackgroundColor);
- canvas.drawRect(r, p);
-
- // draw overlimit
- r.set(usageRight + mMarkerWidth, 0, w, h);
- p.setColor(mOverlimitColor);
- canvas.drawRect(r, p);
- }
+ // draw warning marker
+ float warningLeft = w * (mWarningLevel / (float) mMaxLevel) - mMarkerWidth / 2;
+ warningLeft = Math.min(Math.max(warningLeft, 0), w - mMarkerWidth);
+ r.set(warningLeft, 0, warningLeft + mMarkerWidth, h);
+ p.setColor(mWarningColor);
+ canvas.drawRect(r, p);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 449cc1d..4901f40 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -34,6 +34,7 @@
import com.android.systemui.qs.QSTile.DetailAdapter;
import com.android.systemui.settings.BrightnessController;
import com.android.systemui.settings.ToggleSlider;
+import com.android.systemui.statusbar.phone.QSTileHost;
import java.util.ArrayList;
@@ -61,9 +62,10 @@
private boolean mExpanded;
private boolean mListening;
- private TileRecord mDetailRecord;
+ private Record mDetailRecord;
private Callback mCallback;
private BrightnessController mBrightnessController;
+ private QSTileHost mHost;
public QSPanel(Context context) {
this(context, null);
@@ -89,12 +91,27 @@
mBrightnessController = new BrightnessController(getContext(),
(ImageView) findViewById(R.id.brightness_icon),
(ToggleSlider) findViewById(R.id.brightness_slider));
+
+ mDetailDoneButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showDetail(false, mDetailRecord);
+ }
+ });
}
public void setCallback(Callback callback) {
mCallback = callback;
}
+ public void setHost(QSTileHost host) {
+ mHost = host;
+ }
+
+ public QSTileHost getHost() {
+ return mHost;
+ }
+
public void updateResources() {
final Resources res = mContext.getResources();
final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
@@ -108,6 +125,9 @@
mColumns = columns;
postInvalidate();
}
+ if (mListening) {
+ refreshAllTiles();
+ }
}
public void setExpanded(boolean expanded) {
@@ -123,9 +143,9 @@
mListening = listening;
for (TileRecord r : mRecords) {
r.tile.setListening(mListening);
- if (mListening) {
- r.tile.refreshState();
- }
+ }
+ if (mListening) {
+ refreshAllTiles();
}
if (listening) {
mBrightnessController.registerCallbacks();
@@ -134,7 +154,19 @@
}
}
- private void showDetail(boolean show, TileRecord r) {
+ private void refreshAllTiles() {
+ for (TileRecord r : mRecords) {
+ r.tile.refreshState();
+ }
+ }
+
+ public void showDetailAdapter(boolean show, DetailAdapter adapter) {
+ Record r = new Record();
+ r.detailAdapter = adapter;
+ showDetail(show, r);
+ }
+
+ private void showDetail(boolean show, Record r) {
mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget();
}
@@ -194,40 +226,52 @@
addView(r.tileView);
}
- private void handleShowDetail(TileRecord r, boolean show) {
- if (r == null) return;
- AnimatorListener listener = null;
+ private void handleShowDetail(Record r, boolean show) {
+ if (r instanceof TileRecord) {
+ handleShowDetailTile((TileRecord) r, show);
+ } else {
+ handleShowDetailImpl(r, show, getWidth() /* x */, 0/* y */);
+ }
+ }
+
+ private void handleShowDetailTile(TileRecord r, boolean show) {
+ if ((mDetailRecord != null) == show) return;
+
if (show) {
- if (mDetailRecord != null) return; // already showing something in detail
r.detailAdapter = r.tile.getDetailAdapter();
if (r.detailAdapter == null) return;
- mDetailRecord = r;
- r.detailView = r.detailAdapter.createDetailView(mContext, r.detailView, mDetailContent);
+ }
+ int x = r.tileView.getLeft() + r.tileView.getWidth() / 2;
+ int y = r.tileView.getTop() + r.tileView.getHeight() / 2;
+ handleShowDetailImpl(r, show, x, y);
+ }
+
+ private void handleShowDetailImpl(Record r, boolean show, int x, int y) {
+ if ((mDetailRecord != null) == show) return; // already in right state
+ DetailAdapter detailAdapter = null;
+ AnimatorListener listener = null;
+ if (show) {
+ detailAdapter = r.detailAdapter;
+ r.detailView = detailAdapter.createDetailView(mContext, r.detailView, mDetailContent);
if (r.detailView == null) throw new IllegalStateException("Must return detail view");
- mDetailDoneButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- showDetail(false, mDetailRecord);
- }
- });
- final Intent settingsIntent = r.detailAdapter.getSettingsIntent();
+
+ final Intent settingsIntent = detailAdapter.getSettingsIntent();
mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
mDetailSettingsButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- mDetailRecord.tile.mHost.startSettingsActivity(settingsIntent);
+ mHost.startSettingsActivity(settingsIntent);
}
});
+
mDetailContent.removeAllViews();
mDetail.bringToFront();
mDetailContent.addView(r.detailView);
+ mDetailRecord = r;
} else {
- if (mDetailRecord == null) return;
listener = mTeardownDetailWhenDone;
}
- fireShowingDetail(show ? r.detailAdapter : null);
- int x = r.tileView.getLeft() + r.tileView.getWidth() / 2;
- int y = r.tileView.getTop() + r.tileView.getHeight() / 2;
+ fireShowingDetail(show ? detailAdapter : null);
mClipper.animateCircularClip(x, y, show, listener);
}
@@ -330,18 +374,21 @@
@Override
public void handleMessage(Message msg) {
if (msg.what == SHOW_DETAIL) {
- handleShowDetail((TileRecord)msg.obj, msg.arg1 != 0);
+ handleShowDetail((Record)msg.obj, msg.arg1 != 0);
} else if (msg.what == SET_TILE_VISIBILITY) {
handleSetTileVisibility((View)msg.obj, msg.arg1 != 0);
}
}
}
- private static final class TileRecord {
- QSTile<?> tile;
- QSTileView tileView;
+ private static class Record {
View detailView;
DetailAdapter detailAdapter;
+ }
+
+ private static final class TileRecord extends Record {
+ QSTile<?> tile;
+ QSTileView tileView;
int row;
int col;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 1f12b2a..d76a2fe 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -216,21 +216,27 @@
final DataUsageInfo info = mController.getDataUsageInfo();
if (info == null) return v;
final Resources res = mContext.getResources();
- int titleId;
- long bytes;
+ final int titleId;
+ final long bytes;
int usageColor = R.color.system_accent_color;
- String top = null, bottom = null;
- if (info.limitLevel <= 0) { // no limit
+ final String top;
+ String bottom = null;
+ if (info.usageLevel < info.warningLevel || info.limitLevel <= 0) {
+ // under warning, or no limit
titleId = R.string.quick_settings_cellular_detail_data_usage;
bytes = info.usageLevel;
- } else if (info.usageLevel <= info.limitLevel) { // under limit
+ top = res.getString(R.string.quick_settings_cellular_detail_data_warning,
+ formatBytes(info.warningLevel));
+ } else if (info.usageLevel <= info.limitLevel) {
+ // over warning, under limit
titleId = R.string.quick_settings_cellular_detail_remaining_data;
bytes = info.limitLevel - info.usageLevel;
top = res.getString(R.string.quick_settings_cellular_detail_data_used,
formatBytes(info.usageLevel));
bottom = res.getString(R.string.quick_settings_cellular_detail_data_limit,
formatBytes(info.limitLevel));
- } else { // over limit
+ } else {
+ // over limit
titleId = R.string.quick_settings_cellular_detail_over_limit;
bytes = info.usageLevel - info.limitLevel;
top = res.getString(R.string.quick_settings_cellular_detail_data_used,
@@ -246,7 +252,7 @@
usage.setText(formatBytes(bytes));
usage.setTextColor(res.getColor(usageColor));
final DataUsageGraph graph = (DataUsageGraph) v.findViewById(R.id.usage_graph);
- graph.setLevels(info.maxLevel, info.limitLevel, info.warningLevel, info.usageLevel);
+ graph.setLevels(info.limitLevel, info.warningLevel, info.usageLevel);
final TextView carrier = (TextView) v.findViewById(R.id.usage_carrier_text);
carrier.setText(info.carrier);
final TextView period = (TextView) v.findViewById(R.id.usage_period_text);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 3be97cc..21cf9ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -18,7 +18,6 @@
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.drawable.AnimationDrawable;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
@@ -61,35 +60,19 @@
final boolean rotationLocked = mController.isRotationLocked();
state.visible = mController.isRotationLockAffordanceVisible();
final Resources res = mContext.getResources();
- if (state.value != rotationLocked) {
- state.value = rotationLocked;
- final AnimationDrawable d = (AnimationDrawable) res.getDrawable(rotationLocked
- ? R.drawable.ic_qs_rotation_locked
- : R.drawable.ic_qs_rotation_unlocked);
- state.icon = d;
- mUiHandler.post(new Runnable() {
- @Override
- public void run() {
- d.start();
- }
- });
- }
+ state.value = rotationLocked;
if (rotationLocked) {
- final int lockOrientation = mController.getRotationLockOrientation();
- final int label = lockOrientation == Configuration.ORIENTATION_PORTRAIT
- ? R.string.quick_settings_rotation_locked_portrait_label
- : lockOrientation == Configuration.ORIENTATION_LANDSCAPE
- ? R.string.quick_settings_rotation_locked_landscape_label
- : R.string.quick_settings_rotation_locked_label;
+ final boolean portrait = res.getConfiguration().orientation
+ != Configuration.ORIENTATION_LANDSCAPE;
+ final int label = portrait ? R.string.quick_settings_rotation_locked_portrait_label
+ : R.string.quick_settings_rotation_locked_landscape_label;
+ final int icon = portrait ? R.drawable.ic_qs_rotation_portrait
+ : R.drawable.ic_qs_rotation_landscape;
state.label = mContext.getString(label);
- if (state.icon == null) {
- state.icon = res.getDrawable(R.drawable.ic_qs_rotation_15);
- }
+ state.icon = mContext.getDrawable(icon);
} else {
state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
- if (state.icon == null) {
- state.icon = res.getDrawable(R.drawable.ic_qs_rotation_01);
- }
+ state.icon = res.getDrawable(R.drawable.ic_qs_rotation_unlocked);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
new file mode 100644
index 0000000..d765aab
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -0,0 +1,82 @@
+/*
+ * 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
+ */
+
+package com.android.systemui.qs.tiles;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.UserAvatarView;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * Displays one user in the {@link UserDetailView} view.
+ */
+public class UserDetailItemView extends LinearLayout {
+
+ private UserAvatarView mAvatar;
+ private TextView mName;
+
+ public UserDetailItemView(Context context) {
+ this(context, null);
+ }
+
+ public UserDetailItemView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public UserDetailItemView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public UserDetailItemView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public static UserDetailItemView convertOrInflate(Context context, View convertView,
+ ViewGroup root) {
+ if (!(convertView instanceof UserDetailItemView)) {
+ convertView = LayoutInflater.from(context).inflate(
+ R.layout.qs_user_detail_item, root, false);
+ }
+ return (UserDetailItemView) convertView;
+ }
+
+ public void bind(String name, Bitmap picture) {
+ mName.setText(name);
+ mAvatar.setBitmap(picture);
+ }
+
+ public void bind(String name, Drawable picture) {
+ mName.setText(name);
+ mAvatar.setDrawable(picture);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ mAvatar = (UserAvatarView) findViewById(R.id.user_picture);
+ mName = (TextView) findViewById(R.id.user_name);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
new file mode 100644
index 0000000..ec5f28c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -0,0 +1,101 @@
+/*
+ * 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
+ */
+
+package com.android.systemui.qs.tiles;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+
+import android.content.Context;
+import android.content.Intent;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.GridView;
+
+/**
+ * Quick settings detail view for user switching.
+ */
+public class UserDetailView extends GridView {
+
+ public UserDetailView(Context context) {
+ this(context, null);
+ }
+
+ public UserDetailView(Context context, AttributeSet attrs) {
+ this(context, attrs, android.R.attr.gridViewStyle);
+ }
+
+ public UserDetailView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public UserDetailView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ UserSwitcherController.UserRecord tag =
+ (UserSwitcherController.UserRecord) view.getTag();
+ ((Adapter)getAdapter()).switchTo(tag);
+ }
+ });
+ }
+
+ public static UserDetailView inflate(Context context, ViewGroup parent, boolean attach) {
+ return (UserDetailView) LayoutInflater.from(context).inflate(
+ R.layout.qs_user_detail, parent, attach);
+ }
+
+ public void createAndSetAdapter(UserSwitcherController controller) {
+ setAdapter(new Adapter(mContext, controller));
+ }
+
+ public static class Adapter extends UserSwitcherController.BaseUserAdapter {
+
+ private Context mContext;
+
+ public Adapter(Context context, UserSwitcherController controller) {
+ super(controller);
+ mContext = context;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ UserSwitcherController.UserRecord item = getItem(position);
+ UserDetailItemView v = UserDetailItemView.convertOrInflate(
+ mContext, convertView, parent);
+ String name;
+ if (item.isGuest) {
+ name = mContext.getString(
+ item.info == null ? R.string.guest_new_guest : R.string.guest_nickname);
+ } else {
+ name = item.info.name;
+ }
+ if (item.picture == null) {
+ v.bind(name, mContext.getDrawable(R.drawable.ic_account_circle));
+ } else {
+ v.bind(name, item.picture);
+ }
+ v.setActivated(item.isCurrent);
+ v.setTag(item);
+ return v;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index a9a606f..b6d7d7e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -64,11 +64,9 @@
Context mContext;
SystemServicesProxy mSystemServicesProxy;
-
- // Recents service binding
Handler mHandler;
- boolean mBootCompleted = false;
- boolean mStartAnimationTriggered = false;
+ boolean mBootCompleted;
+ boolean mStartAnimationTriggered;
// Task launching
RecentsConfiguration mConfig;
@@ -95,9 +93,7 @@
}
public void onStart() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|start]");
- }
+ // Do nothing
}
public void onBootCompleted() {
@@ -106,9 +102,6 @@
/** Shows the recents */
public void onShowRecents(boolean triggeredFromAltTab, View statusBarView) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|showRecents]");
- }
mStatusBarView = statusBarView;
mTriggeredFromAltTab = triggeredFromAltTab;
@@ -121,10 +114,6 @@
/** Hides the recents */
public void onHideRecents(boolean triggeredFromAltTab) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|hideRecents]");
- }
-
if (mBootCompleted) {
if (isRecentsTopMost(getTopMostTask(), null)) {
// Notify recents to hide itself
@@ -139,13 +128,6 @@
/** Toggles the alternate recents activity */
public void onToggleRecents(View statusBarView) {
- if (Console.Enabled) {
- Console.logStartTracingTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey);
- Console.logStartTracingTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey);
- Console.log(Constants.Log.App.RecentsComponent, "[RecentsComponent|toggleRecents]", "");
- }
mStatusBarView = statusBarView;
mTriggeredFromAltTab = false;
@@ -223,14 +205,6 @@
intent.setPackage(mContext.getPackageName());
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcast(intent);
-
- // Time this path
- if (Console.Enabled) {
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "receivedToggleRecents");
- Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey, "receivedToggleRecents");
- }
mLastToggleTime = System.currentTimeMillis();
return;
} else {
@@ -395,11 +369,6 @@
startAlternateRecentsActivity(topTask, opts, null);
}
}
-
- if (Console.Enabled) {
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "startRecentsActivity");
- }
mLastToggleTime = System.currentTimeMillis();
}
@@ -417,10 +386,9 @@
intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, mTriggeredFromAltTab);
intent.putExtra(EXTRA_TRIGGERED_FROM_TASK_ID, (topTask != null) ? topTask.id : -1);
if (opts != null) {
- mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
- UserHandle.USER_CURRENT));
+ mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
} else {
- mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 8a80b76..c49e244 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -32,7 +32,7 @@
// Enables the filtering of tasks according to their grouping
public static final boolean EnableTaskFiltering = false;
// Enables clipping of tasks against each other
- public static final boolean EnableTaskStackClipping = true;
+ public static final boolean EnableTaskStackClipping = false;
// Enables tapping on the TaskBar to launch the task
public static final boolean EnableTaskBarTouchEvents = true;
// Enables app-info pane on long-pressing the icon
@@ -52,43 +52,6 @@
}
}
- public static class Log {
- public static class App {
- public static final String TimeRecentsStartupKey = "startup";
- public static final String TimeRecentsLaunchKey = "launchTask";
- public static final String TimeRecentsScreenshotTransitionKey = "screenshot";
- public static final boolean TimeRecentsStartup = false;
- public static final boolean TimeRecentsLaunchTask = false;
- public static final boolean TimeRecentsScreenshotTransition = false;
-
-
- public static final boolean RecentsComponent = false;
- public static final boolean TaskDataLoader = false;
- public static final boolean SystemUIHandshake = false;
- public static final boolean TimeSystemCalls = false;
- public static final boolean Memory = false;
- public static final boolean Search = false;
- }
-
- public static class UI {
- public static final boolean Draw = false;
- public static final boolean ClickEvents = false;
- public static final boolean TouchEvents = false;
- public static final boolean MeasureAndLayout = false;
- public static final boolean HwLayers = false;
- public static final boolean Focus = false;
- }
-
- public static class TaskStack {
- public static final boolean SynchronizeViewsWithModel = false;
- }
-
- public static class ViewPool {
- public static final boolean PoolCallbacks = false;
- }
- }
-
- /** XXX: We are going to move almost all of these into a resource once they are nailed down. */
public static class Values {
public static class App {
public static int AppWidgetHostId = 1024;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 56de0be..29a0262 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -52,16 +52,23 @@
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
-/* Activity */
+/**
+ * The main Recents activity that is started from AlternateRecentsComponent.
+ */
public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks,
FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks {
+ // Actions and Extras sent from AlternateRecentsComponent
final static String EXTRA_TRIGGERED_FROM_ALT_TAB = "extra_triggered_from_alt_tab";
final static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
final static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
+ RecentsConfiguration mConfig;
+ boolean mVisible;
+
+ // Top level views
RecentsView mRecentsView;
SystemBarScrimViews mScrimViews;
ViewStub mEmptyViewStub;
@@ -69,29 +76,29 @@
ViewStub mFullscreenOverlayStub;
FullscreenTransitionOverlayView mFullScreenOverlayView;
- RecentsConfiguration mConfig;
-
+ // Search AppWidget
RecentsAppWidgetHost mAppWidgetHost;
AppWidgetProviderInfo mSearchAppWidgetInfo;
AppWidgetHostView mSearchAppWidgetHostView;
- boolean mVisible;
// Runnables to finish the Recents activity
- FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable(true);
+ FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable();
FinishRecentsRunnable mFinishLaunchHomeRunnable;
/**
- * A Runnable to finish Recents either with/without a transition, and either by calling finish()
- * or just launching the specified intent.
+ * A common Runnable to finish Recents either by calling finish() (with a custom animation) or
+ * launching Home with some ActivityOptions. Generally we always launch home when we exit
+ * Recents rather than just finishing the activity since we don't know what is behind Recents in
+ * the task stack. The only case where we finish() directly is when we are cancelling the full
+ * screen transition from the app.
*/
class FinishRecentsRunnable implements Runnable {
- boolean mUseCustomFinishTransition;
Intent mLaunchIntent;
ActivityOptions mLaunchOpts;
- public FinishRecentsRunnable(boolean withTransition) {
- mUseCustomFinishTransition = withTransition;
+ public FinishRecentsRunnable() {
+ // Do nothing
}
/**
@@ -111,77 +118,66 @@
// Finish Recents
if (mLaunchIntent != null) {
if (mLaunchOpts != null) {
- startActivityAsUser(mLaunchIntent, new UserHandle(UserHandle.USER_CURRENT));
+ startActivityAsUser(mLaunchIntent, UserHandle.CURRENT);
} else {
- startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(),
- new UserHandle(UserHandle.USER_CURRENT));
+ startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(), UserHandle.CURRENT);
}
} else {
finish();
- if (mUseCustomFinishTransition) {
- overridePendingTransition(R.anim.recents_to_launcher_enter,
- R.anim.recents_to_launcher_exit);
- }
+ overridePendingTransition(R.anim.recents_to_launcher_enter,
+ R.anim.recents_to_launcher_exit);
}
}
}
- // Broadcast receiver to handle messages from AlternateRecentsComponent
+ /**
+ * Broadcast receiver to handle messages from AlternateRecentsComponent.
+ */
final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
- }
if (action.equals(ACTION_HIDE_RECENTS_ACTIVITY)) {
if (intent.getBooleanExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, false)) {
- // Dismiss recents, launching the focused task
- dismissRecentsIfVisible();
+ // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
+ dismissRecentsToFocusedTaskOrHome(false);
} else {
- // If we are mid-animation into Recents, then reverse it and finish
- if (mFullScreenOverlayView == null ||
- !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
- // Otherwise, either finish Recents, or launch Home directly
- ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(context,
- null, mFinishLaunchHomeRunnable, null);
- mRecentsView.startExitToHomeAnimation(
- new ViewAnimation.TaskViewExitContext(exitTrigger));
- }
+ // Otherwise, dismiss Recents to Home
+ dismissRecentsToHome(true);
}
} else if (action.equals(ACTION_TOGGLE_RECENTS_ACTIVITY)) {
- // Try and unfilter and filtered stacks
- if (!mRecentsView.unfilterFilteredStacks()) {
- // If there are no filtered stacks, dismiss recents and launch the first task
- dismissRecentsIfVisible();
- }
+ // If we are toggling Recents, then first unfilter any filtered stacks first
+ dismissRecentsToFocusedTaskOrHome(true);
} else if (action.equals(ACTION_START_ENTER_ANIMATION)) {
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
mFullScreenOverlayView, t));
- // Call our callback
onEnterAnimationTriggered();
}
}
};
- // Broadcast receiver to handle messages from the system
+ /**
+ * Broadcast receiver to handle messages from the system
+ */
final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (action.equals(Intent.ACTION_SCREEN_OFF) && mVisible) {
- mFinishLaunchHomeRunnable.run();
+ if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ // When the screen turns off, dismiss Recents to Home
+ dismissRecentsToHome(false);
} else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
- // Refresh the search widget
+ // When the search activity changes, update the Search widget
refreshSearchWidget();
}
}
};
- // Debug trigger
+ /**
+ * A custom debug trigger to listen for a debug key chord.
+ */
final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() {
@Override
public void run() {
@@ -211,15 +207,17 @@
mConfig.launchedToTaskId = launchIntent.getIntExtra(
AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_TASK_ID, -1);
- // Add the default no-recents layout
- if (mEmptyView == null) {
- mEmptyView = mEmptyViewStub.inflate();
- }
+ // Update the top level view's visibilities
if (mConfig.launchedWithNoRecentTasks) {
+ if (mEmptyView == null) {
+ mEmptyView = mEmptyViewStub.inflate();
+ }
mEmptyView.setVisibility(View.VISIBLE);
mRecentsView.setSearchBarVisibility(View.GONE);
} else {
- mEmptyView.setVisibility(View.GONE);
+ if (mEmptyView != null) {
+ mEmptyView.setVisibility(View.GONE);
+ }
if (mRecentsView.hasSearchBar()) {
mRecentsView.setSearchBarVisibility(View.VISIBLE);
} else {
@@ -227,7 +225,7 @@
}
}
- // Show the scrim if we animate into Recents without window transitions
+ // Animate the SystemUI scrims into view
mScrimViews.prepareEnterRecentsAnimation();
}
@@ -250,12 +248,6 @@
ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
appWidgetId = -1;
}
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onCreate|settings|appWidgetId]",
- "Id: " + appWidgetId,
- Console.AnsiBlue);
- }
}
// If there is no id, then bind a new search app widget
@@ -263,13 +255,6 @@
Pair<Integer, AppWidgetProviderInfo> widgetInfo =
ssp.bindSearchAppWidget(mAppWidgetHost);
if (widgetInfo != null) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onCreate|searchWidget]",
- "Id: " + widgetInfo.first + " Info: " + widgetInfo.second,
- Console.AnsiBlue);
- }
-
// Save the app widget id into the settings
mConfig.updateSearchBarAppWidgetId(this, widgetInfo.first);
mSearchAppWidgetInfo = widgetInfo.second;
@@ -283,12 +268,6 @@
if (Constants.DebugFlags.App.EnableSearchLayout) {
int appWidgetId = mConfig.searchBarAppWidgetId;
if (appWidgetId >= 0) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onCreate|addSearchAppWidgetView]",
- "Id: " + appWidgetId,
- Console.AnsiBlue);
- }
mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
mSearchAppWidgetInfo);
Bundle opts = new Bundle();
@@ -305,28 +284,50 @@
}
/** Dismisses recents if we are already visible and the intent is to toggle the recents view */
- boolean dismissRecentsIfVisible() {
+ boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) {
if (mVisible) {
- // If we are mid-animation into Recents, then reverse it and finish
- if (mFullScreenOverlayView == null ||
- !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
- // If we have a focused task, then launch that task
- if (!mRecentsView.launchFocusedTask()) {
- if (mConfig.launchedFromHome) {
- // Just start the animation out of recents
- ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
- null, mFinishLaunchHomeRunnable, null);
- mRecentsView.startExitToHomeAnimation(
- new ViewAnimation.TaskViewExitContext(exitTrigger));
- } else {
- // Otherwise, try and launch the first task
- if (!mRecentsView.launchFirstTask()) {
- // If there are no tasks, then just finish recents
- mFinishLaunchHomeRunnable.run();
- }
- }
- }
+ // If we are mid-animation into Recents, reverse the animation now
+ if (mFullScreenOverlayView != null &&
+ mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) return true;
+ // If we currently have filtered stacks, then unfilter those first
+ if (checkFilteredStackState &&
+ mRecentsView.unfilterFilteredStacks()) return true;
+ // If we have a focused Task, launch that Task now
+ if (mRecentsView.launchFocusedTask()) return true;
+ // If we launched from Home, then return to Home
+ if (mConfig.launchedFromHome) {
+ dismissRecentsToHomeRaw(true);
+ return true;
}
+ // Otherwise, try and return to the first Task in the stack
+ if (mRecentsView.launchFirstTask()) return true;
+ // If none of the other cases apply, then just go Home
+ dismissRecentsToHomeRaw(true);
+ return true;
+ }
+ return false;
+ }
+
+ /** Dismisses Recents directly to Home. */
+ void dismissRecentsToHomeRaw(boolean animated) {
+ if (animated) {
+ ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
+ null, mFinishLaunchHomeRunnable, null);
+ mRecentsView.startExitToHomeAnimation(
+ new ViewAnimation.TaskViewExitContext(exitTrigger));
+ } else {
+ mFinishLaunchHomeRunnable.run();
+ }
+ }
+
+ /** Dismisses Recents directly to Home if we currently aren't transitioning. */
+ boolean dismissRecentsToHome(boolean animated) {
+ if (mVisible) {
+ // If we are mid-animation into Recents, reverse the animation now
+ if (mFullScreenOverlayView != null &&
+ mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) return true;
+ // Return to Home
+ dismissRecentsToHomeRaw(animated);
return true;
}
return false;
@@ -336,13 +337,6 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (Console.Enabled) {
- Console.logDivider(Constants.Log.App.SystemUIHandshake);
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onCreate]",
- getIntent().getAction() + " visible: " + mVisible, Console.AnsiRed);
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "onCreate");
- }
// Initialize the loader and the configuration
RecentsTaskLoader.initialize(this);
@@ -410,11 +404,13 @@
}
void onConfigurationChange() {
+ // Update RecentsConfiguration
+ mConfig = RecentsConfiguration.reinitialize(this);
+
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
mFullScreenOverlayView, t));
- // Call our callback
onEnterAnimationTriggered();
}
@@ -423,18 +419,6 @@
super.onNewIntent(intent);
setIntent(intent);
- if (Console.Enabled) {
- Console.logDivider(Constants.Log.App.SystemUIHandshake);
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onNewIntent]",
- intent.getAction() + " visible: " + mVisible, Console.AnsiRed);
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "onNewIntent");
- }
-
- // Initialize the loader and the configuration
- RecentsTaskLoader.initialize(this);
- mConfig = RecentsConfiguration.reinitialize(this);
-
// Update the recent tasks
updateRecentsTasks(intent);
@@ -446,10 +430,6 @@
@Override
protected void onStart() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStart]", "",
- Console.AnsiRed);
- }
super.onStart();
// Register the broadcast receiver to handle messages from our service
@@ -458,16 +438,10 @@
filter.addAction(ACTION_TOGGLE_RECENTS_ACTIVITY);
filter.addAction(ACTION_START_ENTER_ANIMATION);
registerReceiver(mServiceBroadcastReceiver, filter);
-
- mVisible = true;
}
@Override
protected void onResume() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onResume]", "",
- Console.AnsiRed);
- }
super.onResume();
// Start listening for widget package changes if there is one bound, post it since we don't
@@ -485,63 +459,29 @@
}
}, 1);
}
- }
- @Override
- public void onAttachedToWindow() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onAttachedToWindow]", "",
- Console.AnsiRed);
- }
- super.onAttachedToWindow();
- }
-
- @Override
- public void onDetachedFromWindow() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake,
- "[RecentsActivity|onDetachedFromWindow]", "",
- Console.AnsiRed);
- }
- super.onDetachedFromWindow();
- }
-
- @Override
- protected void onPause() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onPause]", "",
- Console.AnsiRed);
- }
- super.onPause();
+ // Mark Recents as visible
+ mVisible = true;
}
@Override
protected void onStop() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onStop]", "",
- Console.AnsiRed);
- }
super.onStop();
// Unregister the RecentsService receiver
unregisterReceiver(mServiceBroadcastReceiver);
// Stop listening for widget package changes if there was one bound
- if (mConfig.searchBarAppWidgetId >= 0) {
+ if (mAppWidgetHost.isListening()) {
mAppWidgetHost.stopListening();
}
}
@Override
protected void onDestroy() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsActivity|onDestroy]", "",
- Console.AnsiRed);
- }
super.onDestroy();
- // Unregister the screen off receiver
+ // Unregister the system broadcast receivers
unregisterReceiver(mSystemBroadcastReceiver);
RecentsTaskLoader.getInstance().unregisterReceivers();
}
@@ -583,26 +523,8 @@
// Test mode where back does not do anything
if (mConfig.debugModeEnabled) return;
- // If we are mid-animation into Recents, then reverse it and finish
- if (mFullScreenOverlayView == null ||
- !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
- // If we are currently filtering in any stacks, unfilter them first
- if (!mRecentsView.unfilterFilteredStacks()) {
- if (mConfig.launchedFromHome) {
- // Just start the animation out of recents
- ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
- null, mFinishLaunchHomeRunnable, null);
- mRecentsView.startExitToHomeAnimation(
- new ViewAnimation.TaskViewExitContext(exitTrigger));
- } else {
- // Otherwise, try and launch the first task
- if (!mRecentsView.launchFirstTask()) {
- // If there are no tasks, then just finish recents
- mFinishLaunchHomeRunnable.run();
- }
- }
- }
- }
+ // Dismiss Recents to the focused Task or Home
+ dismissRecentsToFocusedTaskOrHome(true);
}
/** Called when debug mode is triggered */
@@ -623,7 +545,7 @@
/** Called when the enter recents animation is triggered. */
public void onEnterAnimationTriggered() {
- // Animate the scrims in
+ // Animate the SystemUI scrim views
mScrimViews.startEnterRecentsAnimation();
}
@@ -644,7 +566,7 @@
@Override
public void onExitToHomeAnimationTriggered() {
- // Animate the scrims out
+ // Animate the SystemUI scrim views out
mScrimViews.startExitRecentsAnimation();
}
@@ -664,7 +586,6 @@
@Override
public void refreshSearchWidget() {
- // Load the Search widget again
bindSearchBarAppWidget();
addSearchBarAppWidgetView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
index 43d7a54..a63e167 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
@@ -33,6 +33,7 @@
Context mContext;
RecentsAppWidgetHostCallbacks mCb;
RecentsConfiguration mConfig;
+ boolean mIsListening;
public RecentsAppWidgetHost(Context context, int hostId) {
super(context, hostId);
@@ -42,6 +43,7 @@
public void startListening(RecentsAppWidgetHostCallbacks cb) {
mCb = cb;
+ mIsListening = true;
super.startListening();
}
@@ -51,6 +53,11 @@
// Ensure that we release any references to the callbacks
mCb = null;
mContext = null;
+ mIsListening = false;
+ }
+
+ public boolean isListening() {
+ return mIsListening;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index e62d989..439765e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -35,6 +35,7 @@
* NOTE: We should not hold any references to a Context from a static instance */
public class RecentsConfiguration {
static RecentsConfiguration sInstance;
+ static int sPrevConfigurationHashCode;
DisplayMetrics mDisplayMetrics;
@@ -138,7 +139,11 @@
if (sInstance == null) {
sInstance = new RecentsConfiguration(context);
}
- sInstance.update(context);
+ int configHashCode = context.getResources().getConfiguration().hashCode();
+ if (sPrevConfigurationHashCode != configHashCode) {
+ sInstance.update(context);
+ sPrevConfigurationHashCode = configHashCode;
+ }
return sInstance;
}
@@ -179,10 +184,8 @@
transposeRecentsLayoutWithOrientation =
res.getBoolean(R.bool.recents_transpose_layout_with_orientation);
- // Search bar
+ // Search Bar
searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
-
- // Update the search widget id
searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
// Task stack
@@ -242,12 +245,6 @@
// Nav bar scrim
navBarScrimEnterDuration =
res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration);
-
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.MeasureAndLayout,
- "[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
- Console.AnsiGreen);
- }
}
/** Updates the system insets */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
index 31825af..4c0ff48 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
@@ -72,7 +72,12 @@
/** Adds a runnable to the last-decrement runnables list. */
public void addLastDecrementRunnable(Runnable r) {
+ // To ensure that the last decrement always calls, we increment and decrement after setting
+ // the last decrement runnable
+ boolean ensureLastDecrement = (mCount == 0);
+ if (ensureLastDecrement) increment();
mLastDecRunnables.add(r);
+ if (ensureLastDecrement) decrement();
}
/** Decrements the ref count */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index b8beda6f..ced4043 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -31,6 +31,7 @@
import android.content.pm.ActivityInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@@ -80,6 +81,8 @@
ComponentName mAssistComponent;
Bitmap mDummyIcon;
+ int mDummyThumbnailWidth;
+ int mDummyThumbnailHeight;
Paint mBgProtectionPaint;
Canvas mBgProtectionCanvas;
@@ -96,6 +99,13 @@
mDisplay = mWm.getDefaultDisplay();
mRecentsPackage = context.getPackageName();
+ // Get the dummy thumbnail width/heights
+ Resources res = context.getResources();
+ int wId = com.android.internal.R.dimen.thumbnail_width;
+ int hId = com.android.internal.R.dimen.thumbnail_height;
+ mDummyThumbnailWidth = res.getDimensionPixelSize(wId);
+ mDummyThumbnailHeight = res.getDimensionPixelSize(hId);
+
// Create the protection paints
mBgProtectionPaint = new Paint();
mBgProtectionPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
@@ -213,7 +223,8 @@
// If we are mocking, then just return a dummy thumbnail
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
- Bitmap thumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ Bitmap thumbnail = Bitmap.createBitmap(mDummyThumbnailWidth, mDummyThumbnailHeight,
+ Bitmap.Config.ARGB_8888);
thumbnail.eraseColor(0xff333333);
return thumbnail;
}
@@ -239,6 +250,8 @@
*/
public static Bitmap getThumbnail(ActivityManager activityManager, int taskId) {
ActivityManager.TaskThumbnail taskThumbnail = activityManager.getTaskThumbnail(taskId);
+ if (taskThumbnail == null) return null;
+
Bitmap thumbnail = taskThumbnail.mainThumbnail;
ParcelFileDescriptor descriptor = taskThumbnail.thumbnailFileDescriptor;
if (thumbnail == null && descriptor != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index bda195b..607e155 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -16,16 +16,10 @@
package com.android.systemui.recents.misc;
-import android.app.ActivityManager;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.ParcelFileDescriptor;
import com.android.systemui.recents.RecentsConfiguration;
-import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -73,22 +67,25 @@
}
}
- /** Calculates the luminance-preserved greyscale of a given color. */
- public static int colorToGreyscale(int color) {
- return Math.round(0.2126f * Color.red(color) + 0.7152f * Color.green(color) +
- 0.0722f * Color.blue(color));
- }
+ /** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */
+ public static float computeContrastBetweenColors(int bg, int fg) {
+ float bgR = Color.red(bg) / 255f;
+ float bgG = Color.green(bg) / 255f;
+ float bgB = Color.blue(bg) / 255f;
+ bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f);
+ bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f);
+ bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f);
+ float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB;
+
+ float fgR = Color.red(fg) / 255f;
+ float fgG = Color.green(fg) / 255f;
+ float fgB = Color.blue(fg) / 255f;
+ fgR = (fgR < 0.03928f) ? fgR / 12.92f : (float) Math.pow((fgR + 0.055f) / 1.055f, 2.4f);
+ fgG = (fgG < 0.03928f) ? fgG / 12.92f : (float) Math.pow((fgG + 0.055f) / 1.055f, 2.4f);
+ fgB = (fgB < 0.03928f) ? fgB / 12.92f : (float) Math.pow((fgB + 0.055f) / 1.055f, 2.4f);
+ float fgL = 0.2126f * fgR + 0.7152f * fgG + 0.0722f * fgB;
- /** Returns the ideal color to draw on top of a specified background color. */
- public static int getIdealColorForBackgroundColorGreyscale(int greyscale, int lightRes,
- int darkRes) {
- return (greyscale < 128) ? lightRes : darkRes;
- }
- /** Returns the ideal drawable to draw on top of a specified background color. */
- public static Drawable getIdealResourceForBackgroundColorGreyscale(int greyscale,
- Drawable lightRes,
- Drawable darkRes) {
- return (greyscale < 128) ? lightRes : darkRes;
+ return Math.abs((fgL + 0.05f) / (bgL + 0.05f));
}
/** Sets some private shadow properties. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java
index 1344729..757c07f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/BitmapLruCache.java
@@ -29,6 +29,6 @@
@Override
protected int computeSize(Bitmap b) {
// The cache size will be measured in kilobytes rather than number of items
- return b.getAllocationByteCount() / 1024;
+ return b.getAllocationByteCount();
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java
index 61d19da..5b50358 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/DrawableLruCache.java
@@ -31,6 +31,6 @@
// The cache size will be measured in kilobytes rather than number of items
// NOTE: this isn't actually correct, as the icon may be smaller
int maxBytes = (d.getIntrinsicWidth() * d.getIntrinsicHeight() * 4);
- return maxBytes / 1024;
+ return maxBytes;
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java
index 3ccca9a2..5f4fabe 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java
@@ -73,11 +73,6 @@
return mCache.get(key);
}
- /** Gets the previous task key that matches the specified key. */
- final Task.TaskKey getKey(Task.TaskKey key) {
- return mKeys.get(key);
- }
-
/** Puts an entry in the cache for a specific key. */
final void put(Task.TaskKey key, V value) {
mCache.put(key, value);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
index 2d50659..31011ae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
@@ -25,7 +25,6 @@
import java.util.HashSet;
import java.util.List;
-import java.util.Set;
/**
* The package monitor listens for changes from PackageManager to update the contents of the Recents
@@ -33,7 +32,7 @@
*/
public class RecentsPackageMonitor extends PackageMonitor {
public interface PackageCallbacks {
- public void onComponentRemoved(Set<ComponentName> cns);
+ public void onComponentRemoved(HashSet<ComponentName> cns);
}
PackageCallbacks mCb;
@@ -45,7 +44,7 @@
mSystemServicesProxy = new SystemServicesProxy(context);
mCb = cb;
try {
- register(context, Looper.getMainLooper(), false);
+ register(context, Looper.getMainLooper(), true);
} catch (IllegalStateException e) {
e.printStackTrace();
}
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 854ea1c..71979c4f7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -27,38 +27,25 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.UserHandle;
-import android.util.Pair;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.SystemServicesProxy;
-import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/** A bitmap load queue */
class TaskResourceLoadQueue {
ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<Task>();
- ConcurrentHashMap<Task.TaskKey, Boolean> mForceLoadSet =
- new ConcurrentHashMap<Task.TaskKey, Boolean>();
-
- static final Boolean sFalse = new Boolean(false);
/** Adds a new task to the load queue */
- void addTask(Task t, boolean forceLoad) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|addTask]");
- }
+ void addTask(Task t) {
if (!mQueue.contains(t)) {
mQueue.add(t);
}
- if (forceLoad) {
- mForceLoadSet.put(t.key, new Boolean(true));
- }
synchronized(this) {
notifyAll();
}
@@ -68,37 +55,18 @@
* Retrieves the next task from the load queue, as well as whether we want that task to be
* force reloaded.
*/
- Pair<Task, Boolean> nextTask() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|nextTask]");
- }
- Task task = mQueue.poll();
- Boolean forceLoadTask = null;
- if (task != null) {
- forceLoadTask = mForceLoadSet.remove(task.key);
- }
- if (forceLoadTask == null) {
- forceLoadTask = sFalse;
- }
- return new Pair<Task, Boolean>(task, forceLoadTask);
+ Task nextTask() {
+ return mQueue.poll();
}
/** Removes a task from the load queue */
void removeTask(Task t) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|removeTask]");
- }
mQueue.remove(t);
- mForceLoadSet.remove(t.key);
}
/** Clears all the tasks from the load queue */
void clearTasks() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, " [TaskResourceLoadQueue|clearTasks]");
- }
mQueue.clear();
- mForceLoadSet.clear();
}
/** Returns whether the load queue is empty */
@@ -119,19 +87,20 @@
DrawableLruCache mApplicationIconCache;
BitmapLruCache mThumbnailCache;
Bitmap mDefaultThumbnail;
+ BitmapDrawable mDefaultApplicationIcon;
boolean mCancelled;
boolean mWaitingOnLoadQueue;
/** Constructor, creates a new loading thread that loads task resources in the background */
- public TaskResourceLoader(TaskResourceLoadQueue loadQueue,
- DrawableLruCache applicationIconCache,
- BitmapLruCache thumbnailCache,
- Bitmap defaultThumbnail) {
+ public TaskResourceLoader(TaskResourceLoadQueue loadQueue, DrawableLruCache applicationIconCache,
+ BitmapLruCache thumbnailCache, Bitmap defaultThumbnail,
+ BitmapDrawable defaultApplicationIcon) {
mLoadQueue = loadQueue;
mApplicationIconCache = applicationIconCache;
mThumbnailCache = thumbnailCache;
mDefaultThumbnail = defaultThumbnail;
+ mDefaultApplicationIcon = defaultApplicationIcon;
mMainThreadHandler = new Handler();
mLoadThread = new HandlerThread("Recents-TaskResourceLoader");
mLoadThread.setPriority(Thread.NORM_PRIORITY - 1);
@@ -142,9 +111,6 @@
/** Restarts the loader thread */
void start(Context context) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|start]");
- }
mContext = context;
mCancelled = false;
mSystemServicesProxy = new SystemServicesProxy(context);
@@ -156,9 +122,6 @@
/** Requests the loader thread to stop after the current iteration */
void stop() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, "[TaskResourceLoader|stop]");
- }
// Mark as cancelled for the thread to pick up
mCancelled = true;
mSystemServicesProxy = null;
@@ -172,25 +135,13 @@
@Override
public void run() {
while (true) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[TaskResourceLoader|run|" + Thread.currentThread().getId() + "]");
- }
if (mCancelled) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[TaskResourceLoader|cancel|" + Thread.currentThread().getId() + "]");
- }
// We have to unset the context here, since the background thread may be using it
// when we call stop()
mContext = null;
// If we are cancelled, then wait until we are started again
synchronized(mLoadThread) {
try {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[TaskResourceLoader|waitOnLoadThreadCancelled]");
- }
mLoadThread.wait();
} catch (InterruptedException ie) {
ie.printStackTrace();
@@ -200,59 +151,38 @@
SystemServicesProxy ssp = mSystemServicesProxy;
// Load the next item from the queue
- Pair<Task, Boolean> nextTaskData = mLoadQueue.nextTask();
- final Task t = nextTaskData.first;
- final boolean forceLoadTask = nextTaskData.second;
+ final Task t = mLoadQueue.nextTask();
if (t != null) {
- Drawable loadIcon = mApplicationIconCache.getCheckLastActiveTime(t.key);
- Bitmap loadThumbnail = mThumbnailCache.getCheckLastActiveTime(t.key);
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- " [TaskResourceLoader|load]",
- t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
- " forceLoad: " + forceLoadTask);
- }
- // Load the application icon
- if (loadIcon == null || forceLoadTask) {
+ Drawable cachedIcon = mApplicationIconCache.getCheckLastActiveTime(t.key);
+ Bitmap cachedThumbnail = mThumbnailCache.getCheckLastActiveTime(t.key);
+ // Load the application icon if it is stale or we haven't cached one yet
+ if (cachedIcon == null) {
+ Drawable icon = null;
ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
t.userId);
- Drawable icon = ssp.getActivityIcon(info, t.userId);
- if (!mCancelled) {
- if (icon != null) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- " [TaskResourceLoader|loadIcon]", icon);
- }
- loadIcon = icon;
- mApplicationIconCache.put(t.key, icon);
- }
+ if (info != null) {
+ icon = ssp.getActivityIcon(info, t.userId);
}
+ // If we can't load the icon, then set the default application icon into the
+ // cache. This will remain until the task's last active time is updated.
+ cachedIcon = icon != null ? icon : mDefaultApplicationIcon;
+ mApplicationIconCache.put(t.key, cachedIcon);
}
- // Load the thumbnail
- if (loadThumbnail == null || forceLoadTask) {
+ // Load the thumbnail if it is stale or we haven't cached one yet
+ if (cachedThumbnail == null) {
Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
- if (!mCancelled) {
- if (thumbnail != null) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- " [TaskResourceLoader|loadThumbnail]", thumbnail);
- }
- thumbnail.setHasAlpha(false);
- loadThumbnail = thumbnail;
- } else {
- loadThumbnail = mDefaultThumbnail;
- Console.logError(mContext,
- "Failed to load task top thumbnail for: " +
- t.key.baseIntent.getComponent().getPackageName());
- }
- // We put the default thumbnail in the cache anyways
- mThumbnailCache.put(t.key, loadThumbnail);
+ if (thumbnail != null) {
+ thumbnail.setHasAlpha(false);
}
+ // Even if we can't load the icon, we set the default thumbnail into the
+ // cache. This will remain until the task's last active time is updated.
+ cachedThumbnail = thumbnail != null ? thumbnail : mDefaultThumbnail;
+ mThumbnailCache.put(t.key, cachedThumbnail);
}
if (!mCancelled) {
// Notify that the task data has changed
- final Drawable newIcon = loadIcon;
- final Bitmap newThumbnail = loadThumbnail;
+ final Drawable newIcon = cachedIcon;
+ final Bitmap newThumbnail = cachedThumbnail;
mMainThreadHandler.post(new Runnable() {
@Override
public void run() {
@@ -266,10 +196,6 @@
if (!mCancelled && mLoadQueue.isEmpty()) {
synchronized(mLoadQueue) {
try {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[TaskResourceLoader|waitOnLoadQueue]");
- }
mWaitingOnLoadQueue = true;
mLoadQueue.wait();
mWaitingOnLoadQueue = false;
@@ -306,22 +232,16 @@
/** Private Constructor */
private RecentsTaskLoader(Context context) {
// Calculate the cache sizes, we just use a reasonable number here similar to those
- // suggested in the Android docs, 1/8th for the thumbnail cache and 1/32 of the max memory
+ // suggested in the Android docs, 1/6th for the thumbnail cache and 1/30 of the max memory
// for icons.
- int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
- mMaxThumbnailCacheSize = maxMemory / 8;
- mMaxIconCacheSize = mMaxThumbnailCacheSize / 4;
+ int maxMemory = (int) Runtime.getRuntime().maxMemory();
+ mMaxThumbnailCacheSize = maxMemory / 6;
+ mMaxIconCacheSize = mMaxThumbnailCacheSize / 5;
int iconCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 :
mMaxIconCacheSize;
int thumbnailCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 :
mMaxThumbnailCacheSize;
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
- " iconCache: " + iconCacheSize);
- }
-
// Create the default assets
Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
icon.eraseColor(0x00000000);
@@ -340,14 +260,7 @@
mApplicationIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
mLoader = new TaskResourceLoader(mLoadQueue, mApplicationIconCache, mThumbnailCache,
- mDefaultThumbnail);
-
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|defaultBitmaps]",
- "icon: " + mDefaultApplicationIcon +
- " default thumbnail: " + mDefaultThumbnail, Console.AnsiRed);
- }
+ mDefaultThumbnail, mDefaultApplicationIcon);
}
/** Initializes the recents task loader */
@@ -369,32 +282,18 @@
}
private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp) {
- long t1 = System.currentTimeMillis();
-
List<ActivityManager.RecentTaskInfo> tasks =
ssp.getRecentTasks(50, UserHandle.CURRENT.getIdentifier());
Collections.reverse(tasks);
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TimeSystemCalls,
- "[RecentsTaskLoader|getRecentTasks]",
- "" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|tasks]", "" + tasks.size());
- }
return tasks;
}
/** Reload the set of recent tasks */
public SpaceNode reload(Context context, int preloadCount) {
- long t1 = System.currentTimeMillis();
-
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
- }
RecentsConfiguration config = RecentsConfiguration.getInstance();
Resources res = context.getResources();
- ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
+ LinkedHashSet<Task> tasksToLoad = new LinkedHashSet<Task>();
TaskStack stack = new TaskStack();
SpaceNode root = new SpaceNode();
root.setStack(stack);
@@ -404,7 +303,6 @@
List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp);
// Add each task to the task stack
- t1 = System.currentTimeMillis();
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
ActivityManager.RecentTaskInfo t = tasks.get(i);
@@ -434,37 +332,28 @@
// Preload the specified number of apps
if (i >= (taskCount - preloadCount)) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|preloadTask]",
- "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
- }
-
// Load the icon from the cache if possible
task.applicationIcon = mApplicationIconCache.getCheckLastActiveTime(task.key);
if (task.applicationIcon == null) {
if (isForemostTask) {
// We force loading the application icon for the foremost task
task.applicationIcon = ssp.getActivityIcon(info, task.userId);
- if (task.applicationIcon != null) {
- mApplicationIconCache.put(task.key, task.applicationIcon);
- } else {
+ if (task.applicationIcon == null) {
task.applicationIcon = mDefaultApplicationIcon;
}
+ // Even if we can't load the icon we set the default application icon into
+ // the cache. This will remain until the task's last active time is updated.
+ mApplicationIconCache.put(task.key, task.applicationIcon);
} else {
- // Either the task has updated, or we haven't cached any information for the
- // task, so reload it
- tasksToForceLoad.add(task);
+ // Either the task has changed since the last active time, or it was not
+ // previously cached, so try and load the task anew.
+ tasksToLoad.add(task);
}
}
// Load the thumbnail (if possible and not the foremost task, from the cache)
task.thumbnail = mThumbnailCache.getCheckLastActiveTime(task.key);
if (task.thumbnail == null) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|loadingTaskThumbnail]");
- }
if (isForemostTask) {
// We force loading the thumbnail icon for the foremost task
task.thumbnail = ssp.getTaskThumbnail(task.key.id);
@@ -473,37 +362,30 @@
} else {
task.thumbnail = mDefaultThumbnail;
}
+ // Even if we can't load the thumbnail we set the default thumbnail into
+ // the cache. This will remain until the task's last active time is updated.
mThumbnailCache.put(task.key, task.thumbnail);
} else {
- // Either the task has updated, or we haven't cached any information for the
- // task, so reload it
- tasksToForceLoad.add(task);
+ // Either the task has changed since the last active time, or it was not
+ // previously cached, so try and load the task anew.
+ tasksToLoad.add(task);
}
}
}
// Add the task to the stack
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
- }
stack.addTask(task);
}
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TimeSystemCalls,
- "[RecentsTaskLoader|getAllTaskTopThumbnail]",
- "" + (System.currentTimeMillis() - t1) + "ms");
- }
// Simulate the groupings that we describe
- stack.createSimulatedAffiliatedGroupings();
+ stack.createAffiliatedGroupings();
// Start the task loader
mLoader.start(context);
- // Add all the tasks that we are force/re-loading
- for (Task t : tasksToForceLoad) {
- mLoadQueue.addTask(t, true);
+ // Add all the tasks that we are reloading
+ for (Task t : tasksToLoad) {
+ mLoadQueue.addTask(t);
}
// Update the package monitor with the list of packages to listen for
@@ -526,7 +408,7 @@
stack.addTask(new Task(t.persistentId, true, t.baseIntent, t.affiliatedTaskId, null,
null, 0, 0, t.firstActiveTime, t.lastActiveTime, (i == (taskCount - 1))));
}
- stack.createSimulatedAffiliatedGroupings();
+ stack.createAffiliatedGroupings();
return stack;
}
@@ -535,12 +417,6 @@
Drawable applicationIcon = mApplicationIconCache.get(t.key);
Bitmap thumbnail = mThumbnailCache.get(t.key);
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]",
- t + " applicationIcon: " + applicationIcon + " thumbnail: " + thumbnail +
- " thumbnailCacheSize: " + mThumbnailCache.size());
- }
-
boolean requiresLoad = false;
if (applicationIcon == null) {
applicationIcon = mDefaultApplicationIcon;
@@ -551,30 +427,19 @@
requiresLoad = true;
}
if (requiresLoad) {
- mLoadQueue.addTask(t, false);
+ mLoadQueue.addTask(t);
}
t.notifyTaskDataLoaded(thumbnail, applicationIcon);
}
/** Releases the task resource data back into the pool. */
public void unloadTaskData(Task t) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|unloadTask]", t +
- " thumbnailCacheSize: " + mThumbnailCache.size());
- }
-
mLoadQueue.removeTask(t);
t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
}
/** Completely removes the resource data from the pool. */
public void deleteTaskData(Task t, boolean notifyTaskDataUnloaded) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader,
- "[RecentsTaskLoader|deleteTask]", t);
- }
-
mLoadQueue.removeTask(t);
mThumbnailCache.remove(t.key);
mApplicationIconCache.remove(t.key);
@@ -585,9 +450,6 @@
/** Stops the task loader and clears all pending tasks */
void stopLoader() {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.TaskDataLoader, "[RecentsTaskLoader|stopLoader]");
- }
mLoader.stop();
mLoadQueue.clearTasks();
}
@@ -608,11 +470,6 @@
* out of memory.
*/
public void onTrimMemory(int level) {
- if (Console.Enabled) {
- Console.log(Constants.Log.App.Memory, "[RecentsTaskLoader|onTrimMemory]",
- Console.trimMemoryLevelToString(level));
- }
-
switch (level) {
case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
// Stop the loader immediately when the UI is no longer visible
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 88e9f40..1670735 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -18,6 +18,7 @@
import android.content.Intent;
import android.graphics.Bitmap;
+import android.graphics.Color;
import android.graphics.drawable.Drawable;
import com.android.systemui.recents.misc.Utilities;
@@ -84,7 +85,7 @@
public Drawable activityIcon;
public String activityLabel;
public int colorPrimary;
- public int colorPrimaryGreyscale;
+ public boolean useLightOnPrimaryColor;
public Bitmap thumbnail;
public boolean isActive;
public boolean canLockToTask;
@@ -104,7 +105,8 @@
this.activityLabel = activityTitle;
this.activityIcon = activityIcon;
this.colorPrimary = colorPrimary;
- this.colorPrimaryGreyscale = Utilities.colorToGreyscale(colorPrimary);
+ this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(colorPrimary,
+ Color.WHITE) > 3f;
this.isActive = isActive;
this.canLockToTask = canLockToTask;
this.userId = userId;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 7dd15a6..13fbe64 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -204,8 +204,8 @@
removeGroup(group);
}
// Update the lock-to-app state
- Task newFrontMostTask = getFrontMostTask();
t.canLockToTask = false;
+ Task newFrontMostTask = getFrontMostTask();
if (newFrontMostTask != null) {
newFrontMostTask.canLockToTask = true;
}
@@ -320,7 +320,7 @@
/**
* Temporary: This method will simulate affiliation groups by
*/
- public void createSimulatedAffiliatedGroupings() {
+ public void createAffiliatedGroupings() {
if (Constants.DebugFlags.App.EnableSimulatedTaskGroups) {
HashMap<Task.TaskKey, Task> taskMap = new HashMap<Task.TaskKey, Task>();
// Sort all tasks by increasing firstActiveTime of the task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
new file mode 100644
index 0000000..3adee0ea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+/**
+ * This is an optimized ImageView that does not trigger a requestLayout() or invalidate() when
+ * setting the image to Null.
+ */
+public class FixedSizeImageView extends ImageView {
+
+ int mFixedWidth;
+ int mFixedHeight;
+ boolean mAllowRelayout = true;
+ boolean mAllowInvalidate = true;
+
+ public FixedSizeImageView(Context context) {
+ this(context, null);
+ }
+
+ public FixedSizeImageView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FixedSizeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public FixedSizeImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ mFixedWidth = getMeasuredWidth();
+ mFixedHeight = getMeasuredHeight();
+ }
+
+ @Override
+ public void requestLayout() {
+ if (mAllowRelayout) {
+ super.requestLayout();
+ }
+ }
+
+ @Override
+ public void invalidate() {
+ if (mAllowInvalidate) {
+ super.invalidate();
+ }
+ }
+
+ @Override
+ public void setImageDrawable(Drawable drawable) {
+ if (drawable == null || (mFixedWidth > 0 && mFixedHeight > 0)) {
+ mAllowRelayout = false;
+ mAllowInvalidate = false;
+ }
+ super.setImageDrawable(drawable);
+ mAllowRelayout = true;
+ mAllowInvalidate = true;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
index 57b8ea4..63f59be 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
@@ -22,8 +22,6 @@
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
@@ -34,9 +32,7 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.misc.Console;
/**
@@ -152,11 +148,6 @@
public void prepareAnimateOnEnterRecents(Bitmap screenshot) {
if (!mConfig.launchedFromAppWithScreenshot) return;
- if (Console.Enabled) {
- Console.logStartTracingTime(Constants.Log.App.TimeRecentsScreenshotTransition,
- Constants.Log.App.TimeRecentsScreenshotTransitionKey);
- }
-
setClipTop(0);
setClipBottom(getMeasuredHeight());
setDim(0);
@@ -180,11 +171,6 @@
/** Animates this view as it enters recents */
public void animateOnEnterRecents(ViewAnimation.TaskViewEnterContext ctx,
final Runnable postAnimRunnable) {
- if (Console.Enabled) {
- Console.logTraceTime(Constants.Log.App.TimeRecentsScreenshotTransition,
- Constants.Log.App.TimeRecentsScreenshotTransitionKey, "Starting");
- }
-
// Cancel the current animation
if (mEnterAnimation != null) {
mEnterAnimation.removeAllListeners();
@@ -226,11 +212,6 @@
mCb.onEnterAnimationComplete();
// Run the given post-anim runnable
postAnimRunnable.run();
-
- if (Console.Enabled) {
- Console.logTraceTime(Constants.Log.App.TimeRecentsScreenshotTransition,
- Constants.Log.App.TimeRecentsScreenshotTransitionKey, "Completed");
- }
}
});
}
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 99b012e..78a99e0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -45,7 +45,7 @@
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
-import java.util.Set;
+import java.util.HashSet;
/**
* This view is the the top level layout that contains TaskStacks (which are laid out according
@@ -141,20 +141,12 @@
TaskView tv = (TaskView) stackView.getChildAt(j);
Task task = tv.getTask();
if (tv.isFocusedTask()) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
- "Found focused Task");
- }
onTaskViewClicked(stackView, tv, stack, task, false);
return true;
}
}
}
}
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.Focus, "[RecentsView|launchFocusedTask]",
- "No Tasks focused");
- }
return false;
}
@@ -191,10 +183,6 @@
/** Requests all task stacks to start their enter-recents animation */
public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
- // Handle the case when there are no views by incrementing and decrementing after all
- // animations are started.
- ctx.postAnimationTrigger.increment();
-
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -203,18 +191,10 @@
stackView.startEnterRecentsAnimation(ctx);
}
}
-
- // Handle the case when there are no views by incrementing and decrementing after all
- // animations are started.
- ctx.postAnimationTrigger.decrement();
}
/** Requests all task stacks to start their exit-recents animation */
public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
- // Handle the case when there are no views by incrementing and decrementing after all
- // animations are started.
- ctx.postAnimationTrigger.increment();
-
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -224,10 +204,6 @@
}
}
- // Handle the case when there are no views by incrementing and decrementing after all
- // animations are started.
- ctx.postAnimationTrigger.decrement();
-
// Notify of the exit animation
mCb.onExitToHomeAnimationTriggered();
}
@@ -244,12 +220,6 @@
if (searchBar != null) {
mSearchBar = searchBar;
addView(mSearchBar);
-
- if (Console.Enabled) {
- Console.log(Constants.Log.App.SystemUIHandshake, "[RecentsView|setSearchBar]",
- "" + (mSearchBar.getVisibility() == View.VISIBLE),
- Console.AnsiBlue);
- }
}
}
}
@@ -276,13 +246,6 @@
int height = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|measure]",
- "width: " + width + " height: " + height, Console.AnsiGreen);
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
- }
-
// Get the search bar bounds and measure the search bar layout
if (mSearchBar != null) {
Rect searchBarSpaceBounds = new Rect();
@@ -319,13 +282,6 @@
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.MeasureAndLayout, "[RecentsView|layout]",
- new Rect(left, top, right, bottom) + " changed: " + changed, Console.AnsiGreen);
- Console.logTraceTime(Constants.Log.App.TimeRecentsStartup,
- Constants.Log.App.TimeRecentsStartupKey, "RecentsView.onLayout");
- }
-
// Get the search bar bounds so that we lay it out
if (mSearchBar != null) {
Rect searchBarSpaceBounds = new Rect();
@@ -367,11 +323,6 @@
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.MeasureAndLayout,
- "[RecentsView|fitSystemWindows]", "insets: " + insets, Console.AnsiGreen);
- }
-
// Update the configuration with the latest system insets and trigger a relayout
mConfig.updateSystemInsets(insets.getSystemWindowInsets());
requestLayout();
@@ -498,11 +449,6 @@
final Runnable launchRunnable = new Runnable() {
@Override
public void run() {
- if (Console.Enabled) {
- Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey, "preStartActivity");
- }
-
if (task.isActive) {
// Bring an active task to the foreground
RecentsTaskLoader.getInstance().getSystemServicesProxy()
@@ -510,9 +456,11 @@
} else {
// Launch the activity anew with the desired animation
Intent i = new Intent(task.key.baseIntent);
- i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
- | Intent.FLAG_ACTIVITY_TASK_ON_HOME
- | Intent.FLAG_ACTIVITY_NEW_TASK);
+ i.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
+ | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+ if ((i.getFlags() & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == 0) {
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
try {
UserHandle taskUser = new UserHandle(task.userId);
if (launchOpts != null) {
@@ -531,19 +479,9 @@
// And clean up the old task
onTaskViewDismissed(task);
}
-
- if (Console.Enabled) {
- Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey, "startActivity");
- }
}
};
- if (Console.Enabled) {
- Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
- Constants.Log.App.TimeRecentsLaunchKey, "onTaskLaunched");
- }
-
// Launch the app right away if there is no task view, otherwise, animate the icon out first
if (tv == null) {
post(launchRunnable);
@@ -615,7 +553,7 @@
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
- public void onComponentRemoved(Set<ComponentName> cns) {
+ public void onComponentRemoved(HashSet<ComponentName> cns) {
// Propagate this event down to each task stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
index 8409227a..e0298ab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SwipeHelper.java
@@ -28,8 +28,6 @@
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.LinearInterpolator;
-import com.android.systemui.recents.misc.Console;
-import com.android.systemui.recents.Constants;
/**
* This class facilitates swipe to dismiss. It defines an interface to be implemented by the
@@ -178,11 +176,6 @@
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[SwipeHelper|interceptTouchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
- }
final int action = ev.getAction();
switch (action) {
@@ -294,12 +287,6 @@
}
public boolean onTouchEvent(MotionEvent ev) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[SwipeHelper|touchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
- }
-
if (!mDragging) {
if (!onInterceptTouchEvent(ev)) {
return mCanCurrViewBeDimissed;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index db84962..deb9df3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -162,11 +162,10 @@
}
// Try and apply the system ui tint
setBackgroundColor(t.colorPrimary);
- mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColorGreyscale(
- t.colorPrimaryGreyscale, mConfig.taskBarViewLightTextColor,
- mConfig.taskBarViewDarkTextColor));
- mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColorGreyscale(
- t.colorPrimaryGreyscale, mLightDismissDrawable, mDarkDismissDrawable));
+ mActivityDescription.setTextColor(t.useLightOnPrimaryColor ?
+ mConfig.taskBarViewLightTextColor : mConfig.taskBarViewDarkTextColor);
+ mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
+ mLightDismissDrawable : mDarkDismissDrawable);
}
/** Unbinds the bar view from the task */
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 599c590..0b35f59 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -23,9 +23,8 @@
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Paint;
import android.graphics.Rect;
-import android.graphics.Region;
-import android.os.SystemClock;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -45,7 +44,7 @@
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Set;
+import java.util.HashSet;
/* The visual representation of a task stack view */
@@ -83,6 +82,7 @@
int mFocusedTaskIndex = -1;
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
+ boolean mEnableStackClipping = true;
// Optimizations
ReferenceCountedTrigger mHwLayersTrigger;
@@ -167,12 +167,9 @@
requestSynchronizeStackViewsWithModel(0);
}
void requestSynchronizeStackViewsWithModel(int duration) {
- if (Console.Enabled) {
- Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
- "[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
- }
if (!mStackViewsDirty) {
invalidate(mStackAlgorithm.mStackRect);
+ mStackViewsDirty = true;
}
if (mAwaitingFirstLayout) {
// Skip the animation if we are awaiting first layout
@@ -180,7 +177,6 @@
} else {
mStackViewsAnimationDuration = Math.max(mStackViewsAnimationDuration, duration);
}
- mStackViewsDirty = true;
}
/** Returns a mapping of child view to Task. */
@@ -266,11 +262,6 @@
if (visibleRangeOut != null) {
visibleRangeOut[0] = frontMostVisibleIndex;
visibleRangeOut[1] = backMostVisibleIndex;
- if (Console.Enabled) {
- Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
- "[TaskStackView|updateStackTransforms]",
- "Back: " + backMostVisibleIndex + " Front: " + frontMostVisibleIndex);
- }
}
}
@@ -290,11 +281,6 @@
/** Synchronizes the views with the model */
void synchronizeStackViewsWithModel() {
- if (Console.Enabled) {
- Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
- "[TaskStackView|synchronizeViewsWithModel]",
- "mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
- }
if (mStackViewsDirty) {
// Get all the task transforms
ArrayList<Task> tasks = mStack.getTasks();
@@ -302,7 +288,6 @@
int[] visibleRange = mTmpVisibleRange;
updateStackTransforms(mCurrentTaskTransforms, tasks, stackScroll, visibleRange, false);
TaskViewTransform tmpTransform = new TaskViewTransform();
- TaskStack.GroupTaskIndex gti = new TaskStack.GroupTaskIndex();
// Return all the invisible children to the pool
HashMap<Task, TaskView> taskChildViewMap = getTaskChildViewMap();
@@ -345,16 +330,66 @@
mStackViewsAnimationDuration);
}
- if (Console.Enabled) {
- Console.log(Constants.Log.TaskStack.SynchronizeViewsWithModel,
- " [TaskStackView|viewChildren]", "" + getChildCount());
- }
-
mStackViewsAnimationDuration = 0;
mStackViewsDirty = false;
}
}
+ /** Updates the clip for each of the task views. */
+ void clipTaskViews() {
+ // Update the clip on each task child
+ if (Constants.DebugFlags.App.EnableTaskStackClipping && mEnableStackClipping) {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount - 1; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ TaskView nextTv = null;
+ TaskView tmpTv = null;
+ int clipBottom = 0;
+ if (tv.shouldClipViewInStack()) {
+ // Find the next view to clip against
+ int nextIndex = i;
+ while (nextIndex < getChildCount()) {
+ tmpTv = (TaskView) getChildAt(++nextIndex);
+ if (tmpTv != null && tmpTv.shouldClipViewInStack()) {
+ nextTv = tmpTv;
+ break;
+ }
+ }
+
+ // Clip against the next view, this is just an approximation since we are
+ // stacked and we can make assumptions about the visibility of the this
+ // task relative to the ones in front of it.
+ if (nextTv != null) {
+ // We calculate the bottom clip independent of the footer (since we animate
+ // that)
+ int scaledMaxFooterHeight = (int) (tv.getMaxFooterHeight() * tv.getScaleX());
+ tv.getHitRect(mTmpRect);
+ nextTv.getHitRect(mTmpRect2);
+ clipBottom = (mTmpRect.bottom - scaledMaxFooterHeight - mTmpRect2.top);
+ }
+ }
+ tv.setClipFromBottom(clipBottom);
+ }
+ }
+ if (getChildCount() > 0) {
+ // The front most task should never be clipped
+ TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
+ tv.setClipFromBottom(0);
+ }
+ }
+
+ /** Enables/Disables clipping of the tasks in the stack. */
+ void setStackClippingEnabled(boolean stackClippingEnabled) {
+ if (!stackClippingEnabled) {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.setClipFromBottom(0);
+ }
+ }
+ mEnableStackClipping = stackClippingEnabled;
+ }
+
/** Sets the current stack scroll */
public void setStackScroll(int value) {
mStackScroll = value;
@@ -497,11 +532,6 @@
mMaxScroll = mStackAlgorithm.mMaxScroll;
// Debug logging
- if (Constants.Log.UI.MeasureAndLayout) {
- Console.log(" [TaskStack|minScroll] " + mMinScroll);
- Console.log(" [TaskStack|maxScroll] " + mMaxScroll);
- }
-
if (boundScrollToNewMinMax) {
boundScroll();
}
@@ -523,9 +553,6 @@
/** Focuses the task at the specified index in the stack */
void focusTask(int taskIndex, boolean scrollToNewPosition) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "" + taskIndex);
- }
if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
mFocusedTaskIndex = taskIndex;
@@ -535,9 +562,6 @@
Runnable postScrollRunnable = null;
if (tv != null) {
tv.setFocusedTask();
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]", "Requesting focus");
- }
} else {
postScrollRunnable = new Runnable() {
@Override
@@ -546,10 +570,6 @@
TaskView tv = getChildViewForTask(t);
if (tv != null) {
tv.setFocusedTask();
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusTask]",
- "Requesting focus after scroll animation");
- }
}
}
};
@@ -571,11 +591,6 @@
/** Focuses the next task in the stack */
void focusNextTask(boolean forward) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.Focus, "[TaskStackView|focusNextTask]", "" +
- mFocusedTaskIndex);
- }
-
// Find the next index to focus
int numTasks = mStack.getTaskCount();
if (mFocusedTaskIndex < 0) {
@@ -590,24 +605,12 @@
/** Enables the hw layers and increments the hw layer requirement ref count */
void addHwLayersRefCount(String reason) {
- if (Console.Enabled) {
- int refCount = mHwLayersTrigger.getCount();
- Console.log(Constants.Log.UI.HwLayers,
- "[TaskStackView|addHwLayersRefCount] refCount: " +
- refCount + "->" + (refCount + 1) + " " + reason);
- }
mHwLayersTrigger.increment();
}
/** Decrements the hw layer requirement ref count and disables the hw layers when we don't
need them anymore. */
void decHwLayersRefCount(String reason) {
- if (Console.Enabled) {
- int refCount = mHwLayersTrigger.getCount();
- Console.log(Constants.Log.UI.HwLayers,
- "[TaskStackView|decHwLayersRefCount] refCount: " +
- refCount + "->" + (refCount - 1) + " " + reason);
- }
mHwLayersTrigger.decrement();
}
@@ -625,7 +628,6 @@
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
setStackScroll(mScroller.getCurrY());
- invalidate(mStackAlgorithm.mStackRect);
// If we just finished scrolling, then disable the hw layers
if (mScroller.isFinished()) {
@@ -636,55 +638,11 @@
@Override
public void dispatchDraw(Canvas canvas) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.Draw, "[TaskStackView|dispatchDraw]", "",
- Console.AnsiPurple);
- }
synchronizeStackViewsWithModel();
+ clipTaskViews();
super.dispatchDraw(canvas);
}
- @Override
- protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
- if (Constants.DebugFlags.App.EnableTaskStackClipping) {
- TaskView tv = (TaskView) child;
- TaskView nextTv = null;
- TaskView tmpTv = null;
- if (tv.shouldClipViewInStack()) {
- int curIndex = indexOfChild(tv);
-
- // Find the next view to clip against
- while (nextTv == null && curIndex < getChildCount()) {
- tmpTv = (TaskView) getChildAt(++curIndex);
- if (tmpTv != null && tmpTv.shouldClipViewInStack()) {
- nextTv = tmpTv;
- }
- }
-
- // Clip against the next view (if we aren't animating its alpha)
- if (nextTv != null) {
- Rect curRect = tv.getClippingRect(mTmpRect);
- Rect nextRect = nextTv.getClippingRect(mTmpRect2);
- // The hit rects are relative to the task view, which needs to be offset by
- // the system bar height
- curRect.offset(0, mConfig.systemInsets.top);
- nextRect.offset(0, mConfig.systemInsets.top);
- // Compute the clip region
- Region clipRegion = new Region();
- clipRegion.op(curRect, Region.Op.UNION);
- clipRegion.op(nextRect, Region.Op.DIFFERENCE);
- // Clip the canvas
- int saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
- canvas.clipRegion(clipRegion);
- boolean invalidate = super.drawChild(canvas, child, drawingTime);
- canvas.restoreToCount(saveCount);
- return invalidate;
- }
- }
- }
- return super.drawChild(canvas, child, drawingTime);
- }
-
/** Computes the stack and task rects */
public void computeRects(int width, int height, int insetLeft, int insetBottom) {
// Compute the rects in the stack algorithm
@@ -703,25 +661,12 @@
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|measure]",
- "width: " + width + " height: " + height +
- " awaitingFirstLayout: " + mAwaitingFirstLayout, Console.AnsiGreen);
- }
// Compute our stack/task rects
Rect taskStackBounds = new Rect();
mConfig.getTaskStackBounds(width, height, taskStackBounds);
computeRects(width, height, taskStackBounds.left, mConfig.systemInsets.bottom);
- // Debug logging
- if (Constants.Log.UI.MeasureAndLayout) {
- Console.log(" [TaskStack|fullRect] " + mStackAlgorithm.mRect);
- Console.log(" [TaskStack|stackRect] " + mStackAlgorithm.mStackRect);
- Console.log(" [TaskStack|stackRectSansPeek] " + mStackAlgorithm.mStackRectSansPeek);
- Console.log(" [TaskStack|taskRect] " + mStackAlgorithm.mTaskRect);
- }
-
// If this is the first layout, then scroll to the front of the stack and synchronize the
// stack views immediately
if (mAwaitingFirstLayout) {
@@ -736,7 +681,7 @@
TaskView t = (TaskView) getChildAt(i);
t.measure(MeasureSpec.makeMeasureSpec(mStackAlgorithm.mTaskRect.width(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mStackAlgorithm.mTaskRect.height() +
- mConfig.taskViewLockToAppButtonHeight, MeasureSpec.EXACTLY));
+ t.getMaxFooterHeight(), MeasureSpec.EXACTLY));
}
setMeasuredDimension(width, height);
@@ -749,26 +694,13 @@
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.MeasureAndLayout, "[TaskStackView|layout]",
- "" + new Rect(left, top, right, bottom), Console.AnsiGreen);
- }
-
- // Debug logging
- if (Constants.Log.UI.MeasureAndLayout) {
- Console.log(" [TaskStack|fullRect] " + mStackAlgorithm.mRect);
- Console.log(" [TaskStack|stackRect] " + mStackAlgorithm.mStackRect);
- Console.log(" [TaskStack|stackRectSansPeek] " + mStackAlgorithm.mStackRectSansPeek);
- Console.log(" [TaskStack|taskRect] " + mStackAlgorithm.mTaskRect);
- }
-
// Layout each of the children
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView t = (TaskView) getChildAt(i);
t.layout(mStackAlgorithm.mTaskRect.left, mStackAlgorithm.mStackRectSansPeek.top,
mStackAlgorithm.mTaskRect.right, mStackAlgorithm.mStackRectSansPeek.top +
- mStackAlgorithm.mTaskRect.height() + mConfig.taskViewLockToAppButtonHeight);
+ mStackAlgorithm.mTaskRect.height() + t.getMaxFooterHeight());
}
if (mAwaitingFirstLayout) {
@@ -1021,19 +953,12 @@
@Override
public TaskView createView(Context context) {
- if (Console.Enabled) {
- Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|createPoolView]");
- }
return (TaskView) mInflater.inflate(R.layout.recents_task_view, this, false);
}
@Override
public void prepareViewToEnterPool(TaskView tv) {
Task task = tv.getTask();
- if (Console.Enabled) {
- Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|returnToPool]",
- tv.getTask() + " tv: " + tv);
- }
// Report that this tasks's data is no longer being used
RecentsTaskLoader.getInstance().unloadTaskData(task);
@@ -1050,11 +975,6 @@
@Override
public void prepareViewToLeavePool(TaskView tv, Task task, boolean isNewView) {
- if (Console.Enabled) {
- Console.log(Constants.Log.ViewPool.PoolCallbacks, "[TaskStackView|leavePool]",
- "isNewView: " + isNewView);
- }
-
// Rebind the task and request that this task's data be filled into the TaskView
tv.onTaskBound(task);
RecentsTaskLoader.getInstance().loadTaskData(task);
@@ -1083,10 +1003,6 @@
}
// Add/attach the view to the hierarchy
- if (Console.Enabled) {
- Console.log(Constants.Log.ViewPool.PoolCallbacks, " [TaskStackView|insertIndex]",
- "" + insertIndex);
- }
if (isNewView) {
addView(tv, insertIndex);
@@ -1112,11 +1028,6 @@
@Override
public void onTaskViewAppIconClicked(TaskView tv) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Icon]",
- tv.getTask() + " is currently filtered: " + mStack.hasFilteredTasks(),
- Console.AnsiCyan);
- }
if (Constants.DebugFlags.App.EnableTaskFiltering) {
if (mStack.hasFilteredTasks()) {
mStack.unfilterTasks();
@@ -1135,11 +1046,6 @@
@Override
public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
- task + " cb: " + mCb);
- }
-
// Cancel any doze triggers
mUIDozeTrigger.stopDozing();
@@ -1155,10 +1061,15 @@
mStack.removeTask(task);
}
+ @Override
+ public void onTaskViewClipStateChanged(TaskView tv) {
+ invalidate(mStackAlgorithm.mStackRect);
+ }
+
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
- public void onComponentRemoved(Set<ComponentName> cns) {
+ public void onComponentRemoved(HashSet<ComponentName> cns) {
// For other tasks, just remove them directly if they no longer exist
ArrayList<Task> tasks = mStack.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 908e063..65407a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -135,9 +135,9 @@
// Set the y translation
if (boundedT < 0f) {
transformOut.translationY = (int) ((Math.max(-numPeekCards, boundedT) /
- numPeekCards) * peekHeight - scaleYOffset - scaleBarYOffset);
+ numPeekCards) * peekHeight - scaleYOffset);
} else {
- transformOut.translationY = (int) (boundedT * overlapHeight - scaleYOffset - scaleBarYOffset);
+ transformOut.translationY = (int) (boundedT * overlapHeight - scaleYOffset);
}
// Set the z translation
@@ -146,7 +146,8 @@
transformOut.translationZ = (int) Math.max(minZ, minZ + ((boundedT + numPeekCards) * incZ));
// Set the alphas
- transformOut.dismissAlpha = Math.max(-1f, Math.min(0f, t + 1)) + 1f;
+ // transformOut.dismissAlpha = Math.max(-1f, Math.min(0f, t + 1)) + 1f;
+ transformOut.dismissAlpha = 1f;
// Update the rect and visibility
transformOut.rect.set(mTaskRect);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 15ace13..bd4ea90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -22,7 +22,6 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewParent;
-import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.Constants;
/* Handles touch events for a TaskStackView. */
@@ -100,12 +99,6 @@
/** Touch preprocessing for handling below */
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|interceptTouchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
- }
-
// Return early if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
if (!hasChildren) {
@@ -186,12 +179,6 @@
/** Handles touch events once we have intercepted them */
public boolean onTouchEvent(MotionEvent ev) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|touchEvent]",
- Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
- }
-
// Short circuit if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
if (!hasChildren) {
@@ -290,16 +277,6 @@
int overscrollRange = (int) (Math.min(1f,
Math.abs((float) velocity / mMaximumVelocity)) *
Constants.Values.TaskStackView.TaskStackOverscrollRange);
-
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.TouchEvents,
- "[TaskStackViewTouchHandler|fling]",
- "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
- " maxVelocity: " + mMaximumVelocity +
- " overscrollRange: " + overscrollRange,
- Console.AnsiGreen);
- }
-
// Fling scroll
mSv.mScroller.fling(0, mSv.getStackScroll(),
0, -velocity,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
index 636746d..08a25f1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
@@ -21,12 +21,11 @@
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
-import android.widget.ImageView;
import com.android.systemui.recents.model.Task;
/** The task thumbnail view */
-public class TaskThumbnailView extends ImageView {
+public class TaskThumbnailView extends FixedSizeImageView {
Task mTask;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 5524e15..199d3f3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -46,8 +46,9 @@
interface TaskViewCallbacks {
public void onTaskViewAppIconClicked(TaskView tv);
public void onTaskViewAppInfoClicked(TaskView tv);
- public void onTaskViewClicked(TaskView tv, Task t, boolean lockToTask);
+ public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask);
public void onTaskViewDismissed(TaskView tv);
+ public void onTaskViewClipStateChanged(TaskView tv);
}
RecentsConfiguration mConfig;
@@ -65,7 +66,7 @@
boolean mIsFocused;
boolean mIsStub;
boolean mClipViewInStack;
- Rect mTmpRect = new Rect();
+ int mClipFromBottom;
Paint mLayerPaint = new Paint();
TaskThumbnailView mThumbnailView;
@@ -118,7 +119,9 @@
setOutlineProvider(new ViewOutlineProvider() {
@Override
public boolean getOutline(View view, Outline outline) {
- int height = getHeight() - mMaxFooterHeight + mFooterHeight;
+ // The current height is measured with the footer, so account for the footer height
+ // and the current clip (in the stack)
+ int height = getMeasuredHeight() - mClipFromBottom - mMaxFooterHeight + mFooterHeight;
outline.setRoundRect(0, 0, getWidth(), height,
mConfig.taskViewRoundedCornerRadiusPx);
return true;
@@ -172,11 +175,6 @@
/** Synchronizes this view's properties with the task's transform */
void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration) {
- if (Console.Enabled) {
- Console.log(Constants.Log.UI.Draw, "[TaskView|updateViewPropertiesToTaskTransform]",
- "duration: " + duration, Console.AnsiPurple);
- }
-
// Update the bar view
mBarView.updateViewPropertiesToTaskTransform(toTransform, duration);
@@ -483,15 +481,6 @@
mBarView.setNoUserInteractionState();
}
- /** Returns the rect we want to clip (it may not be the full rect) */
- Rect getClippingRect(Rect outRect) {
- getHitRect(outRect);
- // XXX: We should get the hit rect of the thumbnail view and intersect, but this is faster
- outRect.right = outRect.left + mThumbnailView.getRight();
- outRect.bottom = outRect.top + mThumbnailView.getBottom();
- return outRect;
- }
-
/** Enable the hw layers on this task view */
void enableHwLayers() {
mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
@@ -533,19 +522,26 @@
void setClipViewInStack(boolean clip) {
if (clip != mClipViewInStack) {
mClipViewInStack = clip;
- if (getParent() instanceof View) {
- getHitRect(mTmpRect);
- ((View) getParent()).invalidate(mTmpRect);
- }
+ mCb.onTaskViewClipStateChanged(this);
+ }
+ }
+
+ void setClipFromBottom(int clipFromBottom) {
+ clipFromBottom = Math.max(0, Math.min(getMeasuredHeight(), clipFromBottom));
+ if (mClipFromBottom != clipFromBottom) {
+ mClipFromBottom = clipFromBottom;
+ invalidateOutline();
}
}
/** Sets the footer height. */
- public void setFooterHeight(int height) {
- mFooterHeight = height;
- invalidateOutline();
- invalidate(0, getMeasuredHeight() - mMaxFooterHeight, getMeasuredWidth(),
- getMeasuredHeight());
+ public void setFooterHeight(int footerHeight) {
+ if (footerHeight != mFooterHeight) {
+ mFooterHeight = footerHeight;
+ invalidateOutline();
+ invalidate(0, getMeasuredHeight() - mMaxFooterHeight, getMeasuredWidth(),
+ getMeasuredHeight());
+ }
}
/** Gets the footer height. */
@@ -553,9 +549,19 @@
return mFooterHeight;
}
+ /** Gets the max footer height. */
+ public int getMaxFooterHeight() {
+ return mMaxFooterHeight;
+ }
+
/** Animates the footer into and out of view. */
public void animateFooterVisibility(boolean visible, int duration, int delay) {
- if (!mTask.canLockToTask) return;
+ if (!mTask.canLockToTask) {
+ if (mLockToAppButtonView.getVisibility() == View.VISIBLE) {
+ mLockToAppButtonView.setVisibility(View.INVISIBLE);
+ }
+ return;
+ }
if (mMaxFooterHeight <= 0) return;
if (mFooterAnimator != null) {
@@ -677,6 +683,7 @@
mTask = t;
mTask.setCallbacks(this);
if (getMeasuredWidth() == 0) {
+ // If we haven't yet measured, we should just set the footer height with any animation
animateFooterVisibility(t.canLockToTask, 0, 0);
} else {
animateFooterVisibility(t.canLockToTask, mConfig.taskViewLockToAppLongAnimDuration, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
deleted file mode 100644
index a3b10f2..0000000
--- a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * 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
- */
-
-package com.android.systemui.settings;
-
-import com.android.systemui.R;
-
-import android.app.ActivityManagerNative;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Shader;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.provider.Settings.SettingNotFoundException;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManagerGlobal;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A quick and dirty view to show a user switcher.
- */
-public class UserSwitcherHostView extends FrameLayout
- implements ListView.OnItemClickListener, View.OnClickListener {
-
- private static final String TAG = "UserSwitcherDialog";
-
- private ArrayList<UserInfo> mUserInfo = new ArrayList<UserInfo>();
- private UserInfo mGuestUser;
- private Adapter mAdapter = new Adapter();
- private UserManager mUserManager;
- private Runnable mFinishRunnable;
- private ListView mListView;
- private boolean mGuestUserEnabled;
-
- public UserSwitcherHostView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
-
- if (isInEditMode()) {
- return;
- }
- mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
-
- mGuestUserEnabled = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.GUEST_USER_ENABLED, 0) == 1;
- }
-
- public UserSwitcherHostView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.listViewStyle);
- }
-
- public UserSwitcherHostView(Context context) {
- this(context, null);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mListView = (ListView) findViewById(android.R.id.list);
- mListView.setAdapter(mAdapter);
- mListView.setOnItemClickListener(this);
- }
-
- @Override
- public void onItemClick(AdapterView<?> l, View v, int position, long id) {
- // Last item is the guest
- if (position == mUserInfo.size()) {
- postDelayed(new Runnable() {
- public void run() {
- switchToGuestUser();
- }
- }, 100);
- } else {
- final int userId = mAdapter.getItem(position).id;
- postDelayed(new Runnable() {
- public void run() {
- switchUser(userId);
- }
- }, 100);
- }
- }
-
- @Override
- public void onClick(View v) {
- // Delete was clicked
- postDelayed(new Runnable() {
- public void run() {
- if (mGuestUser != null) {
- switchUser(0);
- mUserManager.removeUser(mGuestUser.id);
- mGuestUser = null;
- refreshUsers();
- }
- }
- }, 100);
- }
-
- private void switchUser(int userId) {
- try {
- WindowManagerGlobal.getWindowManagerService().lockNow(null);
- ActivityManagerNative.getDefault().switchUser(userId);
- finish();
- } catch (RemoteException e) {
- Log.e(TAG, "Couldn't switch user.", e);
- }
- }
-
- private void switchToGuestUser() {
- if (mGuestUser == null) {
- // No guest user. Create one.
- mGuestUser = mUserManager.createGuest(mContext,
- mContext.getResources().getString(R.string.guest_nickname));
- }
- switchUser(mGuestUser.id);
- }
-
- private void finish() {
- if (mFinishRunnable != null) {
- mFinishRunnable.run();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_UP) {
- finish();
- }
- return true;
- }
-
- @Override
- protected void onVisibilityChanged(View changedView, int visibility) {
- super.onVisibilityChanged(changedView, visibility);
- // A gross hack to get rid of the switcher when the shade is collapsed.
- if (visibility != VISIBLE) {
- finish();
- }
- }
-
- public void setFinishRunnable(Runnable finishRunnable) {
- mFinishRunnable = finishRunnable;
- }
-
- public void refreshUsers() {
- mUserInfo.clear();
- mGuestUser = null;
- List<UserInfo> users = mUserManager.getUsers(true);
- for (UserInfo user : users) {
- if (user.isGuest()) {
- mGuestUser = user;
- } else if (!user.isManagedProfile()) {
- mUserInfo.add(user);
- }
- }
- mAdapter.notifyDataSetChanged();
- }
-
- private class Adapter extends BaseAdapter {
-
- @Override
- public int getCount() {
- return mUserInfo.size() + (mGuestUserEnabled ? 1 : 0);
- }
-
- @Override
- public UserInfo getItem(int position) {
- if (position < mUserInfo.size()) {
- return mUserInfo.get(position);
- } else {
- return mGuestUser;
- }
- }
-
- @Override
- public long getItemId(int position) {
- if (position < mUserInfo.size()) {
- return getItem(position).serialNumber;
- } else {
- return mGuestUser != null ? mGuestUser.serialNumber : -1;
- }
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null || (!(convertView.getTag() instanceof ViewHolder))) {
- convertView = createView(parent);
- }
- ViewHolder h = (ViewHolder) convertView.getTag();
- bindView(h, getItem(position));
- return convertView;
- }
-
- private View createView(ViewGroup parent) {
- View v = LayoutInflater.from(getContext()).inflate(
- R.layout.user_switcher_item, parent, false);
- ViewHolder h = new ViewHolder();
- h.name = (TextView) v.findViewById(R.id.user_name);
- h.picture = (ImageView) v.findViewById(R.id.user_picture);
- h.delete = (ImageView) v.findViewById(R.id.user_delete);
- v.setTag(h);
- return v;
- }
-
- private void bindView(ViewHolder h, UserInfo item) {
- if (item != null) {
- h.name.setText(item.name);
- h.picture.setImageBitmap(circularClip(mUserManager.getUserIcon(item.id)));
- h.delete.setVisibility(item.isGuest() ? View.VISIBLE : View.GONE);
- h.delete.setOnClickListener(UserSwitcherHostView.this);
- if (item.isGuest()) {
- h.picture.setImageResource(R.drawable.ic_account_circle);
- }
- } else {
- h.name.setText(R.string.guest_new_guest);
- h.picture.setImageResource(R.drawable.ic_account_circle);
- h.delete.setVisibility(View.GONE);
- }
- }
-
- private Bitmap circularClip(Bitmap input) {
- if (input == null) {
- return null;
- }
- Bitmap output = Bitmap.createBitmap(input.getWidth(),
- input.getHeight(), Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(output);
- final Paint paint = new Paint();
- paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
- paint.setAntiAlias(true);
- canvas.drawCircle(input.getWidth() / 2, input.getHeight() / 2, input.getWidth() / 2,
- paint);
- return output;
- }
-
- class ViewHolder {
- TextView name;
- ImageView picture;
- ImageView delete;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 9101c8d..0a288d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -62,8 +62,10 @@
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.ViewStub;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.widget.DateTimeView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
@@ -579,7 +581,7 @@
}
}
- private boolean isMediaNotification(NotificationData.Entry entry) {
+ public boolean isMediaNotification(NotificationData.Entry entry) {
// TODO: confirm that there's a valid media key
return entry.expandedBig != null &&
entry.expandedBig.findViewById(com.android.internal.R.id.media_action_area) != null;
@@ -1075,14 +1077,28 @@
}
}
+ final View privateTime = contentViewLocal.findViewById(com.android.internal.R.id.time);
+ if (privateTime != null && privateTime.getVisibility() == View.VISIBLE) {
+ final View timeStub = publicViewLocal.findViewById(com.android.internal.R.id.time);
+ timeStub.setVisibility(View.VISIBLE);
+ final DateTimeView dateTimeView = (DateTimeView)
+ publicViewLocal.findViewById(com.android.internal.R.id.time);
+ dateTimeView.setTime(entry.notification.getNotification().when);
+ }
+
final TextView text = (TextView) publicViewLocal.findViewById(
- com.android.internal.R.id.text);
- text.setText("Unlock your device to see this notification.");
+ com.android.internal.R.id.text);
+ if (text != null) {
+ text.setText(R.string.notification_hidden_text);
+ text.setTextAppearance(mContext,
+ R.style.TextAppearance_StatusBar_Material_EventContent_Parenthetical);
+ }
entry.autoRedacted = true;
- // TODO: fill out "time" as well
}
+ row.setClearable(sbn.isClearable());
+
row.setDrawingCacheEnabled(true);
if (MULTIUSER_DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 280bade..3410834 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -53,6 +53,7 @@
private NotificationContentView mPrivateLayout;
private int mMaxExpandHeight;
private View mVetoButton;
+ private boolean mClearable;
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -166,6 +167,23 @@
}
/**
+ * @return Can the underlying notification be cleared?
+ */
+ public boolean isClearable() {
+ return mClearable;
+ }
+
+ /**
+ * Set whether the notification can be cleared.
+ *
+ * @param clearable
+ */
+ public void setClearable(boolean clearable) {
+ mClearable = clearable;
+ updateVetoButton();
+ }
+
+ /**
* Apply an expansion state to the layout.
*/
public void applyExpansionToLayout() {
@@ -223,6 +241,13 @@
// TODO: animation?
mPublicLayout.setVisibility(show ? View.VISIBLE : View.GONE);
mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE);
+
+ updateVetoButton();
+ }
+
+ private void updateVetoButton() {
+ // public versions cannot be dismissed
+ mVetoButton.setVisibility(isClearable() && !mShowingPublic ? View.VISIBLE : View.GONE);
}
public int getMaxExpandHeight() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 0f12274..688c0d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -18,29 +18,22 @@
import android.content.Context;
import android.content.Intent;
-import android.graphics.Canvas;
-import android.graphics.Path;
-import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.ContactsContract;
import android.util.AttributeSet;
-import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.FrameLayout;
-import android.widget.ImageButton;
-import com.android.systemui.R;
-import com.android.systemui.settings.UserSwitcherHostView;
-import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.qs.QSPanel;
+import com.android.systemui.qs.tiles.UserDetailView;
/**
* Container for image of the multi user switcher (tappable).
*/
public class MultiUserSwitch extends FrameLayout implements View.OnClickListener {
- private ViewGroup mOverlayParent;
+ private QSPanel mQsPanel;
public MultiUserSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -52,25 +45,16 @@
setOnClickListener(this);
}
- public void setOverlayParent(ViewGroup parent) {
- mOverlayParent = parent;
+ public void setQsPanel(QSPanel qsPanel) {
+ mQsPanel = qsPanel;
}
@Override
public void onClick(View v) {
final UserManager um = UserManager.get(getContext());
if (um.isUserSwitcherEnabled()) {
- final UserSwitcherHostView switcher =
- (UserSwitcherHostView) LayoutInflater.from(getContext()).inflate(
- R.layout.user_switcher_host, mOverlayParent, false);
- switcher.setFinishRunnable(new Runnable() {
- @Override
- public void run() {
- mOverlayParent.removeView(switcher);
- }
- });
- switcher.refreshUsers();
- mOverlayParent.addView(switcher);
+ mQsPanel.showDetailAdapter(true,
+ mQsPanel.getHost().getUserSwitcherController().userDetailAdapter);
} else {
Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
getContext(), v, ContactsContract.Profile.CONTENT_URI,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 55b3088..fc0f2d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -150,7 +150,6 @@
super.onFinishInflate();
mHeader = (StatusBarHeaderView) findViewById(R.id.header);
mHeader.setOnClickListener(this);
- mHeader.setOverlayParent(this);
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
mQsContainer = findViewById(R.id.quick_settings_container);
mQsPanel = (QSPanel) findViewById(R.id.quick_settings_panel);
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 505af44..8564409 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -45,15 +45,23 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
+import android.media.MediaMetadata;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -91,6 +99,7 @@
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -127,6 +136,7 @@
import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
@@ -139,6 +149,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
DragDownHelper.OnDragDownListener, ActivityStarter {
@@ -147,17 +158,19 @@
public static final boolean SPEW = false;
public static final boolean DUMPTRUCK = true; // extra dumpsys info
public static final boolean DEBUG_GESTURES = false;
+ public static final boolean DEBUG_MEDIA = false;
+ public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
public static final boolean DEBUG_WINDOW_STATE = false;
- public static final boolean SETTINGS_DRAG_SHORTCUT = true;
-
// additional instrumentation for testing purposes; intended to be left on during development
public static final boolean CHATTY = DEBUG;
public static final String ACTION_STATUSBAR_START
= "com.android.internal.policy.statusbar.START";
+ public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;
+
private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
private static final int MSG_CLOSE_PANELS = 1001;
private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
@@ -194,6 +207,7 @@
VolumeComponent mVolumeComponent;
KeyguardUserSwitcher mKeyguardUserSwitcher;
FlashlightController mFlashlightController;
+ UserSwitcherController mUserSwitcherController;
int mNaturalBarHeight = -1;
int mIconSize = -1;
@@ -376,6 +390,38 @@
private Interpolator mAlphaIn = new PathInterpolator(0f, 0.2f, 1f, 1f);
private Interpolator mAlphaOut = new PathInterpolator(0f, 0f, 0.8f, 1f);
+ private FrameLayout mBackdrop;
+ private ImageView mBackdropFront, mBackdropBack;
+
+ private MediaSessionManager mMediaSessionManager;
+ private MediaController mMediaController;
+ private String mMediaNotificationKey;
+ private MediaMetadata mMediaMetadata;
+ private MediaController.Callback mMediaListener
+ = new MediaController.Callback() {
+ @Override
+ public void onPlaybackStateChanged(PlaybackState state) {
+ super.onPlaybackStateChanged(state);
+ if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onPlaybackStateChanged: " + state);
+ }
+
+ @Override
+ public void onMetadataChanged(MediaMetadata metadata) {
+ super.onMetadataChanged(metadata);
+ if (DEBUG_MEDIA) Log.v(TAG, "DEBUG_MEDIA: onMetadataChanged: " + metadata);
+ mMediaMetadata = metadata;
+ updateMediaMetaData(true);
+ }
+ };
+
+ private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
+ new OnChildLocationsChangedListener() {
+ @Override
+ public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout) {
+ userActivity();
+ }
+ };
+
private int mDisabledUnmodified;
/** Keys of notifications currently visible to the user. */
@@ -478,6 +524,11 @@
updateDisplaySize();
super.start(); // calls createAndAddWindows()
+ mMediaSessionManager
+ = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
+ // TODO: use MediaSessionManager.SessionListener to hook us up to future updates
+ // in session state
+
addNavigationBar();
// Lastly, call to the icon policy to install/update all the icons.
@@ -691,6 +742,7 @@
}
mFlashlightController = new FlashlightController(mContext);
+ mUserSwitcherController = new UserSwitcherController(mContext);
// Set up the quick settings tile panel
mQSPanel = (QSPanel) mStatusBarWindow.findViewById(R.id.quick_settings_panel);
@@ -698,13 +750,19 @@
final QSTileHost qsh = new QSTileHost(mContext, this,
mBluetoothController, mLocationController, mRotationLockController,
mNetworkController, mZenModeController, null /*tethering*/,
- mCastController, mVolumeComponent, mFlashlightController);
+ mCastController, mVolumeComponent, mFlashlightController,
+ mUserSwitcherController);
+ mQSPanel.setHost(qsh);
for (QSTile<?> tile : qsh.getTiles()) {
mQSPanel.addTile(tile);
}
mHeader.setQSPanel(mQSPanel);
}
+ mBackdrop = (FrameLayout) mStatusBarWindow.findViewById(R.id.backdrop);
+ mBackdropFront = (ImageView) mBackdrop.findViewById(R.id.backdrop_front);
+ mBackdropBack = (ImageView) mBackdrop.findViewById(R.id.backdrop_back);
+
// User info. Trigger first load.
mHeader.setUserInfoController(mUserInfoController);
mUserInfoController.reloadUserInfo();
@@ -720,6 +778,9 @@
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
+ if (DEBUG_MEDIA_FAKE_ARTWORK) {
+ filter.addAction("fake_artwork");
+ }
filter.addAction(ACTION_DEMO);
context.registerReceiver(mBroadcastReceiver, filter);
@@ -1404,9 +1465,240 @@
.start();
}
+ findAndUpdateMediaNotifications();
+
updateCarrierLabelVisibility(false);
}
+ public void findAndUpdateMediaNotifications() {
+ boolean metaDataChanged = false;
+
+ synchronized (mNotificationData) {
+ final int N = mNotificationData.size();
+ Entry mediaNotification = null;
+ MediaController controller = null;
+ for (int i=0; i<N; i++) {
+ final Entry entry = mNotificationData.get(i);
+ if (isMediaNotification(entry)) {
+ final MediaSession.Token token = entry.notification.getNotification().extras
+ .getParcelable(Notification.EXTRA_MEDIA_SESSION);
+ if (token != null) {
+ controller = new MediaController(token);
+ if (controller != null) {
+ // we've got a live one, here
+ mediaNotification = entry;
+ }
+ }
+ }
+ }
+
+ if (mediaNotification == null) {
+ // Still nothing? OK, let's just look for live media sessions and see if they match
+ // one of our notifications. This will catch apps that aren't (yet!) using media
+ // notifications.
+
+ if (mMediaSessionManager != null) {
+ final List<MediaController> sessions
+ = mMediaSessionManager.getActiveSessionsForUser(
+ null,
+ UserHandle.USER_ALL);
+
+ for (MediaController aController : sessions) {
+ if (aController == null) continue;
+ final PlaybackState state = aController.getPlaybackState();
+ if (state == null) continue;
+ switch (state.getState()) {
+ case PlaybackState.STATE_STOPPED:
+ case PlaybackState.STATE_ERROR:
+ continue;
+ default:
+ // now to see if we have one like this
+ final String pkg = aController.getSessionInfo().getPackageName();
+
+ for (int i = 0; i < N; i++) {
+ final Entry entry = mNotificationData.get(i);
+ if (entry.notification.getPackageName().equals(pkg)) {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: found controller matching "
+ + entry.notification.getKey());
+ }
+ controller = aController;
+ mediaNotification = entry;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (controller != mMediaController) {
+ // We have a new media session
+
+ if (mMediaController != null) {
+ // something old was playing
+ Log.v(TAG, "DEBUG_MEDIA: Disconnecting from old controller: "
+ + mMediaController);
+ mMediaController.removeCallback(mMediaListener);
+ }
+ mMediaController = controller;
+
+ if (mMediaController != null) {
+ mMediaController.addCallback(mMediaListener);
+ mMediaMetadata = mMediaController.getMetadata();
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: insert listener, receive metadata: "
+ + mMediaMetadata);
+ }
+
+ final String notificationKey = mediaNotification == null
+ ? null
+ : mediaNotification.notification.getKey();
+
+ if (notificationKey == null || !notificationKey.equals(mMediaNotificationKey)) {
+ // we have a new notification!
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Found new media notification: key="
+ + notificationKey + " controller=" + controller);
+ }
+ mMediaNotificationKey = notificationKey;
+ }
+ } else {
+ mMediaMetadata = null;
+ mMediaNotificationKey = null;
+ }
+
+ metaDataChanged = true;
+ } else {
+ // Media session unchanged
+
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Continuing media notification: key=" + mMediaNotificationKey);
+ }
+ }
+ }
+
+ updateMediaMetaData(metaDataChanged);
+ }
+
+ private void removeAndRecycleImageViewDrawable(ImageView iv) {
+ Bitmap oldBitmap = null;
+ final Drawable drawable = iv.getDrawable();
+ if (drawable != null && drawable instanceof BitmapDrawable) {
+ oldBitmap = ((BitmapDrawable) drawable).getBitmap();
+ }
+ iv.animate().cancel();
+ iv.setImageDrawable(null);
+ if (oldBitmap != null) {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: recycling bitmap " + oldBitmap + " from ImageView " + iv);
+ }
+ oldBitmap.recycle();
+ }
+ }
+
+ /**
+ * Hide the album artwork that is fading out and release its memory.
+ */
+ private Runnable mHideBackdropFront = new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: removing fade layer");
+ }
+ mBackdropFront.setVisibility(View.INVISIBLE);
+ removeAndRecycleImageViewDrawable(mBackdropFront);
+ }
+ };
+
+ /**
+ * Refresh or remove lockscreen artwork from media metadata.
+ */
+ public void updateMediaMetaData(boolean metaDataChanged) {
+ if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) return;
+
+ if (mBackdrop == null) return; // called too early
+
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: updating album art for notification " + mMediaNotificationKey
+ + " metadata=" + mMediaMetadata
+ + " metaDataChanged=" + metaDataChanged
+ + " state=" + mState);
+ }
+
+ Bitmap artworkBitmap = null;
+ if (mMediaMetadata != null) {
+ artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
+ if (artworkBitmap == null) {
+ artworkBitmap = mMediaMetadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
+ // might still be null
+ }
+ }
+
+ final boolean hasArtwork = artworkBitmap != null;
+
+ if ((hasArtwork || DEBUG_MEDIA_FAKE_ARTWORK)
+ && (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
+ // time to show some art!
+ if (mBackdrop.getVisibility() != View.VISIBLE) {
+ mBackdrop.setVisibility(View.VISIBLE);
+ mBackdrop.animate().alpha(1f);
+ metaDataChanged = true;
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
+ }
+ }
+ if (metaDataChanged) {
+ if (mBackdropBack.getDrawable() != null) {
+ mBackdropFront.setImageDrawable(mBackdropBack.getDrawable());
+ mBackdropFront.setAlpha(1f);
+ mBackdropFront.setVisibility(View.VISIBLE);
+ } else {
+ mBackdropFront.setVisibility(View.INVISIBLE);
+ }
+
+ if (DEBUG_MEDIA_FAKE_ARTWORK) {
+ final int c = 0xFF000000 | (int)(Math.random() * 0xFFFFFF);
+ Log.v(TAG, String.format("DEBUG_MEDIA: setting new color: 0x%08x", c));
+ mBackdropBack.setBackgroundColor(0xFFFFFFFF);
+ mBackdropBack.setImageDrawable(new ColorDrawable(c));
+ } else {
+ mBackdropBack.setImageBitmap(artworkBitmap);
+ }
+
+ if (mBackdropFront.getVisibility() == View.VISIBLE) {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Crossfading album artwork from "
+ + mBackdropFront.getDrawable()
+ + " to "
+ + mBackdropBack.getDrawable());
+ }
+ mBackdropFront.animate().withLayer()
+ .setDuration(250)
+ .alpha(0f).withEndAction(mHideBackdropFront);
+ }
+ }
+ } else {
+ // need to hide the album art, either because we are unlocked or because
+ // the metadata isn't there to support it
+ if (mBackdrop.getVisibility() != View.GONE) {
+ if (DEBUG_MEDIA) {
+ Log.v(TAG, "DEBUG_MEDIA: Fading out album artwork");
+ }
+ mBackdrop.animate().withLayer()
+ .alpha(0f).withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mBackdrop.setVisibility(View.GONE);
+ mBackdropFront.animate().cancel();
+ mBackdropBack.animate().cancel();
+ mHandler.post(mHideBackdropFront);
+ }
+ });
+ }
+ }
+ }
+
public void showClock(boolean show) {
if (mStatusBarView == null) return;
View clock = mStatusBarView.findViewById(R.id.clock);
@@ -2267,6 +2559,23 @@
mNavigationBarView.dump(fd, pw, args);
}
+ pw.print(" mMediaSessionManager=");
+ pw.println(mMediaSessionManager);
+ pw.print(" mMediaNotificationKey=");
+ pw.println(mMediaNotificationKey);
+ pw.print(" mMediaController=");
+ pw.print(mMediaController);
+ if (mMediaController != null) {
+ pw.print(" state=" + mMediaController.getPlaybackState());
+ }
+ pw.println();
+ pw.print(" mMediaMetadata=");
+ pw.print(mMediaMetadata);
+ if (mMediaMetadata != null) {
+ pw.print(" title=" + mMediaMetadata.getString(MediaMetadata.METADATA_KEY_TITLE));
+ }
+ pw.println();
+
pw.println(" Panels: ");
if (mNotificationPanel != null) {
pw.println(" mNotificationPanel=" +
@@ -2325,6 +2634,9 @@
if (mCastController != null) {
mCastController.dump(fd, pw, args);
}
+ if (mUserSwitcherController != null) {
+ mUserSwitcherController.dump(fd, pw, args);
+ }
}
private String hunStateToString(Entry entry) {
@@ -2445,6 +2757,10 @@
}
}
}
+ } else if ("fake_artwork".equals(action)) {
+ if (DEBUG_MEDIA_FAKE_ARTWORK) {
+ updateMediaMetaData(true);
+ }
}
}
};
@@ -2882,6 +3198,7 @@
updateNotifications();
checkBarModes();
updateCarrierLabelVisibility(false);
+ updateMediaMetaData(false);
}
private void updateDozingState() {
@@ -3125,16 +3442,6 @@
IActivityManager activityManager = ActivityManagerNative.getDefault();
if (activityManager.isInLockTaskMode()) {
activityManager.stopLockTaskModeOnCurrent();
- } else {
- try {
- boolean lockToAppEnabled = Settings.System.getInt(mContext.getContentResolver(),
- Settings.System.LOCK_TO_APP_ENABLED) != 0;
- if (lockToAppEnabled) {
- activityManager.startLockTaskModeOnCurrent();
- }
- } catch (SettingNotFoundException e) {
- // No setting, not enabled.
- }
}
} catch (RemoteException e) {
Log.d(TAG, "Unable to toggle Lock-to-app", e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 1bb36dd..8b5ff67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -27,11 +27,12 @@
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings.Global;
+import android.telecomm.TelecommConstants;
+import android.telecomm.TelecommManager;
import android.util.Log;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.cdma.TtyIntent;
import com.android.systemui.R;
/**
@@ -89,7 +90,7 @@
else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
updateSimState(intent);
}
- else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
+ else if (action.equals(TelecommConstants.ACTION_CURRENT_TTY_MODE_CHANGED)) {
updateTTY(intent);
}
else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
@@ -110,7 +111,7 @@
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
+ filter.addAction(TelecommConstants.ACTION_CURRENT_TTY_MODE_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
@@ -269,7 +270,9 @@
}
private final void updateTTY(Intent intent) {
- final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
+ int currentTtyMode = intent.getIntExtra(TelecommConstants.EXTRA_CURRENT_TTY_MODE,
+ TelecommConstants.TTY_MODE_OFF);
+ boolean enabled = currentTtyMode != TelecommConstants.TTY_MODE_OFF;
if (DEBUG) Log.v(TAG, "updateTTY: enabled: " + enabled);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 5fbade1..a599070 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -40,6 +40,7 @@
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.TetheringController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.volume.VolumeComponent;
@@ -63,12 +64,14 @@
private final VolumeComponent mVolume;
private final ArrayList<QSTile<?>> mTiles = new ArrayList<QSTile<?>>();
private final FlashlightController mFlashlight;
+ private final UserSwitcherController mUserSwitcherController;
public QSTileHost(Context context, PhoneStatusBar statusBar,
BluetoothController bluetooth, LocationController location,
RotationLockController rotation, NetworkController network,
ZenModeController zen, TetheringController tethering,
- CastController cast, VolumeComponent volume, FlashlightController flashlight) {
+ CastController cast, VolumeComponent volume, FlashlightController flashlight,
+ UserSwitcherController userSwitcher) {
mContext = context;
mStatusBar = statusBar;
mBluetooth = bluetooth;
@@ -80,6 +83,7 @@
mCast = cast;
mVolume = volume;
mFlashlight = flashlight;
+ mUserSwitcherController = userSwitcher;
final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName());
ht.start();
@@ -181,4 +185,8 @@
public FlashlightController getFlashlightController() {
return mFlashlight;
}
+
+ public UserSwitcherController getUserSwitcherController() {
+ return mUserSwitcherController;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 33d1b15..dc06ec2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -475,10 +475,6 @@
});
}
- public void setOverlayParent(ViewGroup parent) {
- mMultiUserSwitch.setOverlayParent(parent);
- }
-
@Override
public void onClick(View v) {
if (v == mSettingsButton) {
@@ -501,6 +497,7 @@
if (mQSPanel != null) {
mQSPanel.setCallback(mQsPanelCallback);
}
+ mMultiUserSwitch.setQsPanel(qsp);
}
@Override
@@ -589,7 +586,7 @@
mQsDetailHeader.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- detail.setToggleState(!toggleState);
+ detail.setToggleState(!mQsDetailHeaderSwitch.isChecked());
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index f021623..80fec5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -180,8 +180,13 @@
final BluetoothDevice device = (BluetoothDevice) pd.tag;
final String action = connect ? "connect" : "disconnect";
if (DEBUG) Log.d(TAG, action + " " + deviceToString(device));
+ final ParcelUuid[] uuids = device.getUuids();
+ if (uuids == null) {
+ Log.w(TAG, "No uuids returned, aborting " + action + " for " + deviceToString(device));
+ return;
+ }
final SparseBooleanArray profiles = new SparseBooleanArray();
- for (ParcelUuid uuid : device.getUuids()) {
+ for (ParcelUuid uuid : uuids) {
final int profile = uuidToProfile(uuid);
if (profile == 0) {
Log.w(TAG, "Device " + deviceToString(device) + " has an unsupported uuid: "
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
index f2dfe05..33d68bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileDataController.java
@@ -20,6 +20,8 @@
import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
import static android.telephony.TelephonyManager.SIM_STATE_READY;
+import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
+import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
import android.content.Context;
import android.net.ConnectivityManager;
@@ -33,19 +35,23 @@
import android.os.ServiceManager;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
+import android.text.format.Time;
import android.util.Log;
import com.android.systemui.statusbar.policy.NetworkController.DataUsageInfo;
-import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
public class MobileDataController {
private static final String TAG = "MobileDataController";
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final SimpleDateFormat MMM_D = new SimpleDateFormat("MMM d");
+ private static final long DEFAULT_WARNING_LEVEL = 2L * 1024 * 1024 * 1024;
private static final int FIELDS = FIELD_RX_BYTES | FIELD_TX_BYTES;
+ private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50);
+ private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter(
+ PERIOD_BUILDER, Locale.getDefault());
private final Context mContext;
private final TelephonyManager mTelephonyManager;
@@ -87,6 +93,13 @@
return null;
}
+ private static Time addMonth(Time t, int months) {
+ final Time rt = new Time(t);
+ rt.set(t.monthDay, t.month + months, t.year);
+ rt.normalize(false);
+ return rt;
+ }
+
public DataUsageInfo getDataUsageInfo() {
final String subscriberId = getActiveSubscriberId(mContext);
if (subscriberId == null) {
@@ -101,9 +114,28 @@
try {
final NetworkStatsHistory history = mSession.getHistoryForNetwork(template, FIELDS);
final long now = System.currentTimeMillis();
- // period = last 4 wks for now
- final long start = now - DateUtils.WEEK_IN_MILLIS * 4;
- final long end = now;
+ final long start, end;
+ if (policy != null && policy.cycleDay > 0) {
+ // period = determined from cycleDay
+ if (DEBUG) Log.d(TAG, "Cycle day=" + policy.cycleDay + " tz="
+ + policy.cycleTimezone);
+ final Time nowTime = new Time(policy.cycleTimezone);
+ nowTime.setToNow();
+ final Time policyTime = new Time(nowTime);
+ policyTime.set(policy.cycleDay, policyTime.month, policyTime.year);
+ policyTime.normalize(false);
+ if (nowTime.after(policyTime)) {
+ start = policyTime.toMillis(false);
+ end = addMonth(policyTime, 1).toMillis(false);
+ } else {
+ start = addMonth(policyTime, -1).toMillis(false);
+ end = policyTime.toMillis(false);
+ }
+ } else {
+ // period = last 4 wks
+ end = now;
+ start = now - DateUtils.WEEK_IN_MILLIS * 4;
+ }
final long callStart = System.currentTimeMillis();
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
final long callEnd = System.currentTimeMillis();
@@ -115,12 +147,13 @@
}
final long totalBytes = entry.rxBytes + entry.txBytes;
final DataUsageInfo usage = new DataUsageInfo();
- usage.maxLevel = (long) (totalBytes / .4);
usage.usageLevel = totalBytes;
- usage.period = MMM_D.format(new Date(start)) + " - " + MMM_D.format(new Date(end));
+ usage.period = formatDateRange(start, end);
if (policy != null) {
usage.limitLevel = policy.limitBytes > 0 ? policy.limitBytes : 0;
usage.warningLevel = policy.warningBytes > 0 ? policy.warningBytes : 0;
+ } else {
+ usage.warningLevel = DEFAULT_WARNING_LEVEL;
}
return usage;
} catch (RemoteException e) {
@@ -178,6 +211,15 @@
return actualSubscriberId;
}
+ private String formatDateRange(long start, long end) {
+ final int flags = FORMAT_SHOW_DATE | FORMAT_ABBREV_MONTH;
+ synchronized (PERIOD_BUILDER) {
+ PERIOD_BUILDER.setLength(0);
+ return DateUtils.formatDateRange(mContext, PERIOD_FORMATTER, start, end, flags, null)
+ .toString();
+ }
+ }
+
public interface Callback {
void onMobileDataEnabled(boolean enabled);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index d058bd0..6d8b400 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -61,7 +61,6 @@
public static class DataUsageInfo {
public String carrier;
public String period;
- public long maxLevel;
public long limitLevel;
public long warningLevel;
public long usageLevel;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
new file mode 100644
index 0000000..4640067
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -0,0 +1,279 @@
+/*
+ * 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
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import com.android.systemui.R;
+import com.android.systemui.qs.QSTile;
+import com.android.systemui.qs.tiles.UserDetailView;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
+import android.widget.BaseAdapter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Keeps a list of all users on the device for user switching.
+ */
+public class UserSwitcherController {
+
+ private static final String TAG = "UserSwitcherController";
+
+ private final Context mContext;
+ private final UserManager mUserManager;
+ private final ArrayList<WeakReference<BaseUserAdapter>> mAdapters = new ArrayList<>();
+
+ private ArrayList<UserRecord> mUsers = new ArrayList<>();
+
+ public UserSwitcherController(Context context) {
+ mContext = context;
+ mUserManager = UserManager.get(context);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_ADDED);
+ filter.addAction(Intent.ACTION_USER_REMOVED);
+ filter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiver(mReceiver, filter);
+ refreshUsers();
+ }
+
+ private void refreshUsers() {
+ new AsyncTask<Void, Void, ArrayList<UserRecord>>() {
+
+ @Override
+ protected ArrayList<UserRecord> doInBackground(Void... params) {
+ List<UserInfo> infos = mUserManager.getUsers(true);
+ if (infos == null) {
+ return null;
+ }
+ ArrayList<UserRecord> records = new ArrayList<>(infos.size());
+ int currentId = ActivityManager.getCurrentUser();
+ UserRecord guestRecord = null;
+
+ for (UserInfo info : infos) {
+ boolean isCurrent = currentId == info.id;
+ if (info.isGuest()) {
+ guestRecord = new UserRecord(info, null /* picture */,
+ true /* isGuest */, isCurrent);
+ } else if (!info.isManagedProfile()) {
+ records.add(new UserRecord(info, mUserManager.getUserIcon(info.id),
+ false /* isGuest */, isCurrent));
+ }
+ }
+
+ if (guestRecord == null) {
+ records.add(new UserRecord(null /* info */, null /* picture */,
+ true /* isGuest */, false /* isCurrent */));
+ } else {
+ records.add(guestRecord);
+ }
+
+ return records;
+ }
+
+ @Override
+ protected void onPostExecute(ArrayList<UserRecord> userRecords) {
+ if (userRecords != null) {
+ mUsers = userRecords;
+ notifyAdapters();
+ }
+ }
+ }.execute((Void[])null);
+ }
+
+ private void notifyAdapters() {
+ for (int i = mAdapters.size() - 1; i >= 0; i--) {
+ BaseUserAdapter adapter = mAdapters.get(i).get();
+ if (adapter != null) {
+ adapter.notifyDataSetChanged();
+ } else {
+ mAdapters.remove(i);
+ }
+ }
+ }
+
+ public void switchTo(UserRecord record) {
+ int id;
+ if (record.isGuest && record.info == null) {
+ // No guest user. Create one.
+ id = mUserManager.createGuest(mContext,
+ mContext.getResources().getString(R.string.guest_nickname)).id;
+ } else {
+ id = record.info.id;
+ }
+
+ if (ActivityManager.getCurrentUser() == id) {
+ return;
+ }
+
+ try {
+ WindowManagerGlobal.getWindowManagerService().lockNow(null);
+ ActivityManagerNative.getDefault().switchUser(id);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't switch user.", e);
+ }
+ }
+
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
+ final int currentId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ final int N = mUsers.size();
+ for (int i = 0; i < N; i++) {
+ UserRecord record = mUsers.get(i);
+ boolean shouldBeCurrent = record.info.id == currentId;
+ if (record.isCurrent != shouldBeCurrent) {
+ mUsers.set(i, record.copyWithIsCurrent(shouldBeCurrent));
+ }
+ }
+ notifyAdapters();
+ } else {
+ refreshUsers();
+ }
+ }
+ };
+
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("UserSwitcherController state:");
+ pw.print(" mUsers.size="); pw.println(mUsers.size());
+ for (int i = 0; i < mUsers.size(); i++) {
+ final UserRecord u = mUsers.get(i);
+ pw.print(" "); pw.println(u.toString());
+ }
+ }
+
+ public static abstract class BaseUserAdapter extends BaseAdapter {
+
+ final UserSwitcherController mController;
+
+ protected BaseUserAdapter(UserSwitcherController controller) {
+ mController = controller;
+ controller.mAdapters.add(new WeakReference<>(this));
+ }
+
+ @Override
+ public int getCount() {
+ return mController.mUsers.size();
+ }
+
+ @Override
+ public UserRecord getItem(int position) {
+ return mController.mUsers.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return mController.mUsers.get(position).info.id;
+ }
+
+ public void switchTo(UserRecord record) {
+ mController.switchTo(record);
+ }
+ }
+
+ public static final class UserRecord {
+ public final UserInfo info;
+ public final Bitmap picture;
+ public final boolean isGuest;
+ public final boolean isCurrent;
+
+ public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent) {
+ this.info = info;
+ this.picture = picture;
+ this.isGuest = isGuest;
+ this.isCurrent = isCurrent;
+ }
+
+ public UserRecord copyWithIsCurrent(boolean _isCurrent) {
+ return new UserRecord(info, picture, isGuest, _isCurrent);
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("UserRecord(");
+ if (info != null) {
+ sb.append("name=\"" + info.name + "\" id=" + info.id);
+ } else {
+ sb.append("<add guest placeholder>");
+ }
+ if (isGuest) {
+ sb.append(" <isGuest>");
+ }
+ if (isCurrent) {
+ sb.append(" <isCurrent>");
+ }
+ if (picture != null) {
+ sb.append(" <hasPicture>");
+ }
+ sb.append(')');
+ return sb.toString();
+ }
+ }
+
+ public final QSTile.DetailAdapter userDetailAdapter = new QSTile.DetailAdapter() {
+ private final Intent USER_SETTINGS_INTENT = new Intent("android.settings.USER_SETTINGS");
+
+ @Override
+ public int getTitle() {
+ return R.string.quick_settings_user_title;
+ }
+
+ @Override
+ public View createDetailView(Context context, View convertView, ViewGroup parent) {
+ if (!(convertView instanceof UserDetailView)) {
+ convertView = UserDetailView.inflate(context, parent, false);
+ }
+ UserDetailView v = (UserDetailView) convertView;
+ if (v.getAdapter() == null) {
+ v.createAndSetAdapter(UserSwitcherController.this);
+ }
+ return v;
+ }
+
+ @Override
+ public Intent getSettingsIntent() {
+ return USER_SETTINGS_INTENT;
+ }
+
+ @Override
+ public Boolean getToggleState() {
+ return null;
+ }
+
+ @Override
+ public void setToggleState(boolean state) {
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index ad2cf75..0c5d2a5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -908,6 +908,9 @@
if (mDialog != null) {
mDialog.show();
+ if (mCallback != null) {
+ mCallback.onVisible(true);
+ }
}
}
@@ -1160,6 +1163,9 @@
mDialog.dismiss();
clearRemoteStreamController();
mActiveStreamType = -1;
+ if (mCallback != null) {
+ mCallback.onVisible(false);
+ }
}
}
synchronized (sConfirmSafeVolumeLock) {
@@ -1262,5 +1268,6 @@
public interface Callback {
void onZenSettings();
void onInteraction();
+ void onVisible(boolean visible);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index e4f5870..e38c2ac 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -99,6 +99,13 @@
kvm.userActivity();
}
}
+
+ @Override
+ public void onVisible(boolean visible) {
+ if (mAudioManager != null && mVolumeController != null) {
+ mAudioManager.notifyVolumeControllerVisible(mVolumeController, visible);
+ }
+ }
});
mDialogPanel = mPanel;
}
@@ -182,7 +189,7 @@
@Override
public void remoteVolumeChanged(ISessionController binder, int flags)
throws RemoteException {
- MediaController controller = MediaController.fromBinder(binder);
+ MediaController controller = new MediaController(binder);
mPanel.postRemoteVolumeChanged(controller, flags);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 9c166ac..cf04219 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -32,7 +32,6 @@
import android.service.notification.ZenModeConfig;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AnimationUtils;
@@ -54,8 +53,11 @@
private static final String TAG = "ZenModePanel";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final int SECONDS_MS = 1000;
+ private static final int MINUTES_MS = 60 * SECONDS_MS;
+
private static final int[] MINUTE_BUCKETS = DEBUG
- ? new int[] { 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 }
+ ? new int[] { 0, 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 }
: new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
@@ -64,9 +66,7 @@
private static final int TIME_CONDITION_INDEX = 1;
private static final int FIRST_CONDITION_INDEX = 2;
private static final float SILENT_HINT_PULSE_SCALE = 1.1f;
-
- private static final int SECONDS_MS = 1000;
- private static final int MINUTES_MS = 60 * SECONDS_MS;
+ private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
@@ -152,6 +152,7 @@
if (DEBUG) Log.d(mTag, "onAttachedToWindow");
mAttachedZen = getSelectedZen(-1);
refreshExitConditionText();
+ updateWidgets();
}
@Override
@@ -292,7 +293,8 @@
private Condition newTimeCondition(int minutesFromNow) {
final long now = System.currentTimeMillis();
- return timeCondition(now + minutesFromNow * MINUTES_MS, minutesFromNow);
+ final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS;
+ return timeCondition(now + millis, minutesFromNow);
}
private Condition timeCondition(long time, int minutes) {
@@ -369,6 +371,9 @@
}
tag.conditionId = condition != null ? condition.id : null;
tag.rb.setEnabled(enabled);
+ if (Objects.equals(tag.conditionId, mExitConditionId)) {
+ tag.rb.setChecked(true);
+ }
tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index adfa1f2..edeb5b4 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -49,6 +49,9 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionLegacyHelper;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -205,6 +208,8 @@
private Drawable mBackgroundDrawable;
+ private float mElevation;
+
private int mFrameResource = 0;
private int mTextColor = 0;
@@ -224,6 +229,7 @@
private boolean mClosingActionMenu;
private int mVolumeControlStreamType = AudioManager.USE_DEFAULT_STREAM_TYPE;
+ private MediaController mMediaController;
private AudioManager mAudioManager;
private KeyguardManager mKeyguardManager;
@@ -1688,15 +1694,42 @@
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_DOWN: {
+ int direction = keyCode == KeyEvent.KEYCODE_VOLUME_UP ? AudioManager.ADJUST_RAISE
+ : AudioManager.ADJUST_LOWER;
+ // If we have a session send it the volume command, otherwise
+ // use the suggested stream.
+ if (mMediaController != null) {
+ mMediaController.adjustVolume(direction, AudioManager.FLAG_SHOW_UI);
+ } else {
+ MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
+ mVolumeControlStreamType, direction, AudioManager.FLAG_SHOW_UI);
+ }
+ return true;
+ }
case KeyEvent.KEYCODE_VOLUME_MUTE: {
- // Similar code is in PhoneFallbackEventHandler in case the window
- // doesn't have one of these. In this case, we execute it here and
- // eat the event instead, because we have mVolumeControlStreamType
- // and they don't.
getAudioManager().handleKeyDown(event, mVolumeControlStreamType);
return true;
}
+ // These are all the recognized media key codes in
+ // KeyEvent.isMediaKey()
+ case KeyEvent.KEYCODE_MEDIA_PLAY:
+ case KeyEvent.KEYCODE_MEDIA_PAUSE:
+ case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+ case KeyEvent.KEYCODE_MUTE:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_MEDIA_STOP:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ case KeyEvent.KEYCODE_MEDIA_REWIND:
+ case KeyEvent.KEYCODE_MEDIA_RECORD:
+ case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
+ if (mMediaController != null) {
+ if (mMediaController.dispatchMediaButtonEvent(event)) {
+ return true;
+ }
+ }
+ }
case KeyEvent.KEYCODE_MENU: {
onKeyDownPanel((featureId < 0) ? FEATURE_OPTIONS_PANEL : featureId, event);
@@ -1750,7 +1783,19 @@
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_DOWN: {
+ // If we have a session send it the volume command, otherwise
+ // use the suggested stream.
+ if (mMediaController != null) {
+ mMediaController.adjustVolume(0, AudioManager.FLAG_PLAY_SOUND
+ | AudioManager.FLAG_VIBRATE);
+ } else {
+ MediaSessionLegacyHelper.getHelper(getContext()).sendAdjustVolumeBy(
+ mVolumeControlStreamType, 0,
+ AudioManager.FLAG_PLAY_SOUND | AudioManager.FLAG_VIBRATE);
+ }
+ return true;
+ }
case KeyEvent.KEYCODE_VOLUME_MUTE: {
// Similar code is in PhoneFallbackEventHandler in case the window
// doesn't have one of these. In this case, we execute it here and
@@ -1759,6 +1804,25 @@
getAudioManager().handleKeyUp(event, mVolumeControlStreamType);
return true;
}
+ // These are all the recognized media key codes in
+ // KeyEvent.isMediaKey()
+ case KeyEvent.KEYCODE_MEDIA_PLAY:
+ case KeyEvent.KEYCODE_MEDIA_PAUSE:
+ case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+ case KeyEvent.KEYCODE_MUTE:
+ case KeyEvent.KEYCODE_HEADSETHOOK:
+ case KeyEvent.KEYCODE_MEDIA_STOP:
+ case KeyEvent.KEYCODE_MEDIA_NEXT:
+ case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+ case KeyEvent.KEYCODE_MEDIA_REWIND:
+ case KeyEvent.KEYCODE_MEDIA_RECORD:
+ case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
+ if (mMediaController != null) {
+ if (mMediaController.dispatchMediaButtonEvent(event)) {
+ return true;
+ }
+ }
+ }
case KeyEvent.KEYCODE_MENU: {
onKeyUpPanel(featureId < 0 ? FEATURE_OPTIONS_PANEL : featureId,
@@ -3189,6 +3253,7 @@
+ Integer.toHexString(mFrameResource));
}
}
+ mElevation = a.getDimension(com.android.internal.R.styleable.Window_windowElevation, 0);
mTextColor = a.getColor(com.android.internal.R.styleable.Window_textColor, 0xFF000000);
}
@@ -3278,28 +3343,31 @@
// Remaining setup -- of background and title -- that only applies
// to top-level windows.
if (getContainer() == null) {
- Drawable drawable = mBackgroundDrawable;
+ final Drawable background;
if (mBackgroundResource != 0) {
- drawable = getContext().getDrawable(mBackgroundResource);
+ background = getContext().getDrawable(mBackgroundResource);
+ } else {
+ background = mBackgroundDrawable;
}
- mDecor.setWindowBackground(drawable);
- drawable = null;
+ mDecor.setWindowBackground(background);
+
+ final Drawable frame;
if (mFrameResource != 0) {
- drawable = getContext().getDrawable(mFrameResource);
+ frame = getContext().getDrawable(mFrameResource);
+ } else {
+ frame = null;
}
- mDecor.setWindowFrame(drawable);
+ mDecor.setWindowFrame(frame);
- // System.out.println("Text=" + Integer.toHexString(mTextColor) +
- // " Sel=" + Integer.toHexString(mTextSelectedColor) +
- // " Title=" + Integer.toHexString(mTitleColor));
-
- if (mTitleColor == 0) {
- mTitleColor = mTextColor;
- }
+ mDecor.setElevation(mElevation);
if (mTitle != null) {
setTitle(mTitle);
}
+
+ if (mTitleColor == 0) {
+ mTitleColor = mTextColor;
+ }
setTitleColor(mTitleColor);
}
@@ -3773,6 +3841,16 @@
return mVolumeControlStreamType;
}
+ @Override
+ public void setMediaController(MediaController controller) {
+ mMediaController = controller;
+ }
+
+ @Override
+ public MediaController getMediaController() {
+ return mMediaController;
+ }
+
private boolean isTranslucent() {
TypedArray a = getWindowStyle();
return a.getBoolean(a.getResourceId(
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 153384c..a3c84c6 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -250,6 +250,9 @@
// Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock.
long[] mClockTickVibePattern;
+ // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
+ long[] mCalendarDateVibePattern;
+
// Vibrator pattern for haptic feedback during boot when safe mode is disabled.
long[] mSafeModeDisabledVibePattern;
@@ -1071,6 +1074,8 @@
com.android.internal.R.array.config_keyboardTapVibePattern);
mClockTickVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_clockTickVibePattern);
+ mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
+ com.android.internal.R.array.config_calendarDateVibePattern);
mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_safeModeDisabledVibePattern);
mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
@@ -5407,6 +5412,9 @@
case HapticFeedbackConstants.CLOCK_TICK:
pattern = mClockTickVibePattern;
break;
+ case HapticFeedbackConstants.CALENDAR_DATE:
+ pattern = mCalendarDateVibePattern;
+ break;
case HapticFeedbackConstants.SAFE_MODE_DISABLED:
pattern = mSafeModeDisabledVibePattern;
break;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ee7eb9f2..07bb713 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1443,6 +1443,7 @@
somthingChanged |= readEnabledAccessibilityServicesLocked(userState);
somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
somthingChanged |= readTouchExplorationEnabledSettingLocked(userState);
+ somthingChanged |= readHighTextContrastEnabledSettingLocked(userState);
somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
@@ -1506,6 +1507,18 @@
return displayAdjustmentsEnabled;
}
+ private boolean readHighTextContrastEnabledSettingLocked(UserState userState) {
+ final boolean highTextContrastEnabled = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0,
+ userState.mUserId) == 1;
+ if (highTextContrastEnabled != userState.mIsTextHighContrastEnabled) {
+ userState.mIsTextHighContrastEnabled = highTextContrastEnabled;
+ return true;
+ }
+ return false;
+ }
+
private void updateTouchExplorationLocked(UserState userState) {
boolean enabled = false;
final int serviceCount = userState.mBoundServices.size();
@@ -3586,6 +3599,7 @@
public boolean mIsAccessibilityEnabled;
public boolean mIsTouchExplorationEnabled;
+ public boolean mIsTextHighContrastEnabled;
public boolean mIsEnhancedWebAccessibilityEnabled;
public boolean mIsDisplayMagnificationEnabled;
public boolean mIsFilterKeyEventsEnabled;
@@ -3622,6 +3636,9 @@
if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
}
+ if (mIsTextHighContrastEnabled) {
+ clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
+ }
return clientState;
}
@@ -3687,9 +3704,13 @@
private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
+
private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor(
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER);
+ private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
+ Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
+
public AccessibilityContentObserver(Handler handler) {
super(handler);
}
@@ -3714,94 +3735,55 @@
mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(
mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL);
+ contentResolver.registerContentObserver(
+ mHighTextContrastUri, false, this, UserHandle.USER_ALL);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
- if (mAccessibilityEnabledUri.equals(uri)) {
- synchronized (mLock) {
- // Profiles share the accessibility state of the parent. Therefore,
- // we are checking for changes only the parent settings.
- UserState userState = getCurrentUserStateLocked();
- // We will update when the automation service dies.
- if (userState.mUiAutomationService == null) {
- if (readAccessibilityEnabledSettingLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
- }
+ synchronized (mLock) {
+ // Profiles share the accessibility state of the parent. Therefore,
+ // we are checking for changes only the parent settings.
+ UserState userState = getCurrentUserStateLocked();
+
+ // We will update when the automation service dies.
+ if (userState.mUiAutomationService != null) {
+ return;
}
- } else if (mTouchExplorationEnabledUri.equals(uri)) {
- synchronized (mLock) {
- // Profiles share the accessibility state of the parent. Therefore,
- // we are checking for changes only the parent settings.
- UserState userState = getCurrentUserStateLocked();
- // We will update when the automation service dies.
- if (userState.mUiAutomationService == null) {
- if (readTouchExplorationEnabledSettingLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
+
+ if (mAccessibilityEnabledUri.equals(uri)) {
+ if (readAccessibilityEnabledSettingLocked(userState)) {
+ onUserStateChangedLocked(userState);
}
- }
- } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
- synchronized (mLock) {
- // Profiles share the accessibility state of the parent. Therefore,
- // we are checking for changes only the parent settings.
- UserState userState = getCurrentUserStateLocked();
- // We will update when the automation service dies.
- if (userState.mUiAutomationService == null) {
- if (readDisplayMagnificationEnabledSettingLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
+ } else if (mTouchExplorationEnabledUri.equals(uri)) {
+ if (readTouchExplorationEnabledSettingLocked(userState)) {
+ onUserStateChangedLocked(userState);
}
- }
- } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
- synchronized (mLock) {
- // Profiles share the accessibility state of the parent. Therefore,
- // we are checking for changes only the parent settings.
- UserState userState = getCurrentUserStateLocked();
- // We will update when the automation service dies.
- if (userState.mUiAutomationService == null) {
- if (readEnabledAccessibilityServicesLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
+ } else if (mDisplayMagnificationEnabledUri.equals(uri)) {
+ if (readDisplayMagnificationEnabledSettingLocked(userState)) {
+ onUserStateChangedLocked(userState);
}
- }
- } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
- synchronized (mLock) {
- // Profiles share the accessibility state of the parent. Therefore,
- // we are checking for changes only the parent settings.
- UserState userState = getCurrentUserStateLocked();
- // We will update when the automation service dies.
- if (userState.mUiAutomationService == null) {
- if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
+ } else if (mEnabledAccessibilityServicesUri.equals(uri)) {
+ if (readEnabledAccessibilityServicesLocked(userState)) {
+ onUserStateChangedLocked(userState);
}
- }
- } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
- synchronized (mLock) {
- // Profiles share the accessibility state of the parent. Therefore,
- // we are checking for changes only the parent settings.
- UserState userState = getCurrentUserStateLocked();
- // We will update when the automation service dies.
- if (userState.mUiAutomationService == null) {
- if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
+ } else if (mTouchExplorationGrantedAccessibilityServicesUri.equals(uri)) {
+ if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) {
+ onUserStateChangedLocked(userState);
}
- }
- } else if (mDisplayInversionEnabledUri.equals(uri)
- || mDisplayDaltonizerEnabledUri.equals(uri)
- || mDisplayDaltonizerUri.equals(uri)) {
- synchronized (mLock) {
- // Profiles share the accessibility state of the parent. Therefore,
- // we are checking for changes only the parent settings.
- UserState userState = getCurrentUserStateLocked();
- // We will update when the automation service dies.
- if (userState.mUiAutomationService == null) {
- if (readDisplayColorAdjustmentSettingsLocked(userState)) {
- updateDisplayColorAdjustmentSettingsLocked(userState);
- }
+ } else if (mEnhancedWebAccessibilityUri.equals(uri)) {
+ if (readEnhancedWebAccessibilityEnabledChangedLocked(userState)) {
+ onUserStateChangedLocked(userState);
+ }
+ } else if (mDisplayInversionEnabledUri.equals(uri)
+ || mDisplayDaltonizerEnabledUri.equals(uri)
+ || mDisplayDaltonizerUri.equals(uri)) {
+ if (readDisplayColorAdjustmentSettingsLocked(userState)) {
+ updateDisplayColorAdjustmentSettingsLocked(userState);
+ }
+ } else if (mHighTextContrastUri.equals(uri)) {
+ if (readHighTextContrastEnabledSettingLocked(userState)) {
+ onUserStateChangedLocked(userState);
}
}
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 5bfde4d..e8e2813 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -3535,19 +3535,30 @@
}
} while (nRead > 0 && result == BackupTransport.TRANSPORT_OK);
- // Done -- how did it turn out?
- if (result == BackupTransport.TRANSPORT_OK){
- result = transport.finishBackup();
- } else {
- Slog.w(TAG, "Error backing up " + target.packageName);
+ // In all cases we need to give the transport its finish callback
+ int finishResult = transport.finishBackup();
+
+ // If we were otherwise in a good state, now interpret the final
+ // result based on what finishBackup() returned. If we're in a
+ // failure case already, preserve that result and ignore whatever
+ // finishBackup() reported.
+ if (result == BackupTransport.TRANSPORT_OK) {
+ result = finishResult;
}
- } else if (result == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
+
+ if (result != BackupTransport.TRANSPORT_OK) {
+ Slog.e(TAG, "Error " + result
+ + " backing up " + target.packageName);
+ }
+ }
+
+ if (result == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
if (DEBUG) {
Slog.i(TAG, "Transport rejected backup of " + target.packageName
+ ", skipping");
}
// do nothing, clean up, and continue looping
- } else {
+ } else if (result != BackupTransport.TRANSPORT_OK) {
if (DEBUG) {
Slog.i(TAG, "Transport failed; aborting backup");
return;
@@ -3922,6 +3933,11 @@
break;
}
+ // Is it a *file* we need to drop?
+ if (!isRestorableFile(info)) {
+ okay = false;
+ }
+
// If the policy is satisfied, go ahead and set up to pipe the
// data to the agent.
if (DEBUG && okay && mAgent != null) {
@@ -4082,9 +4098,9 @@
}
}
- // Problems setting up the agent communication, or an already-
- // ignored package: skip to the next tar stream entry by
- // reading and discarding this file.
+ // Problems setting up the agent communication, an explicitly
+ // dropped file, or an already-ignored package: skip to the
+ // next stream entry by reading and discarding this file.
if (!okay) {
if (DEBUG) Slog.d(TAG, "[discarding file content]");
long bytesToConsume = (info.size + 511) & ~511;
@@ -4691,6 +4707,31 @@
return info;
}
+ private boolean isRestorableFile(FileMetadata info) {
+ if (FullBackup.CACHE_TREE_TOKEN.equals(info.domain)) {
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "Dropping cache file path " + info.path);
+ }
+ return false;
+ }
+
+ if (FullBackup.ROOT_TREE_TOKEN.equals(info.domain)) {
+ // It's possible this is "no-backup" dir contents in an archive stream
+ // produced on a device running a version of the OS that predates that
+ // API. Respect the no-backup intention and don't let the data get to
+ // the app.
+ if (info.path.startsWith("no_backup/")) {
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "Dropping no_backup file path " + info.path);
+ }
+ return false;
+ }
+ }
+
+ // Otherwise we think this file is good to go
+ return true;
+ }
+
private void HEXLOG(byte[] block) {
int offset = 0;
int todo = block.length;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6554ed3..9945909 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3199,13 +3199,17 @@
break;
}
case NetworkMonitor.EVENT_PROVISIONING_NOTIFICATION: {
- NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
- if (nai == null) {
- loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
- break;
+ if (msg.arg1 == 0) {
+ setProvNotificationVisibleIntent(false, msg.arg2, 0, null, null);
+ } else {
+ NetworkAgentInfo nai = mNetworkForNetId.get(msg.arg2);
+ if (nai == null) {
+ loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor");
+ break;
+ }
+ setProvNotificationVisibleIntent(true, msg.arg2, nai.networkInfo.getType(),
+ nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj);
}
- setProvNotificationVisibleIntent(msg.arg1 != 0, nai.networkInfo.getType(),
- nai.networkInfo.getExtraInfo(), (PendingIntent)msg.obj);
break;
}
case NetworkStateTracker.EVENT_STATE_CHANGED: {
@@ -4958,10 +4962,19 @@
break;
}
}
- setProvNotificationVisibleIntent(visible, networkType, extraInfo, pendingIntent);
+ // Concatenate the range of types onto the range of NetIDs.
+ int id = MAX_NET_ID + 1 + (networkType - ConnectivityManager.TYPE_NONE);
+ setProvNotificationVisibleIntent(visible, id, networkType, extraInfo, pendingIntent);
}
- private void setProvNotificationVisibleIntent(boolean visible, int networkType,
+ /**
+ * Show or hide network provisioning notificaitons.
+ *
+ * @param id an identifier that uniquely identifies this notification. This must match
+ * between show and hide calls. We use the NetID value but for legacy callers
+ * we concatenate the range of types with the range of NetIDs.
+ */
+ private void setProvNotificationVisibleIntent(boolean visible, int id, int networkType,
String extraInfo, PendingIntent intent) {
if (DBG) {
log("setProvNotificationVisibleIntent: E visible=" + visible + " networkType=" +
@@ -5008,14 +5021,14 @@
notification.contentIntent = intent;
try {
- notificationManager.notify(NOTIFICATION_ID, networkType, notification);
+ notificationManager.notify(NOTIFICATION_ID, id, notification);
} catch (NullPointerException npe) {
loge("setNotificaitionVisible: visible notificationManager npe=" + npe);
npe.printStackTrace();
}
} else {
try {
- notificationManager.cancel(NOTIFICATION_ID, networkType);
+ notificationManager.cancel(NOTIFICATION_ID, id);
} catch (NullPointerException npe) {
loge("setNotificaitionVisible: cancel notificationManager npe=" + npe);
npe.printStackTrace();
@@ -5707,6 +5720,17 @@
oldNetwork.asyncChannel.disconnect();
}
+ private void makeDefault(NetworkAgentInfo newNetwork) {
+ if (VDBG) log("Switching to new default network: " + newNetwork);
+ setupDataActivityTracking(newNetwork);
+ try {
+ mNetd.setDefaultNetId(newNetwork.network.netId);
+ } catch (Exception e) {
+ loge("Exception setting default network :" + e);
+ }
+ handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
+ }
+
private void handleConnectionValidated(NetworkAgentInfo newNetwork) {
if (newNetwork == null) {
loge("Unknown NetworkAgentInfo in handleConnectionValidated");
@@ -5800,16 +5824,7 @@
}
if (keep) {
if (isNewDefault) {
- if (VDBG) log("Switching to new default network: " + newNetwork);
- setupDataActivityTracking(newNetwork);
- try {
- mNetd.setDefaultNetId(newNetwork.network.netId);
- } catch (Exception e) {
- loge("Exception setting default network :" + e);
- }
- if (newNetwork.equals(mNetworkForRequestId.get(mDefaultRequest.requestId))) {
- handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
- }
+ makeDefault(newNetwork);
synchronized (ConnectivityService.this) {
// have a new default network, release the transition wakelock in
// a second if it's held. The second pause is to allow apps
@@ -5906,6 +5921,13 @@
}
// TODO: support proxy per network.
}
+ // Make default network if we have no default. Any network is better than no network.
+ if (mNetworkForRequestId.get(mDefaultRequest.requestId) == null &&
+ networkAgent.isVPN() == false &&
+ mDefaultRequest.networkCapabilities.satisfiedByNetworkCapabilities(
+ networkAgent.networkCapabilities)) {
+ makeDefault(networkAgent);
+ }
} else if (state == NetworkInfo.State.DISCONNECTED ||
state == NetworkInfo.State.SUSPENDED) {
networkAgent.asyncChannel.disconnect();
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index a19eb15..87084d5 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1069,27 +1069,31 @@
synchronized (mRecords) {
final int recordCount = mRecords.size();
pw.println("last known state:");
- pw.println(" mCallState=" + mCallState);
- pw.println(" mCallIncomingNumber=" + mCallIncomingNumber);
- pw.println(" mServiceState=" + mServiceState);
- pw.println(" mSignalStrength=" + mSignalStrength);
- pw.println(" mMessageWaiting=" + mMessageWaiting);
- pw.println(" mCallForwarding=" + mCallForwarding);
- pw.println(" mDataActivity=" + mDataActivity);
- pw.println(" mDataConnectionState=" + mDataConnectionState);
- pw.println(" mDataConnectionPossible=" + mDataConnectionPossible);
- pw.println(" mDataConnectionReason=" + mDataConnectionReason);
- pw.println(" mDataConnectionApn=" + mDataConnectionApn);
- pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties);
- pw.println(" mDataConnectionNetworkCapabilities=" +
- mDataConnectionNetworkCapabilities);
+ for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+ pw.println(" Phone Id=" + i);
+ pw.println(" mCallState=" + mCallState[i]);
+ pw.println(" mCallIncomingNumber=" + mCallIncomingNumber[i]);
+ pw.println(" mServiceState=" + mServiceState[i]);
+ pw.println(" mSignalStrength=" + mSignalStrength[i]);
+ pw.println(" mMessageWaiting=" + mMessageWaiting[i]);
+ pw.println(" mCallForwarding=" + mCallForwarding[i]);
+ pw.println(" mDataActivity=" + mDataActivity[i]);
+ pw.println(" mDataConnectionState=" + mDataConnectionState[i]);
+ pw.println(" mDataConnectionPossible=" + mDataConnectionPossible[i]);
+ pw.println(" mDataConnectionReason=" + mDataConnectionReason[i]);
+ pw.println(" mDataConnectionApn=" + mDataConnectionApn[i]);
+ pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties[i]);
+ pw.println(" mDataConnectionNetworkCapabilities=" +
+ mDataConnectionNetworkCapabilities[i]);
+ pw.println(" mCellLocation=" + mCellLocation[i]);
+ pw.println(" mCellInfo=" + mCellInfo.get(i));
+ }
pw.println(" mDefaultSubId=" + mDefaultSubId);
- pw.println(" mCellLocation=" + mCellLocation);
- pw.println(" mCellInfo=" + mCellInfo);
pw.println(" mDcRtInfo=" + mDcRtInfo);
pw.println("registrations: count=" + recordCount);
for (Record r : mRecords) {
pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
+ pw.println("is Legacy = " + r.isLegacyApp + " subId = " + r.subId);
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cdb3835..8b7e0d6 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1189,6 +1189,9 @@
*/
private boolean mUserIsMonkey;
+ /** Flag whether the device has a recents UI */
+ final boolean mHasRecents;
+
final ServiceThread mHandlerThread;
final MainHandler mHandler;
@@ -1808,10 +1811,18 @@
break;
}
case SYSTEM_USER_START_MSG: {
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
+ Integer.toString(msg.arg1), msg.arg1);
mSystemServiceManager.startUser(msg.arg1);
break;
}
case SYSTEM_USER_CURRENT_MSG: {
+ mBatteryStatsService.noteEvent(
+ BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_FINISH,
+ Integer.toString(msg.arg2), msg.arg2);
+ mBatteryStatsService.noteEvent(
+ BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
+ Integer.toString(msg.arg1), msg.arg1);
mSystemServiceManager.switchUser(msg.arg1);
break;
}
@@ -2205,6 +2216,9 @@
mConfigurationSeq = mConfiguration.seq = 1;
mProcessCpuTracker.init();
+ mHasRecents = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_hasRecents);
+
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mStackSupervisor = new ActivityStackSupervisor(this);
@@ -2795,7 +2809,7 @@
void ensurePackageDexOpt(String packageName) {
IPackageManager pm = AppGlobals.getPackageManager();
try {
- if (pm.performDexOpt(packageName)) {
+ if (pm.performDexOptIfNeeded(packageName, null /* instruction set */)) {
mDidDexOpt = true;
}
} catch (RemoteException e) {
@@ -4701,6 +4715,28 @@
}
}
+ @Override
+ public void addPackageDependency(String packageName) {
+ synchronized (this) {
+ int callingPid = Binder.getCallingPid();
+ if (callingPid == Process.myPid()) {
+ // Yeah, um, no.
+ Slog.w(TAG, "Can't addPackageDependency on system process");
+ return;
+ }
+ ProcessRecord proc;
+ synchronized (mPidsSelfLocked) {
+ proc = mPidsSelfLocked.get(Binder.getCallingPid());
+ }
+ if (proc != null) {
+ if (proc.pkgDeps == null) {
+ proc.pkgDeps = new ArraySet<String>(1);
+ }
+ proc.pkgDeps.add(packageName);
+ }
+ }
+ }
+
/*
* The pkg name and app id have to be specified.
*/
@@ -4897,7 +4933,6 @@
// Remove all processes this package may have touched: all with the
// same UID (except for the system or root user), and all whose name
// matches the package name.
- final String procNamePrefix = packageName != null ? (packageName + ":") : null;
final int NP = mProcessNames.getMap().size();
for (int ip=0; ip<NP; ip++) {
SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
@@ -4933,13 +4968,15 @@
// that match it. We need to qualify this by the processes
// that are running under the specified app and user ID.
} else {
- if (UserHandle.getAppId(app.uid) != appId) {
+ final boolean isDep = app.pkgDeps != null
+ && app.pkgDeps.contains(packageName);
+ if (!isDep && UserHandle.getAppId(app.uid) != appId) {
continue;
}
if (userId != UserHandle.USER_ALL && app.userId != userId) {
continue;
}
- if (!app.pkgList.containsKey(packageName)) {
+ if (!app.pkgList.containsKey(packageName) && !isDep) {
continue;
}
}
@@ -5649,6 +5686,11 @@
}
@Override
+ public final void notifyLaunchTaskBehindComplete(IBinder token) {
+ mStackSupervisor.scheduleLaunchTaskBehindComplete(token);
+ }
+
+ @Override
public String getCallingPackage(IBinder token) {
synchronized (this) {
ActivityRecord r = getCallingRecordLocked(token);
@@ -8035,7 +8077,7 @@
checkedGrants = true;
}
userId = handleIncomingUser(callingPid, callingUid, userId,
- false, ALLOW_NON_FULL_IN_PROFILE,
+ false, ALLOW_NON_FULL,
"checkContentProviderPermissionLocked " + cpi.authority, null);
if (userId != tmpTargetUserId) {
// When we actually went to determine the final targer user ID, this ended
@@ -10157,7 +10199,11 @@
}
if (goingCallback != null) goingCallback.run();
-
+
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
+ Integer.toString(mCurrentUserId), mCurrentUserId);
+ mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
+ Integer.toString(mCurrentUserId), mCurrentUserId);
mSystemServiceManager.startUser(mCurrentUserId);
synchronized (this) {
@@ -11007,30 +11053,15 @@
return errList;
}
- static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
- if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
- if (currApp != null) {
- currApp.lru = adj - ProcessList.CACHED_APP_MIN_ADJ + 1;
- }
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
- } else if (adj >= ProcessList.SERVICE_B_ADJ) {
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
- } else if (adj >= ProcessList.HOME_APP_ADJ) {
- if (currApp != null) {
- currApp.lru = 0;
- }
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
- } else if (adj >= ProcessList.SERVICE_ADJ) {
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
- } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
- } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
- } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+ static int procStateToImportance(int procState, int memAdj,
+ ActivityManager.RunningAppProcessInfo currApp) {
+ int imp = ActivityManager.RunningAppProcessInfo.procStateToImportance(procState);
+ if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
+ currApp.lru = memAdj;
} else {
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+ currApp.lru = 0;
}
+ return imp;
}
private void fillInProcMemInfo(ProcessRecord app,
@@ -11048,7 +11079,8 @@
}
outInfo.lastTrimLevel = app.trimMemoryLevel;
int adj = app.curAdj;
- outInfo.importance = oomAdjToImportance(adj, outInfo);
+ int procState = app.curProcState;
+ outInfo.importance = procStateToImportance(procState, adj, outInfo);
outInfo.importanceReasonCode = app.adjTypeCode;
outInfo.processState = app.curProcState;
}
@@ -11075,8 +11107,9 @@
fillInProcMemInfo(app, currApp);
if (app.adjSource instanceof ProcessRecord) {
currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
- currApp.importanceReasonImportance = oomAdjToImportance(
- app.adjSourceOom, null);
+ currApp.importanceReasonImportance =
+ ActivityManager.RunningAppProcessInfo.procStateToImportance(
+ app.adjSourceProcState);
} else if (app.adjSource instanceof ActivityRecord) {
ActivityRecord r = (ActivityRecord)app.adjSource;
if (r.app != null) currApp.importanceReasonPid = r.app.pid;
@@ -12430,12 +12463,11 @@
pw.print(" lastCachedPss="); pw.println(r.lastCachedPss);
pw.print(prefix);
pw.print(" ");
- pw.print("keeping="); pw.print(r.keeping);
- pw.print(" cached="); pw.print(r.cached);
+ pw.print("cached="); pw.print(r.cached);
pw.print(" empty="); pw.print(r.empty);
pw.print(" hasAboveClient="); pw.println(r.hasAboveClient);
- if (!r.keeping) {
+ if (r.setProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
if (r.lastWakeTime != 0) {
long wtime;
BatteryStatsImpl stats = service.mBatteryStatsService.getActiveStatistics();
@@ -15189,7 +15221,6 @@
app.adjSeq = mAdjSeq;
app.curRawAdj = app.maxAdj;
app.foregroundActivities = false;
- app.keeping = true;
app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
// System processes can do UI, and when they do we want to have
@@ -15213,7 +15244,6 @@
return (app.curAdj=app.maxAdj);
}
- app.keeping = false;
app.systemNoUi = false;
// Determine the importance of the process, starting with most
@@ -15458,9 +15488,6 @@
app.adjType = "cch-started-services";
}
}
- // Don't kill this process because it is doing work; it
- // has said it is doing work.
- app.keeping = true;
}
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
@@ -15550,9 +15577,6 @@
if (!client.cached) {
app.cached = false;
}
- if (client.keeping) {
- app.keeping = true;
- }
adjType = "service";
}
}
@@ -15601,7 +15625,7 @@
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
app.adjSource = cr.binding.client;
- app.adjSourceOom = clientAdj;
+ app.adjSourceProcState = clientProcState;
app.adjTarget = s.name;
}
}
@@ -15622,7 +15646,7 @@
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_SERVICE_IN_USE;
app.adjSource = a;
- app.adjSourceOom = adj;
+ app.adjSourceProcState = procState;
app.adjTarget = s.name;
}
}
@@ -15664,11 +15688,10 @@
app.adjType = "provider";
}
app.cached &= client.cached;
- app.keeping |= client.keeping;
app.adjTypeCode = ActivityManager.RunningAppProcessInfo
.REASON_PROVIDER_IN_USE;
app.adjSource = client;
- app.adjSourceOom = clientAdj;
+ app.adjSourceProcState = clientProcState;
app.adjTarget = cpr.name;
}
if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
@@ -15708,7 +15731,6 @@
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
app.cached = false;
- app.keeping = true;
app.adjType = "provider";
app.adjTarget = cpr.name;
}
@@ -15791,9 +15813,6 @@
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
}
- if (adj < ProcessList.CACHED_APP_MIN_ADJ) {
- app.keeping = true;
- }
// Do final modification to adj. Everything we do between here and applying
// the final setAdj must be done in this function, because we will also use
@@ -16015,7 +16034,7 @@
while (i > 0) {
i--;
ProcessRecord app = mLruProcesses.get(i);
- if (!app.keeping) {
+ if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
long wtime;
synchronized (stats) {
wtime = stats.getProcessWakeTime(app.info.uid,
@@ -16060,7 +16079,7 @@
+ " during " + realtimeSince);
app.baseProcessTracker.reportExcessiveWake(app.pkgList);
} else if (doCpuKills && uptimeSince > 0
- && ((cputimeUsed*100)/uptimeSince) >= 50) {
+ && ((cputimeUsed*100)/uptimeSince) >= 25) {
synchronized (stats) {
stats.reportExcessiveCpuLocked(app.info.uid, app.processName,
uptimeSince, cputimeUsed);
@@ -16076,23 +16095,11 @@
}
}
- private final boolean applyOomAdjLocked(ProcessRecord app, boolean wasKeeping,
+ private final boolean applyOomAdjLocked(ProcessRecord app,
ProcessRecord TOP_APP, boolean doingAll, long now) {
boolean success = true;
if (app.curRawAdj != app.setRawAdj) {
- if (wasKeeping && !app.keeping) {
- // This app is no longer something we want to keep. Note
- // its current wake lock time to later know to kill it if
- // it is not behaving well.
- BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- synchronized (stats) {
- app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
- app.pid, SystemClock.elapsedRealtime());
- }
- app.lastCpuTime = app.curCpuTime;
- }
-
app.setRawAdj = app.curRawAdj;
}
@@ -16181,6 +16188,21 @@
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG,
"Proc state change of " + app.processName
+ " to " + app.curProcState);
+ boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE;
+ boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE;
+ if (setImportant && !curImportant) {
+ // This app is no longer something we consider important enough to allow to
+ // use arbitrary amounts of battery power. Note
+ // its current wake lock time to later know to kill it if
+ // it is not behaving well.
+ BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+ synchronized (stats) {
+ app.lastWakeTime = stats.getProcessWakeTime(app.info.uid,
+ app.pid, SystemClock.elapsedRealtime());
+ }
+ app.lastCpuTime = app.curCpuTime;
+
+ }
app.setProcState = app.curProcState;
if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) {
app.notCachedSinceIdle = false;
@@ -16257,11 +16279,9 @@
return false;
}
- final boolean wasKeeping = app.keeping;
-
computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
- return applyOomAdjLocked(app, wasKeeping, TOP_APP, doingAll, now);
+ return applyOomAdjLocked(app, TOP_APP, doingAll, now);
}
final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
@@ -16417,7 +16437,6 @@
ProcessRecord app = mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
app.procStateChanged = false;
- final boolean wasKeeping = app.keeping;
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
// If we haven't yet assigned the final cached adj
@@ -16472,7 +16491,7 @@
}
}
- applyOomAdjLocked(app, wasKeeping, TOP_APP, true, now);
+ applyOomAdjLocked(app, TOP_APP, true, now);
// Count the number of process types.
switch (app.curProcState) {
@@ -17116,7 +17135,8 @@
}
if (foreground) {
- mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_CURRENT_MSG, userId));
+ mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_CURRENT_MSG, userId,
+ oldUserId));
mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
@@ -17491,6 +17511,9 @@
}
uss.mState = UserStartedState.STATE_SHUTDOWN;
}
+ mBatteryStatsService.noteEvent(
+ BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
+ Integer.toString(userId), userId);
mSystemServiceManager.stopUser(userId);
broadcastIntentLocked(null, null, shutdownIntent,
null, shutdownReceiver, 0, null, null, null, AppOpsManager.OP_NONE,
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 46521c5..6c47922 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -167,6 +167,8 @@
ActivityContainer mInitialActivityContainer;
TaskDescription taskDescription; // the recents information for this activity
+ boolean mLaunchTaskBehind; // this activity is actively being launched with
+ // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
@@ -400,6 +402,7 @@
mInitialActivityContainer = container;
if (options != null) {
pendingOptions = new ActivityOptions(options);
+ mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
}
// This starts out true, since the initial state of an activity
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 1f92bf9..32f2624 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -825,7 +825,7 @@
prev.task.touchActiveTime();
clearLaunchTime(prev);
final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
- if (next == null || next.noDisplay || next.task != prev.task) {
+ if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task)) {
prev.updateThumbnail(screenshotActivities(prev), null);
}
stopFullyDrawnTraceIfNeeded();
@@ -1081,6 +1081,7 @@
if (next == mLastScreenshotActivity) {
invalidateLastScreenshot();
}
+ mReturningActivityOptions = null;
}
private void setVisibile(ActivityRecord r, boolean visible) {
@@ -1134,19 +1135,15 @@
return true;
}
- final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
- ActivityRecord r = topRunningActivityLocked(null);
- if (r != null) {
- ensureActivitiesVisibleLocked(r, starting, null, configChanges);
- }
- }
-
/**
* Make sure that all activities that need to be visible (that is, they
* currently can be seen by the user) actually are.
*/
- final void ensureActivitiesVisibleLocked(ActivityRecord top, ActivityRecord starting,
- String onlyThisProcess, int configChanges) {
+ final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
+ ActivityRecord top = topRunningActivityLocked(null);
+ if (top == null) {
+ return;
+ }
if (DEBUG_VISBILITY) Slog.v(
TAG, "ensureActivitiesVisible behind " + top
+ " configChanges=0x" + Integer.toHexString(configChanges));
@@ -1178,37 +1175,34 @@
continue;
}
aboveTop = false;
- if (!behindFullscreen) {
+ // mLaunchingBehind: Activities launching behind are at the back of the task stack
+ // but must be drawn initially for the animation as though they were visible.
+ if (!behindFullscreen || r.mLaunchTaskBehind) {
if (DEBUG_VISBILITY) Slog.v(
TAG, "Make visible? " + r + " finishing=" + r.finishing
+ " state=" + r.state);
- final boolean doThisProcess = onlyThisProcess == null
- || onlyThisProcess.equals(r.processName);
-
// First: if this is not the current activity being started, make
// sure it matches the current configuration.
- if (r != starting && doThisProcess) {
+ if (r != starting) {
ensureActivityConfigurationLocked(r, 0);
}
if (r.app == null || r.app.thread == null) {
- if (onlyThisProcess == null || onlyThisProcess.equals(r.processName)) {
- // This activity needs to be visible, but isn't even
- // running... get it started, but don't resume it
- // at this point.
- if (DEBUG_VISBILITY) Slog.v(TAG, "Start and freeze screen for " + r);
- if (r != starting) {
- r.startFreezingScreenLocked(r.app, configChanges);
- }
- if (!r.visible) {
- if (DEBUG_VISBILITY) Slog.v(
- TAG, "Starting and making visible: " + r);
- setVisibile(r, true);
- }
- if (r != starting) {
- mStackSupervisor.startSpecificActivityLocked(r, false, false);
- }
+ // This activity needs to be visible, but isn't even
+ // running... get it started, but don't resume it
+ // at this point.
+ if (DEBUG_VISBILITY) Slog.v(TAG, "Start and freeze screen for " + r);
+ if (r != starting) {
+ r.startFreezingScreenLocked(r.app, configChanges);
+ }
+ if (!r.visible || r.mLaunchTaskBehind) {
+ if (DEBUG_VISBILITY) Slog.v(
+ TAG, "Starting and making visible: " + r);
+ setVisibile(r, true);
+ }
+ if (r != starting) {
+ mStackSupervisor.startSpecificActivityLocked(r, false, false);
}
} else if (r.visible) {
@@ -1217,17 +1211,14 @@
if (DEBUG_VISBILITY) Slog.v(TAG, "Skipping: already visible at " + r);
r.stopFreezingScreenLocked(false);
try {
- if (mReturningActivityOptions != null) {
- if (activityNdx > 0) {
- ActivityRecord under = activities.get(activityNdx - 1);
- under.app.thread.scheduleOnNewActivityOptions(under.appToken,
- mReturningActivityOptions);
- }
- mReturningActivityOptions = null;
+ if (mReturningActivityOptions != null && r == top && activityNdx > 0) {
+ ActivityRecord under = activities.get(activityNdx - 1);
+ under.app.thread.scheduleOnNewActivityOptions(under.appToken,
+ mReturningActivityOptions);
}
} catch(RemoteException e) {
}
- } else if (onlyThisProcess == null) {
+ } else {
// This activity is not currently visible, but is running.
// Tell it to become visible.
r.visible = true;
@@ -1650,7 +1641,9 @@
} else {
mWindowManager.prepareAppTransition(prev.task == next.task
? AppTransition.TRANSIT_ACTIVITY_OPEN
- : AppTransition.TRANSIT_TASK_OPEN, false);
+ : next.mLaunchTaskBehind
+ ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
+ : AppTransition.TRANSIT_TASK_OPEN, false);
}
}
if (false) {
@@ -1842,8 +1835,11 @@
ActivityStack lastStack = mStackSupervisor.getLastStack();
final boolean fromHome = lastStack.isHomeStack();
if (!isHomeStack() && (fromHome || topTask() != task)) {
- task.setTaskToReturnTo(fromHome ?
- lastStack.topTask().taskType : APPLICATION_ACTIVITY_TYPE);
+ task.setTaskToReturnTo(fromHome
+ ? lastStack.topTask() == null
+ ? HOME_ACTIVITY_TYPE
+ : lastStack.topTask().taskType
+ : APPLICATION_ACTIVITY_TYPE);
}
} else {
task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
@@ -1851,17 +1847,17 @@
mTaskHistory.remove(task);
// Now put task at top.
- int stackNdx = mTaskHistory.size();
+ int taskNdx = mTaskHistory.size();
if (!isCurrentProfileLocked(task.userId)) {
// Put non-current user tasks below current user tasks.
- while (--stackNdx >= 0) {
- if (!isCurrentProfileLocked(mTaskHistory.get(stackNdx).userId)) {
+ while (--taskNdx >= 0) {
+ if (!isCurrentProfileLocked(mTaskHistory.get(taskNdx).userId)) {
break;
}
}
- ++stackNdx;
+ ++taskNdx;
}
- mTaskHistory.add(stackNdx, task);
+ mTaskHistory.add(taskNdx, task);
updateTaskMovement(task, true);
}
@@ -1869,7 +1865,8 @@
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
- if (taskForIdLocked(taskId) == null || newTask) {
+ // mLaunchTaskBehind tasks get placed at the back of the task stack.
+ if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
// Last activity in task had been removed or ActivityManagerService is reusing task.
// Insert or replace.
// Might not even be in.
@@ -1894,7 +1891,8 @@
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
- r.userId, r.info.configChanges, task.voiceSession != null);
+ r.userId, r.info.configChanges, task.voiceSession != null,
+ r.mLaunchTaskBehind);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
@@ -1948,14 +1946,16 @@
mNoAnimActivities.add(r);
} else {
mWindowManager.prepareAppTransition(newTask
- ? AppTransition.TRANSIT_TASK_OPEN
+ ? r.mLaunchTaskBehind
+ ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
+ : AppTransition.TRANSIT_TASK_OPEN
: AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
mNoAnimActivities.remove(r);
}
mWindowManager.addAppToken(task.mActivities.indexOf(r),
r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
- r.info.configChanges, task.voiceSession != null);
+ r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
@@ -1971,7 +1971,12 @@
== ActivityOptions.ANIM_SCENE_TRANSITION) {
doShow = false;
}
- if (SHOW_APP_STARTING_PREVIEW && doShow) {
+ if (r.mLaunchTaskBehind) {
+ // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
+ // tell WindowManager that r is visible even though it is at the back of the stack.
+ mWindowManager.setAppVisibility(r.appToken, true);
+ ensureActivitiesVisibleLocked(null, 0);
+ } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
@@ -2002,7 +2007,7 @@
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
- r.info.configChanges, task.voiceSession != null);
+ r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
ActivityOptions.abort(options);
options = null;
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index bc184c6..b0dfe4a 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -144,6 +144,7 @@
static final int LOCK_TASK_END_MSG = FIRST_SUPERVISOR_STACK_MSG + 10;
static final int CONTAINER_CALLBACK_TASK_LIST_EMPTY = FIRST_SUPERVISOR_STACK_MSG + 11;
static final int CONTAINER_TASK_LIST_EMPTY_TIMEOUT = FIRST_SUPERVISOR_STACK_MSG + 12;
+ static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 13;
private final static String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";
@@ -1557,9 +1558,9 @@
break;
}
}
- final int launchBehindFlags = Intent.FLAG_ACTIVITY_LAUNCH_BEHIND |
- Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
- final boolean affiliateTask = (launchFlags & launchBehindFlags) == launchBehindFlags;
+
+ final boolean launchTaskBehind = r.mLaunchTaskBehind &&
+ (launchFlags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// For whatever reason this activity is being launched into a new
@@ -1709,7 +1710,7 @@
sourceStack.topActivity().task == sourceRecord.task)) {
// We really do want to push this one into the
// user's face, right now.
- if (affiliateTask && sourceRecord != null) {
+ if (launchTaskBehind && sourceRecord != null) {
intentActivity.setTaskToAffiliateWith(sourceRecord.task);
}
movedHome = true;
@@ -1886,7 +1887,7 @@
boolean newTask = false;
boolean keepCurTransition = false;
- TaskRecord taskToAffiliate = affiliateTask && sourceRecord != null ?
+ TaskRecord taskToAffiliate = launchTaskBehind && sourceRecord != null ?
sourceRecord.task : null;
// Should this be considered a new task?
@@ -1898,12 +1899,15 @@
}
newTask = true;
targetStack = adjustStackFocus(r, newTask);
- targetStack.moveToFront();
+ if (!launchTaskBehind) {
+ targetStack.moveToFront();
+ }
if (reuseTask == null) {
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
newTaskIntent != null ? newTaskIntent : intent,
- voiceSession, voiceInteractor, true), taskToAffiliate);
+ voiceSession, voiceInteractor, !launchTaskBehind /* toTop */),
+ taskToAffiliate);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
r.task);
} else {
@@ -1997,7 +2001,10 @@
ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
targetStack.mLastPausedActivity = null;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
- mService.setFocusedActivityLocked(r);
+ if (!launchTaskBehind) {
+ // Don't set focus on an activity that's going to the back.
+ mService.setFocusedActivityLocked(r);
+ }
return ActivityManager.START_SUCCESS;
}
@@ -2394,7 +2401,8 @@
mWindowManager.addAppToken(0, r.appToken, taskId, stackId,
r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
- r.userId, r.info.configChanges, task.voiceSession != null);
+ r.userId, r.info.configChanges, task.voiceSession != null,
+ r.mLaunchTaskBehind);
}
mWindowManager.addTask(taskId, stackId, false);
}
@@ -2642,6 +2650,19 @@
return true;
}
+ // Called when WindowManager has finished animating the launchingBehind activity to the back.
+ void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
+ r.mLaunchTaskBehind = false;
+ final TaskRecord task = r.task;
+ task.setLastThumbnail(task.stack.screenshotActivities(r));
+ mService.addRecentTaskLocked(task);
+ mWindowManager.setAppVisibility(r.appToken, false);
+ }
+
+ void scheduleLaunchTaskBehindComplete(IBinder token) {
+ mHandler.obtainMessage(LAUNCH_TASK_BEHIND_COMPLETE, token).sendToTarget();
+ }
+
void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
// First the front stacks. In case any are not fullscreen and are in front of home.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
@@ -3268,6 +3289,7 @@
Settings.System.LOCK_TO_APP_EXIT_LOCKED) != 0;
if (shouldLockKeyguard) {
mWindowManager.lockNow(null);
+ mWindowManager.dismissKeyguard();
}
} catch (SettingNotFoundException e) {
// No setting, don't lock.
@@ -3293,6 +3315,14 @@
((ActivityContainer) msg.obj).onTaskListEmptyLocked();
}
} break;
+ case LAUNCH_TASK_BEHIND_COMPLETE: {
+ synchronized (mService) {
+ ActivityRecord r = ActivityRecord.forToken((IBinder) msg.obj);
+ if (r != null) {
+ handleLaunchTaskBehindCompleteLocked(r);
+ }
+ }
+ } break;
}
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index da444f9..ac19bde 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -186,6 +186,34 @@
}
}
+ public void noteSyncStart(String name, int uid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteSyncStartLocked(name, uid);
+ }
+ }
+
+ public void noteSyncFinish(String name, int uid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteSyncFinishLocked(name, uid);
+ }
+ }
+
+ public void noteJobStart(String name, int uid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteJobStartLocked(name, uid);
+ }
+ }
+
+ public void noteJobFinish(String name, int uid) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteJobFinishLocked(name, uid);
+ }
+ }
+
public void noteStartWakelock(int uid, int pid, String name, String historyName, int type,
boolean unimportantForLogging) {
enforceCallingPermission();
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index fe39744..6f9b23d 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -16,28 +16,9 @@
package com.android.server.am;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.graphics.BitmapFactory;
-import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.Message;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.style.DynamicDrawableSpan;
-import android.text.style.ImageSpan;
-import android.util.DisplayMetrics;
-import android.util.Slog;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.widget.TextView;
import android.widget.Toast;
import com.android.internal.R;
@@ -49,20 +30,12 @@
public class LockTaskNotify {
private static final String TAG = "LockTaskNotify";
- private static final int SHOW_LENGTH_MS = 1500;
-
private final Context mContext;
private final H mHandler;
- private ClingWindowView mClingWindow;
- private WindowManager mWindowManager;
- private boolean mIsStarting;
-
public LockTaskNotify(Context context) {
mContext = context;
mHandler = new H();
- mWindowManager = (WindowManager)
- mContext.getSystemService(Context.WINDOW_SERVICE);
}
public void showToast(boolean isLocked) {
@@ -70,163 +43,25 @@
}
public void handleShowToast(boolean isLocked) {
- final Resources r = Resources.getSystem();
String text = mContext.getString(isLocked
? R.string.lock_to_app_toast_locked : R.string.lock_to_app_toast);
- Toast toast = Toast.makeText(mContext, text, Toast.LENGTH_LONG);
- TextView tv = (TextView) toast.getView().findViewById(R.id.message);
-
- if (isLocked) {
- tv.setText(text);
- } else {
- final SpannableString formattedText =
- new SpannableString(text.replace('$', ' '));
- final ImageSpan imageSpan = new ImageSpan(mContext,
- BitmapFactory.decodeResource(r, R.drawable.ic_recent),
- DynamicDrawableSpan.ALIGN_BOTTOM);
- final int index = text.indexOf('$');
- if (index >= 0) {
- formattedText.setSpan(imageSpan, index, index + 1,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
-
- // Make icon fit.
- final float width = imageSpan.getDrawable().getIntrinsicWidth();
- final float height = imageSpan.getDrawable().getIntrinsicHeight();
- final int lineHeight = tv.getLineHeight();
- imageSpan.getDrawable().setBounds(0, 0, (int) (lineHeight * width / height),
- lineHeight);
-
- tv.setText(formattedText);
- }
-
-
- toast.show();
+ Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
}
public void show(boolean starting) {
- mIsStarting = starting;
- mHandler.obtainMessage(H.SHOW).sendToTarget();
- }
-
- public WindowManager.LayoutParams getClingWindowLayoutParams() {
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_TOAST,
- 0
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
- ,
- PixelFormat.TRANSLUCENT);
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
- lp.setTitle("LockTaskNotify");
- lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
- lp.gravity = Gravity.FILL;
- return lp;
- }
-
- public FrameLayout.LayoutParams getImageLayoutParams() {
- return new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
- }
-
- private void handleShow() {
- mClingWindow = new ClingWindowView(mContext);
-
- // we will be hiding the nav bar, so layout as if it's already hidden
- mClingWindow.setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-
- // show the confirmation
- WindowManager.LayoutParams lp = getClingWindowLayoutParams();
- mWindowManager.addView(mClingWindow, lp);
- }
-
- private void handleHide() {
- if (mClingWindow != null) {
- mWindowManager.removeView(mClingWindow);
- mClingWindow = null;
+ int showString = R.string.lock_to_app_exit;
+ if (starting) {
+ showString = R.string.lock_to_app_start;
}
- }
-
-
- private class ClingWindowView extends FrameLayout {
- private View mView;
-
- private Runnable mUpdateLayoutRunnable = new Runnable() {
- @Override
- public void run() {
- if (mView != null && mView.getParent() != null) {
- mView.setLayoutParams(getImageLayoutParams());
- }
- }
- };
-
- private BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
- post(mUpdateLayoutRunnable);
- }
- }
- };
-
- public ClingWindowView(Context context) {
- super(context);
- setClickable(true);
- }
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- DisplayMetrics metrics = new DisplayMetrics();
- mWindowManager.getDefaultDisplay().getMetrics(metrics);
-
- int id = R.layout.lock_to_app_exit;
- if (mIsStarting) {
- id = R.layout.lock_to_app_enter;
- }
- mView = View.inflate(getContext(), id, null);
-
- addView(mView, getImageLayoutParams());
-
- mContext.registerReceiver(mReceiver,
- new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
- mHandler.sendMessageDelayed(mHandler.obtainMessage(H.HIDE), SHOW_LENGTH_MS);
- }
-
- @Override
- public void onDetachedFromWindow() {
- mContext.unregisterReceiver(mReceiver);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent motion) {
- Slog.v(TAG, "ClingWindowView.onTouchEvent");
- return true;
- }
+ Toast.makeText(mContext, mContext.getString(showString), Toast.LENGTH_LONG).show();
}
private final class H extends Handler {
- private static final int SHOW = 1;
- private static final int HIDE = 2;
private static final int SHOW_TOAST = 3;
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
- case SHOW:
- handleShow();
- break;
- case HIDE:
- handleHide();
- break;
case SHOW_TOAST:
handleShowToast(msg.arg1 != 0);
break;
diff --git a/services/core/java/com/android/server/am/LockToAppRequestDialog.java b/services/core/java/com/android/server/am/LockToAppRequestDialog.java
index 6e86dff..0847b52 100644
--- a/services/core/java/com/android/server/am/LockToAppRequestDialog.java
+++ b/services/core/java/com/android/server/am/LockToAppRequestDialog.java
@@ -2,21 +2,23 @@
package com.android.server.am;
import android.app.AlertDialog;
+import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Resources;
-import android.graphics.BitmapFactory;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.provider.Settings;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.style.DynamicDrawableSpan;
-import android.text.style.ImageSpan;
+import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import android.view.WindowManager;
-import android.widget.TextView;
+import android.widget.CheckBox;
import com.android.internal.R;
+import com.android.internal.widget.ILockSettings;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtilsCache;
public class LockToAppRequestDialog implements OnClickListener {
private static final String TAG = "ActivityManager";
@@ -27,55 +29,95 @@
private AlertDialog mDialog;
private TaskRecord mRequestedTask;
+ private CheckBox mCheckbox;
+
+ private ILockSettings mLockSettingsService;
+
public LockToAppRequestDialog(Context context, ActivityManagerService activityManagerService) {
mContext = context;
mService = activityManagerService;
}
+ private ILockSettings getLockSettings() {
+ if (mLockSettingsService == null) {
+ mLockSettingsService = LockPatternUtilsCache.getInstance(
+ ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings")));
+ }
+ return mLockSettingsService;
+ }
+
+ private int getLockString(int userId) {
+ try {
+ int quality = (int) getLockSettings().getLong(LockPatternUtils.PASSWORD_TYPE_KEY,
+ DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, userId);
+ switch (quality) {
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ return R.string.lock_to_app_unlock_pin;
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+ return R.string.lock_to_app_unlock_password;
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ if (getLockSettings().getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false,
+ userId)) {
+ return R.string.lock_to_app_unlock_pattern;
+ }
+ }
+ } catch (RemoteException e) {
+ }
+ return 0;
+ }
+
public void showLockTaskPrompt(TaskRecord task) {
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
}
mRequestedTask = task;
+ final int unlockStringId = getLockString(task.userId);
final Resources r = Resources.getSystem();
- final String descriptionString = r.getString(R.string.lock_to_app_description);
- final SpannableString description =
- new SpannableString(descriptionString.replace('$', ' '));
- final ImageSpan imageSpan = new ImageSpan(mContext,
- BitmapFactory.decodeResource(r, R.drawable.ic_recent),
- DynamicDrawableSpan.ALIGN_BOTTOM);
- final int index = descriptionString.indexOf('$');
- if (index >= 0) {
- description.setSpan(imageSpan, index, index + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- mDialog =
- new AlertDialog.Builder(mContext)
+ final String description= r.getString(R.string.lock_to_app_description);
+ AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
.setTitle(r.getString(R.string.lock_to_app_title))
.setMessage(description)
.setPositiveButton(r.getString(R.string.lock_to_app_positive), this)
- .setNegativeButton(r.getString(R.string.lock_to_app_negative), this)
- .create();
+ .setNegativeButton(r.getString(R.string.lock_to_app_negative), this);
+ if (unlockStringId != 0) {
+ builder.setView(R.layout.lock_to_app_checkbox);
+ }
+ mDialog = builder.create();
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mDialog.show();
- // Make icon fit.
- final TextView msgTxt = (TextView) mDialog.findViewById(R.id.message);
- final float width = imageSpan.getDrawable().getIntrinsicWidth();
- final float height = imageSpan.getDrawable().getIntrinsicHeight();
- final int lineHeight = msgTxt.getLineHeight();
- imageSpan.getDrawable().setBounds(0, 0, (int) (lineHeight * width / height), lineHeight);
+ if (unlockStringId != 0) {
+ String unlockString = mContext.getString(unlockStringId);
+ mCheckbox = (CheckBox) mDialog.findViewById(R.id.lock_to_app_checkbox);
+ mCheckbox.setText(mContext.getString(R.string.lock_to_app_use_screen_lock,
+ unlockString));
+
+ // Remember state.
+ try {
+ boolean useLock = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.LOCK_TO_APP_EXIT_LOCKED) != 0;
+ mCheckbox.setChecked(useLock);
+ } catch (SettingNotFoundException e) {
+ }
+ } else {
+ mCheckbox = null;
+ }
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (DialogInterface.BUTTON_POSITIVE == which) {
Slog.d(TAG, "accept lock-to-app request");
- // Automatically enable if not currently on. (Could be triggered by an app)
+ // Set whether to use the lock screen when exiting.
Settings.System.putInt(mContext.getContentResolver(),
- Settings.System.LOCK_TO_APP_ENABLED, 1);
+ Settings.System.LOCK_TO_APP_EXIT_LOCKED,
+ mCheckbox != null && mCheckbox.isChecked() ? 1 : 0);
// Start lock-to-app.
mService.startLockTaskMode(mRequestedTask);
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 2f25bd4..b33f7b7 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -55,6 +55,7 @@
// List of packages running in the process
final ArrayMap<String, ProcessStats.ProcessStateHolder> pkgList
= new ArrayMap<String, ProcessStats.ProcessStateHolder>();
+ ArraySet<String> pkgDeps; // additional packages we have a dependency on
IApplicationThread thread; // the actual proc... may be null only if
// 'persistent' is true (in which case we
// are in the process of launching the app)
@@ -83,7 +84,6 @@
int pssProcState = -1; // The proc state we are currently requesting pss for
boolean serviceb; // Process currently is on the service B list
boolean serviceHighRam; // We are forcing to service B list due to its RAM use
- boolean keeping; // Actively running code so don't kill due to that?
boolean setIsForeground; // Running foreground UI when last set?
boolean notCachedSinceIdle; // Has this process not been in a cached state since last idle?
boolean hasClientActivities; // Are there any client services with activities?
@@ -125,7 +125,7 @@
String adjType; // Debugging: primary thing impacting oom_adj.
int adjTypeCode; // Debugging: adj code to report to app.
Object adjSource; // Debugging: option dependent object.
- int adjSourceOom; // Debugging: oom_adj of adjSource's process.
+ int adjSourceProcState; // Debugging: proc state of adjSource's process.
Object adjTarget; // Debugging: target component impacting oom_adj.
// contains HistoryRecord objects
@@ -196,6 +196,14 @@
pw.print(pkgList.keyAt(i));
}
pw.println("}");
+ if (pkgDeps != null) {
+ pw.print(prefix); pw.print("packageDependencies={");
+ for (int i=0; i<pkgDeps.size(); i++) {
+ if (i > 0) pw.print(", ");
+ pw.print(pkgDeps.valueAt(i));
+ }
+ pw.println("}");
+ }
pw.print(prefix); pw.print("compat="); pw.println(compat);
if (instrumentationClass != null || instrumentationProfileFile != null
|| instrumentationArguments != null) {
@@ -225,8 +233,7 @@
pw.print(" lruSeq="); pw.print(lruSeq);
pw.print(" lastPss="); pw.print(lastPss);
pw.print(" lastCachedPss="); pw.println(lastCachedPss);
- pw.print(prefix); pw.print("keeping="); pw.print(keeping);
- pw.print(" cached="); pw.print(cached);
+ pw.print(prefix); pw.print("cached="); pw.print(cached);
pw.print(" empty="); pw.println(empty);
if (serviceb) {
pw.print(prefix); pw.print("serviceb="); pw.print(serviceb);
@@ -275,16 +282,15 @@
if (hasStartedServices) {
pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices);
}
- if (!keeping) {
+ if (setProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
long wtime;
synchronized (mBatteryStats) {
wtime = mBatteryStats.getProcessWakeTime(info.uid,
pid, SystemClock.elapsedRealtime());
}
- long timeUsed = wtime - lastWakeTime;
pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
pw.print(" timeUsed=");
- TimeUtils.formatDuration(timeUsed, pw); pw.println("");
+ TimeUtils.formatDuration(wtime-lastWakeTime, pw); pw.println("");
pw.print(prefix); pw.print("lastCpuTime="); pw.print(lastCpuTime);
pw.print(" timeUsed=");
TimeUtils.formatDuration(curCpuTime-lastCpuTime, pw); pw.println("");
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 6fb8570..545723a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -148,8 +148,8 @@
/**
* Request ConnectivityService display provisioning notification.
* arg1 = Whether to make the notification visible.
- * obj = Intent to be launched when notification selected by user.
- * replyTo = NetworkAgentInfo.messenger so ConnectivityService can identify sender.
+ * arg2 = NetID.
+ * obj = Intent to be launched when notification selected by user, null if !arg1.
*/
public static final int EVENT_PROVISIONING_NOTIFICATION = BASE + 12;
@@ -447,9 +447,9 @@
// Initiate notification to sign-in.
Intent intent = new Intent(ACTION_SIGN_IN_REQUESTED);
intent.putExtra(Intent.EXTRA_TEXT, String.valueOf(mNetworkAgentInfo.network.netId));
- Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 1, 0,
+ Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 1,
+ mNetworkAgentInfo.network.netId,
PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
- message.replyTo = mNetworkAgentInfo.messenger;
mConnectivityServiceHandler.sendMessage(message);
}
@@ -470,8 +470,8 @@
@Override
public void exit() {
- Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 0, 0, null);
- message.replyTo = mNetworkAgentInfo.messenger;
+ Message message = obtainMessage(EVENT_PROVISIONING_NOTIFICATION, 0,
+ mNetworkAgentInfo.network.netId, null);
mConnectivityServiceHandler.sendMessage(message);
mContext.unregisterReceiver(mUserRespondedBroadcastReceiver);
mUserRespondedBroadcastReceiver = null;
@@ -648,6 +648,7 @@
new InputStreamReader(socket.getInputStream()));
OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
writer.write("GET " + url.getFile() + " HTTP/1.1\r\nHost: " + url.getHost() +
+ "\r\nUser-Agent: " + System.getProperty("http.agent") +
"\r\nConnection: close\r\n\r\n");
writer.flush();
String response = reader.readLine();
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 1b40cdf..08d6fc9 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1212,8 +1212,7 @@
} else {
try {
mEventName = mSyncOperation.wakeLockName();
- mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_SYNC_START,
- mEventName, mSyncAdapterUid);
+ mBatteryStats.noteSyncStart(mEventName, mSyncAdapterUid);
} catch (RemoteException e) {
}
}
@@ -1232,8 +1231,7 @@
mBound = false;
mContext.unbindService(this);
try {
- mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_SYNC_FINISH,
- mEventName, mSyncAdapterUid);
+ mBatteryStats.noteSyncFinish(mEventName, mSyncAdapterUid);
} catch (RemoteException e) {
}
}
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 3028100..384cd4a 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -203,8 +203,8 @@
// in config.xml to allow customization.
static final int IRT_MS = 300;
- static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "hdmi_cec.preferred_address.playback";
- static final String PROPERTY_PREFERRED_ADDRESS_TV = "hdmi_cec.preferred_address.tv";
+ static final String PROPERTY_PREFERRED_ADDRESS_PLAYBACK = "hdmi_cec.prefaddr.playback";
+ static final String PROPERTY_PREFERRED_ADDRESS_TV = "hdmi_cec.prefaddr.tv";
private Constants() { /* cannot be instantiated */ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 44b0f28..6aa86a7 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -21,9 +21,6 @@
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.IHdmiControlCallback;
import android.media.AudioManager;
-import android.media.AudioManager.OnAudioPortUpdateListener;
-import android.media.AudioPatch;
-import android.media.AudioPort;
import android.media.AudioSystem;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -56,9 +53,10 @@
// Whether ARC feature is enabled or not.
private boolean mArcFeatureEnabled = false;
- // Whether SystemAudioMode is "On" or not.
+ // Whether System audio mode is activated or not.
+ // This becomes true only when all system audio sequences are finished.
@GuardedBy("mLock")
- private boolean mSystemAudioMode;
+ private boolean mSystemAudioActivated = false;
// The previous port id (input) before switching to the new one. This is remembered in order to
// be able to switch to it upon receiving <Inactive Source> from currently active source.
@@ -89,9 +87,15 @@
// If true, TV going to standby mode puts other devices also to standby.
private boolean mAutoDeviceOff;
+ // If true, TV wakes itself up when receiving <Text/Image View On>.
+ private boolean mAutoWakeup;
+
HdmiCecLocalDeviceTv(HdmiControlService service) {
super(service, HdmiCecDeviceInfo.DEVICE_TV);
mPrevPortId = Constants.INVALID_PORT_ID;
+ mAutoDeviceOff = mService.readBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
+ true);
+ mAutoWakeup = mService.readBooleanSetting(Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED, true);
}
@Override
@@ -102,11 +106,8 @@
mAddress, mService.getPhysicalAddress(), mDeviceType));
mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
mAddress, mService.getVendorId()));
- mSystemAudioMode = mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_ENABLED, false);
launchRoutingControl(fromBootup);
launchDeviceDiscovery();
- registerAudioPortUpdateListener();
- // TODO: unregister audio port update listener if local device is released.
}
@Override
@@ -121,32 +122,7 @@
@ServiceThreadOnly
protected void setPreferredAddress(int addr) {
assertRunOnServiceThread();
- SystemProperties.set(Constants.PROPERTY_PREFERRED_ADDRESS_TV,
- String.valueOf(addr));
- }
-
- private void registerAudioPortUpdateListener() {
- mService.getAudioManager().registerAudioPortUpdateListener(
- new OnAudioPortUpdateListener() {
- @Override
- public void OnAudioPatchListUpdate(AudioPatch[] patchList) {}
-
- @Override
- public void OnAudioPortListUpdate(AudioPort[] portList) {
- if (!mSystemAudioMode) {
- return;
- }
- int devices = mService.getAudioManager().getDevicesForStream(
- AudioSystem.STREAM_MUSIC);
- if ((devices & ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER)
- != 0) {
- // TODO: release system audio here.
- }
- }
-
- @Override
- public void OnServiceDied() {}
- });
+ SystemProperties.set(Constants.PROPERTY_PREFERRED_ADDRESS_TV, String.valueOf(addr));
}
/**
@@ -491,7 +467,7 @@
@ServiceThreadOnly
protected boolean handleTextViewOn(HdmiCecMessage message) {
assertRunOnServiceThread();
- if (mService.isPowerStandbyOrTransient()) {
+ if (mService.isPowerStandbyOrTransient() && mAutoWakeup) {
mService.wakeUp();
}
// TODO: Connect to Hardware input manager to invoke TV App with the appropriate channel
@@ -560,7 +536,7 @@
// If there is AVR, initiate System Audio Auto initiation action,
// which turns on and off system audio according to last system
// audio setting.
- if (mSystemAudioMode && getAvrDeviceInfo() != null) {
+ if (mSystemAudioActivated && getAvrDeviceInfo() != null) {
addAndStartAction(new SystemAudioAutoInitiationAction(
HdmiCecLocalDeviceTv.this,
getAvrDeviceInfo().getLogicalAddress()));
@@ -603,21 +579,34 @@
// # Seq 25
void setSystemAudioMode(boolean on, boolean updateSetting) {
+ if (updateSetting) {
+ mService.writeBooleanSetting(Global.HDMI_SYSTEM_AUDIO_ENABLED, on);
+ }
+ updateAudioManagerForSystemAudio(on);
synchronized (mLock) {
- if (on != mSystemAudioMode) {
- mSystemAudioMode = on;
- if (updateSetting) {
- mService.writeBooleanSetting(Global.HDMI_SYSTEM_AUDIO_ENABLED, on);
- }
+ if (mSystemAudioActivated != on) {
+ mSystemAudioActivated = on;
mService.announceSystemAudioModeChange(on);
}
}
}
- boolean getSystemAudioMode() {
- synchronized (mLock) {
- return mSystemAudioMode;
+ private void updateAudioManagerForSystemAudio(boolean on) {
+ // TODO: remove output device, once update AudioManager api.
+ mService.getAudioManager().setHdmiSystemAudioSupported(on);
+ }
+
+ boolean isSystemAudioActivated() {
+ if (getAvrDeviceInfo() == null) {
+ return false;
}
+ synchronized (mLock) {
+ return mSystemAudioActivated;
+ }
+ }
+
+ boolean getSystemAudioModeSetting() {
+ return mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_ENABLED, false);
}
/**
@@ -717,7 +706,7 @@
@ServiceThreadOnly
void changeVolume(int curVolume, int delta, int maxVolume) {
assertRunOnServiceThread();
- if (delta == 0 || !isSystemAudioOn()) {
+ if (delta == 0 || !isSystemAudioActivated()) {
return;
}
@@ -745,7 +734,7 @@
@ServiceThreadOnly
void changeMute(boolean mute) {
assertRunOnServiceThread();
- if (!isSystemAudioOn()) {
+ if (!isSystemAudioActivated()) {
return;
}
@@ -756,12 +745,10 @@
}
private boolean isSystemAudioOn() {
- if (getAvrDeviceInfo() == null) {
- return false;
- }
+
synchronized (mLock) {
- return mSystemAudioMode;
+ return mSystemAudioActivated;
}
}
@@ -1115,6 +1102,14 @@
void setAutoDeviceOff(boolean enabled) {
assertRunOnServiceThread();
mAutoDeviceOff = enabled;
+ mService.writeBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, enabled);
+ }
+
+ @ServiceThreadOnly
+ void setAutoWakeup(boolean enabled) {
+ assertRunOnServiceThread();
+ mAutoWakeup = enabled;
+ mService.writeBooleanSetting(Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED, enabled);
}
@Override
@@ -1176,7 +1171,7 @@
if (!mService.isControlEnabled()) {
return;
}
- if (!initiatedByCec) {
+ if (!initiatedByCec && mAutoDeviceOff) {
mService.sendCecCommand(HdmiCecMessageBuilder.buildStandby(
mAddress, Constants.ADDR_BROADCAST));
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a9a391b..0239c83 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -44,7 +44,6 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings.Global;
-import android.provider.Settings.SettingNotFoundException;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -828,7 +827,7 @@
if (tv == null) {
return false;
}
- return tv.getSystemAudioMode();
+ return tv.isSystemAudioActivated();
}
@Override
diff --git a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
index 6204c16..813901d 100644
--- a/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
+++ b/services/core/java/com/android/server/hdmi/HotplugDetectionAction.java
@@ -108,7 +108,7 @@
if (mTimeoutCount == 0) {
pollAllDevices();
} else {
- if (tv().getSystemAudioMode()) {
+ if (tv().isSystemAudioActivated()) {
pollAudioSystem();
}
}
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
index f89e299..7d7a95b 100644
--- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -158,7 +158,7 @@
if (HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress)
== HdmiCecDeviceInfo.DEVICE_AUDIO_SYSTEM) {
- if (tv().getSystemAudioMode()) {
+ if (tv().getSystemAudioModeSetting()) {
addAndStartAction(new SystemAudioAutoInitiationAction(localDevice(),
mDeviceLogicalAddress));
}
diff --git a/services/core/java/com/android/server/hdmi/RoutingControlAction.java b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
index 46dc453..8296f69 100644
--- a/services/core/java/com/android/server/hdmi/RoutingControlAction.java
+++ b/services/core/java/com/android/server/hdmi/RoutingControlAction.java
@@ -114,9 +114,8 @@
tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
}
}
- invokeCallback(HdmiControlManager.RESULT_SUCCESS);
- finish();
- }
+ finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
+ }
private int getTvPowerStatus() {
return tv().getPowerStatus();
@@ -132,6 +131,11 @@
mCurrentRoutingPath));
}
+ private void finishWithCallback(int result) {
+ invokeCallback(result);
+ finish();
+ }
+
@Override
public void handleTimerEvent(int timeoutState) {
if (mState != timeoutState || mState == STATE_NONE) {
@@ -152,6 +156,7 @@
});
} else {
tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
+ finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
}
return;
case STATE_WAIT_FOR_REPORT_POWER_STATUS:
@@ -159,8 +164,7 @@
tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
sendSetStreamPath();
}
- invokeCallback(HdmiControlManager.RESULT_SUCCESS);
- finish();
+ finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
return;
}
}
@@ -177,6 +181,7 @@
} else {
tv().updateActivePortId(tv().pathToPortId(mCurrentRoutingPath));
sendSetStreamPath();
+ finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
}
}
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
index 77783b7..df9bdfc 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
@@ -48,7 +48,7 @@
}
private void handleSystemAudioActionFromAvr() {
- if (mTargetAudioStatus == tv().getSystemAudioMode()) {
+ if (mTargetAudioStatus == tv().isSystemAudioActivated()) {
finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
return;
}
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
index d03634e..137cada 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java
@@ -73,7 +73,7 @@
private void handleSystemAudioModeStatusMessage() {
// If the last setting is system audio, turn on system audio whatever AVR status is.
- if (tv().getSystemAudioMode()) {
+ if (tv().getSystemAudioModeSetting()) {
if (canChangeSystemAudio()) {
addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true, null));
}
@@ -102,7 +102,7 @@
}
private void handleSystemAudioModeStatusTimeout() {
- if (tv().getSystemAudioMode()) {
+ if (tv().getSystemAudioModeSetting()) {
if (canChangeSystemAudio()) {
addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true, null));
}
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
index 91805c5..1066204 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
@@ -68,7 +68,7 @@
// the audio amplifier is unknown.
tv().setAudioStatus(false, Constants.UNKNOWN_VOLUME);
- int uiCommand = tv().getSystemAudioMode()
+ int uiCommand = tv().isSystemAudioActivated()
? HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION // SystemAudioMode: ON
: HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION; // SystemAudioMode: OFF
sendUserControlPressedAndReleased(mAvrAddress, uiCommand);
@@ -98,7 +98,7 @@
int volume = params[0] & 0x7F;
tv().setAudioStatus(mute, volume);
- if ((tv().getSystemAudioMode() && mute) || (!tv().getSystemAudioMode() && !mute)) {
+ if (!(tv().isSystemAudioActivated() ^ mute)) {
// Toggle AVR's mute status to match with the system audio status.
sendUserControlPressedAndReleased(mAvrAddress, HdmiCecKeycode.CEC_KEYCODE_MUTE);
}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 7f8b232..caae9f5 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -35,16 +35,20 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
+import com.android.internal.app.IBatteryStats;
import com.android.server.job.controllers.BatteryController;
import com.android.server.job.controllers.ConnectivityController;
import com.android.server.job.controllers.IdleController;
@@ -52,8 +56,6 @@
import com.android.server.job.controllers.StateController;
import com.android.server.job.controllers.TimeController;
-import java.util.LinkedList;
-
/**
* Responsible for taking jobs representing work to be performed by a client app, and determining
* based on the criteria specified when that job should be run against the client application's
@@ -74,7 +76,7 @@
private static final int MAX_JOB_CONTEXTS_COUNT = 3;
static final String TAG = "JobManagerService";
/** Master list of jobs. */
- private final JobStore mJobs;
+ final JobStore mJobs;
static final int MSG_JOB_EXPIRED = 0;
static final int MSG_CHECK_JOB = 1;
@@ -84,33 +86,41 @@
* Minimum # of idle jobs that must be ready in order to force the JMS to schedule things
* early.
*/
- private static final int MIN_IDLE_COUNT = 1;
+ static final int MIN_IDLE_COUNT = 1;
/**
* Minimum # of connectivity jobs that must be ready in order to force the JMS to schedule
* things early.
*/
- private static final int MIN_CONNECTIVITY_COUNT = 2;
+ static final int MIN_CONNECTIVITY_COUNT = 2;
/**
* Minimum # of jobs (with no particular constraints) for which the JMS will be happy running
* some work early.
*/
- private static final int MIN_READY_JOBS_COUNT = 4;
+ static final int MIN_READY_JOBS_COUNT = 4;
/**
* Track Services that have currently active or pending jobs. The index is provided by
* {@link JobStatus#getServiceToken()}
*/
- private final List<JobServiceContext> mActiveServices = new LinkedList<JobServiceContext>();
+ final List<JobServiceContext> mActiveServices = new ArrayList<JobServiceContext>();
/** List of controllers that will notify this service of updates to jobs. */
- private List<StateController> mControllers;
+ List<StateController> mControllers;
/**
* Queue of pending jobs. The JobServiceContext class will receive jobs from this list
* when ready to execute them.
*/
- private final LinkedList<JobStatus> mPendingJobs = new LinkedList<JobStatus>();
+ final ArrayList<JobStatus> mPendingJobs = new ArrayList<JobStatus>();
- private final JobHandler mHandler;
- private final JobSchedulerStub mJobSchedulerStub;
+ final JobHandler mHandler;
+ final JobSchedulerStub mJobSchedulerStub;
+
+ IBatteryStats mBatteryStats;
+
+ /**
+ * Set to true once we are allowed to run third party apps.
+ */
+ boolean mReadyToRock;
+
/**
* Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
* still clean up. On reinstall the package will have a new uid.
@@ -152,7 +162,9 @@
public List<JobInfo> getPendingJobs(int uid) {
ArrayList<JobInfo> outList = new ArrayList<JobInfo>();
synchronized (mJobs) {
- for (JobStatus job : mJobs.getJobs()) {
+ ArraySet<JobStatus> jobs = mJobs.getJobs();
+ for (int i=0; i<jobs.size(); i++) {
+ JobStatus job = jobs.valueAt(i);
if (job.getUid() == uid) {
outList.add(job.getJob());
}
@@ -164,7 +176,8 @@
private void cancelJobsForUser(int userHandle) {
synchronized (mJobs) {
List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
- for (JobStatus toRemove : jobsForUser) {
+ for (int i=0; i<jobsForUser.size(); i++) {
+ JobStatus toRemove = jobsForUser.get(i);
if (DEBUG) {
Slog.d(TAG, "Cancelling: " + toRemove);
}
@@ -183,7 +196,8 @@
// Remove from master list.
synchronized (mJobs) {
List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
- for (JobStatus toRemove : jobsForUid) {
+ for (int i=0; i<jobsForUid.size(); i++) {
+ JobStatus toRemove = jobsForUid.get(i);
if (DEBUG) {
Slog.d(TAG, "Cancelling: " + toRemove);
}
@@ -230,7 +244,7 @@
public JobSchedulerService(Context context) {
super(context);
// Create the controllers.
- mControllers = new LinkedList<StateController>();
+ mControllers = new ArrayList<StateController>();
mControllers.add(ConnectivityController.get(this));
mControllers.add(TimeController.get(this));
mControllers.add(IdleController.get(this));
@@ -238,11 +252,6 @@
mHandler = new JobHandler(context.getMainLooper());
mJobSchedulerStub = new JobSchedulerStub();
- // Create the "runners".
- for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
- mActiveServices.add(
- new JobServiceContext(this, context.getMainLooper()));
- }
mJobs = JobStore.initAndGet(this);
}
@@ -262,6 +271,29 @@
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
+ } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ synchronized (mJobs) {
+ // Let's go!
+ mReadyToRock = true;
+ mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
+ BatteryStats.SERVICE_NAME));
+ // Create the "runners".
+ for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
+ mActiveServices.add(
+ new JobServiceContext(this, mBatteryStats,
+ getContext().getMainLooper()));
+ }
+ // Attach jobs to their controllers.
+ ArraySet<JobStatus> jobs = mJobs.getJobs();
+ for (int i=0; i<jobs.size(); i++) {
+ JobStatus job = jobs.valueAt(i);
+ for (int j=0; j<mControllers.size(); j++) {
+ mControllers.get(i).maybeStartTrackingJob(job);
+ }
+ }
+ // GO GO GO!
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ }
}
}
@@ -272,14 +304,19 @@
*/
private void startTrackingJob(JobStatus jobStatus) {
boolean update;
+ boolean rocking;
synchronized (mJobs) {
update = mJobs.add(jobStatus);
+ rocking = mReadyToRock;
}
- for (StateController controller : mControllers) {
- if (update) {
- controller.maybeStopTrackingJob(jobStatus);
+ if (rocking) {
+ for (int i=0; i<mControllers.size(); i++) {
+ StateController controller = mControllers.get(i);
+ if (update) {
+ controller.maybeStopTrackingJob(jobStatus);
+ }
+ controller.maybeStartTrackingJob(jobStatus);
}
- controller.maybeStartTrackingJob(jobStatus);
}
}
@@ -289,12 +326,15 @@
*/
private boolean stopTrackingJob(JobStatus jobStatus) {
boolean removed;
+ boolean rocking;
synchronized (mJobs) {
// Remove from store as well as controllers.
removed = mJobs.remove(jobStatus);
+ rocking = mReadyToRock;
}
- if (removed) {
- for (StateController controller : mControllers) {
+ if (removed && rocking) {
+ for (int i=0; i<mControllers.size(); i++) {
+ StateController controller = mControllers.get(i);
controller.maybeStopTrackingJob(jobStatus);
}
}
@@ -302,7 +342,8 @@
}
private boolean stopJobOnServiceContextLocked(JobStatus job) {
- for (JobServiceContext jsc : mActiveServices) {
+ for (int i=0; i<mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
final JobStatus executing = jsc.getRunningJob();
if (executing != null && executing.matches(job.getUid(), job.getJobId())) {
jsc.cancelExecutingJob();
@@ -318,7 +359,8 @@
* is pending.
*/
private boolean isCurrentlyActiveLocked(JobStatus job) {
- for (JobServiceContext serviceContext : mActiveServices) {
+ for (int i=0; i<mActiveServices.size(); i++) {
+ JobServiceContext serviceContext = mActiveServices.get(i);
final JobStatus running = serviceContext.getRunningJob();
if (running != null && running.matches(job.getUid(), job.getJobId())) {
return true;
@@ -431,8 +473,13 @@
*/
@Override
public void onControllerStateChanged() {
- // Post a message to to run through the list of jobs and start/stop any that are eligible.
- mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ synchronized (mJobs) {
+ if (mReadyToRock) {
+ // Post a message to to run through the list of jobs and start/stop any that
+ // are eligible.
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ }
+ }
}
@Override
@@ -449,7 +496,8 @@
@Override
public void onJobMapReadFinished(List<JobStatus> jobs) {
synchronized (mJobs) {
- for (JobStatus js : jobs) {
+ for (int i=0; i<jobs.size(); i++) {
+ JobStatus js = jobs.get(i);
if (mJobs.containsJobIdForUid(js.getJobId(), js.getUid())) {
// An app with BOOT_COMPLETED *might* have decided to reschedule their job, in
// the same amount of time it took us to read it from disk. If this is the case
@@ -495,7 +543,9 @@
*/
private void queueReadyJobsForExecutionH() {
synchronized (mJobs) {
- for (JobStatus job : mJobs.getJobs()) {
+ ArraySet<JobStatus> jobs = mJobs.getJobs();
+ for (int i=0; i<jobs.size(); i++) {
+ JobStatus job = jobs.valueAt(i);
if (isReadyToBeExecutedLocked(job)) {
mPendingJobs.add(job);
} else if (isReadyToBeCancelledLocked(job)) {
@@ -520,7 +570,9 @@
int backoffCount = 0;
int connectivityCount = 0;
List<JobStatus> runnableJobs = new ArrayList<JobStatus>();
- for (JobStatus job : mJobs.getJobs()) {
+ ArraySet<JobStatus> jobs = mJobs.getJobs();
+ for (int i=0; i<jobs.size(); i++) {
+ JobStatus job = jobs.valueAt(i);
if (isReadyToBeExecutedLocked(job)) {
if (job.getNumFailures() > 0) {
backoffCount++;
@@ -539,8 +591,8 @@
if (backoffCount > 0 || idleCount >= MIN_IDLE_COUNT ||
connectivityCount >= MIN_CONNECTIVITY_COUNT ||
runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
- for (JobStatus job : runnableJobs) {
- mPendingJobs.add(job);
+ for (int i=0; i<runnableJobs.size(); i++) {
+ mPendingJobs.add(runnableJobs.get(i));
}
}
}
@@ -576,7 +628,8 @@
while (it.hasNext()) {
JobStatus nextPending = it.next();
JobServiceContext availableContext = null;
- for (JobServiceContext jsc : mActiveServices) {
+ for (int i=0; i<mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
final JobStatus running = jsc.getRunningJob();
if (running != null && running.matches(nextPending.getUid(),
nextPending.getJobId())) {
@@ -737,25 +790,28 @@
synchronized (mJobs) {
pw.println("Registered jobs:");
if (mJobs.size() > 0) {
- for (JobStatus job : mJobs.getJobs()) {
+ ArraySet<JobStatus> jobs = mJobs.getJobs();
+ for (int i=0; i<jobs.size(); i++) {
+ JobStatus job = jobs.valueAt(i);
job.dump(pw, " ");
}
} else {
pw.println();
pw.println("No jobs scheduled.");
}
- for (StateController controller : mControllers) {
+ for (int i=0; i<mControllers.size(); i++) {
pw.println();
- controller.dumpControllerState(pw);
+ mControllers.get(i).dumpControllerState(pw);
}
pw.println();
pw.println("Pending");
- for (JobStatus jobStatus : mPendingJobs) {
- pw.println(jobStatus.hashCode());
+ for (int i=0; i<mPendingJobs.size(); i++) {
+ pw.println(mPendingJobs.get(i).hashCode());
}
pw.println();
pw.println("Active jobs:");
- for (JobServiceContext jsc : mActiveServices) {
+ for (int i=0; i<mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
if (jsc.isAvailable()) {
continue;
} else {
@@ -765,6 +821,8 @@
"timeout: " + jsc.getTimeoutElapsed());
}
}
+ pw.println();
+ pw.print("mReadyToRock="); pw.println(mReadyToRock);
}
pw.println();
}
diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java
index 534faba3..eaf5480 100644
--- a/services/core/java/com/android/server/job/JobServiceContext.java
+++ b/services/core/java/com/android/server/job/JobServiceContext.java
@@ -39,6 +39,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.IBatteryStats;
import com.android.server.job.controllers.JobStatus;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -57,8 +58,6 @@
private static final long EXECUTING_TIMESLICE_MILLIS = 60 * 1000;
/** Amount of time the JobScheduler will wait for a response from an app for a message. */
private static final long OP_TIMEOUT_MILLIS = 8 * 1000;
- /** String prefix for all wakelock names. */
- private static final String JS_WAKELOCK_PREFIX = "*job*/";
private static final String[] VERB_STRINGS = {
"VERB_STARTING", "VERB_EXECUTING", "VERB_STOPPING", "VERB_PENDING"
@@ -87,6 +86,7 @@
private final JobCompletedListener mCompletedListener;
/** Used for service binding, etc. */
private final Context mContext;
+ private final IBatteryStats mBatteryStats;
private PowerManager.WakeLock mWakeLock;
// Execution state.
@@ -109,13 +109,15 @@
/** Track when job will timeout. */
private long mTimeoutElapsed;
- JobServiceContext(JobSchedulerService service, Looper looper) {
- this(service.getContext(), service, looper);
+ JobServiceContext(JobSchedulerService service, IBatteryStats batteryStats, Looper looper) {
+ this(service.getContext(), batteryStats, service, looper);
}
@VisibleForTesting
- JobServiceContext(Context context, JobCompletedListener completedListener, Looper looper) {
+ JobServiceContext(Context context, IBatteryStats batteryStats,
+ JobCompletedListener completedListener, Looper looper) {
mContext = context;
+ mBatteryStats = batteryStats;
mCallbackHandler = new JobServiceHandler(looper);
mCompletedListener = completedListener;
mAvailable = true;
@@ -152,6 +154,11 @@
mExecutionStartTimeElapsed = 0L;
return false;
}
+ try {
+ mBatteryStats.noteJobStart(job.getName(), job.getUid());
+ } catch (RemoteException e) {
+ // Whatever.
+ }
mAvailable = false;
return true;
}
@@ -228,8 +235,7 @@
mCallbackHandler.removeMessages(MSG_TIMEOUT);
final PowerManager pm =
(PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
- JS_WAKELOCK_PREFIX + mRunningJob.getServiceComponent().getPackageName());
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mRunningJob.getTag());
mWakeLock.setWorkSource(new WorkSource(mRunningJob.getUid()));
mWakeLock.setReferenceCounted(false);
mWakeLock.acquire();
@@ -483,6 +489,11 @@
removeMessages(MSG_TIMEOUT);
mCompletedListener.onJobCompleted(mRunningJob, reschedule);
synchronized (mLock) {
+ try {
+ mBatteryStats.noteJobFinish(mRunningJob.getName(), mRunningJob.getUid());
+ } catch (RemoteException e) {
+ // Whatever.
+ }
mWakeLock.release();
mContext.unbindService(JobServiceContext.this);
mWakeLock = null;
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 8736980..48312b0 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -136,7 +136,8 @@
* Whether this jobStatus object already exists in the JobStore.
*/
public boolean containsJobIdForUid(int jobId, int uId) {
- for (JobStatus ts : mJobSet) {
+ for (int i=mJobSet.size()-1; i>=0; i--) {
+ JobStatus ts = mJobSet.valueAt(i);
if (ts.getUid() == uId && ts.getJobId() == jobId) {
return true;
}
@@ -267,7 +268,8 @@
List<JobStatus> mStoreCopy = new ArrayList<JobStatus>();
synchronized (JobStore.this) {
// Copy over the jobs so we can release the lock before writing.
- for (JobStatus jobStatus : mJobSet) {
+ for (int i=0; i<mJobSet.size(); i++) {
+ JobStatus jobStatus = mJobSet.valueAt(i);
JobStatus copy = new JobStatus(jobStatus.getJob(), jobStatus.getUid(),
jobStatus.getEarliestRunTime(), jobStatus.getLatestRunTimeElapsed());
mStoreCopy.add(copy);
@@ -290,7 +292,8 @@
out.startTag(null, "job-info");
out.attribute(null, "version", Integer.toString(JOBS_FILE_VERSION));
- for (JobStatus jobStatus : jobList) {
+ for (int i=0; i<jobList.size(); i++) {
+ JobStatus jobStatus = jobList.get(i);
if (DEBUG) {
Slog.d(TAG, "Saving job " + jobStatus.getJobId());
}
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 9ee2869..652d8f8 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -42,6 +42,8 @@
final JobInfo job;
final int uId;
+ final String name;
+ final String tag;
// Constraints.
final AtomicBoolean chargingConstraintSatisfied = new AtomicBoolean();
@@ -72,6 +74,8 @@
private JobStatus(JobInfo job, int uId, int numFailures) {
this.job = job;
this.uId = uId;
+ this.name = job.getService().flattenToShortString();
+ this.tag = "*job*/" + this.name;
this.numFailures = numFailures;
}
@@ -140,6 +144,14 @@
return uId;
}
+ public String getName() {
+ return name;
+ }
+
+ public String getTag() {
+ return tag;
+ }
+
public PersistableBundle getExtras() {
return job.getExtras();
}
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 8222155..b3419c1 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -62,6 +62,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
@@ -70,6 +71,7 @@
import android.telephony.SmsMessage;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
+import android.text.TextUtils;
import android.util.Log;
import android.util.NtpTrustedTime;
@@ -85,6 +87,8 @@
import java.util.Map.Entry;
import java.util.Properties;
+import libcore.io.IoUtils;
+
/**
* A GPS implementation of LocationProvider used by LocationManager.
*
@@ -201,7 +205,9 @@
private static final int AGPS_SETID_TYPE_IMSI = 1;
private static final int AGPS_SETID_TYPE_MSISDN = 2;
- private static final String PROPERTIES_FILE = "/etc/gps.conf";
+ private static final String PROPERTIES_FILE_PREFIX = "/etc/gps";
+ private static final String PROPERTIES_FILE_SUFFIX = ".conf";
+ private static final String DEFAULT_PROPERTIES_FILE = PROPERTIES_FILE_PREFIX + PROPERTIES_FILE_SUFFIX;
private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
@@ -441,6 +447,44 @@
return native_is_supported();
}
+ private boolean loadPropertiesFile(String filename) {
+ mProperties = new Properties();
+ try {
+ File file = new File(filename);
+ FileInputStream stream = null;
+ try {
+ stream = new FileInputStream(file);
+ mProperties.load(stream);
+ } finally {
+ IoUtils.closeQuietly(stream);
+ }
+
+ mSuplServerHost = mProperties.getProperty("SUPL_HOST");
+ String portString = mProperties.getProperty("SUPL_PORT");
+ if (mSuplServerHost != null && portString != null) {
+ try {
+ mSuplServerPort = Integer.parseInt(portString);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
+ }
+ }
+
+ mC2KServerHost = mProperties.getProperty("C2K_HOST");
+ portString = mProperties.getProperty("C2K_PORT");
+ if (mC2KServerHost != null && portString != null) {
+ try {
+ mC2KServerPort = Integer.parseInt(portString);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "unable to parse C2K_PORT: " + portString);
+ }
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Could not open GPS configuration file " + filename);
+ return false;
+ }
+ return true;
+ }
+
public GpsLocationProvider(Context context, ILocationManager ilocationManager,
Looper looper) {
mContext = context;
@@ -469,34 +513,15 @@
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
BatteryStats.SERVICE_NAME));
- mProperties = new Properties();
- try {
- File file = new File(PROPERTIES_FILE);
- FileInputStream stream = new FileInputStream(file);
- mProperties.load(stream);
- stream.close();
+ boolean propertiesLoaded = false;
+ final String gpsHardware = SystemProperties.get("ro.hardware.gps");
+ if (!TextUtils.isEmpty(gpsHardware)) {
+ final String propFilename = PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
+ propertiesLoaded = loadPropertiesFile(propFilename);
+ }
- mSuplServerHost = mProperties.getProperty("SUPL_HOST");
- String portString = mProperties.getProperty("SUPL_PORT");
- if (mSuplServerHost != null && portString != null) {
- try {
- mSuplServerPort = Integer.parseInt(portString);
- } catch (NumberFormatException e) {
- Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
- }
- }
-
- mC2KServerHost = mProperties.getProperty("C2K_HOST");
- portString = mProperties.getProperty("C2K_PORT");
- if (mC2KServerHost != null && portString != null) {
- try {
- mC2KServerPort = Integer.parseInt(portString);
- } catch (NumberFormatException e) {
- Log.e(TAG, "unable to parse C2K_PORT: " + portString);
- }
- }
- } catch (IOException e) {
- Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
+ if (!propertiesLoaded) {
+ loadPropertiesFile(DEFAULT_PROPERTIES_FILE);
}
// construct handler, listen for events
diff --git a/services/core/java/com/android/server/media/MediaRouteProviderProxy.java b/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
deleted file mode 100644
index b31153b..0000000
--- a/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * 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.
- */
-package com.android.server.media;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.media.routeprovider.IRouteConnection;
-import android.media.routeprovider.IRouteProvider;
-import android.media.routeprovider.IRouteProviderCallback;
-import android.media.routeprovider.RouteProviderService;
-import android.media.routeprovider.RouteRequest;
-import android.media.session.RouteEvent;
-import android.media.session.RouteInfo;
-import android.media.session.MediaSession;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.UserHandle;
-import android.util.Log;
-import android.util.Slog;
-
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * System representation and interface to a MediaRouteProvider. This class is
- * not thread safe so all calls should be made on the main thread.
- */
-public class MediaRouteProviderProxy {
- private static final String TAG = "MRPProxy";
- private static final boolean DEBUG = true;
-
- private static final int MAX_RETRIES = 3;
-
- private final Object mLock = new Object();
- private final Context mContext;
- private final String mId;
- private final ComponentName mComponentName;
- private final int mUserId;
- // Interfaces declared in the manifest
- private final ArrayList<String> mInterfaces = new ArrayList<String>();
- private final ArrayList<RouteConnectionRecord> mConnections
- = new ArrayList<RouteConnectionRecord>();
- // The sessions that have a route from this provider selected
- private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>();
- private final Handler mHandler = new Handler();
-
- private Intent mBindIntent;
- private IRouteProvider mBinder;
- private boolean mRunning;
- private boolean mPaused;
- private boolean mInterested;
- private boolean mBound;
- private int mRetryCount;
-
- private RoutesListener mRouteListener;
-
- public MediaRouteProviderProxy(Context context, String id, ComponentName component, int uid,
- ArrayList<String> interfaces) {
- mContext = context;
- mId = id;
- mComponentName = component;
- mUserId = uid;
- if (interfaces != null) {
- mInterfaces.addAll(interfaces);
- }
- mBindIntent = new Intent(RouteProviderService.SERVICE_INTERFACE);
- mBindIntent.setComponent(mComponentName);
- }
-
- public void destroy() {
- stop();
- mSessions.clear();
- updateBinding();
- }
-
- /**
- * Send any cleanup messages and unbind from the media route provider
- */
- public void stop() {
- if (mRunning) {
- mRunning = false;
- mRetryCount = 0;
- updateBinding();
- }
- }
-
- /**
- * Bind to the media route provider and perform any setup needed
- */
- public void start() {
- if (!mRunning) {
- mRunning = true;
- updateBinding();
- }
- }
-
- /**
- * Set whether or not this provider is currently interesting to the system.
- * In the future this may take a list of interfaces instead.
- *
- * @param interested True if we want to connect to this provider
- */
- public void setInterested(boolean interested) {
- mInterested = interested;
- updateBinding();
- }
-
- /**
- * Set a listener to get route updates on.
- *
- * @param listener The listener to receive updates on.
- */
- public void setRoutesListener(RoutesListener listener) {
- mRouteListener = listener;
- }
-
- /**
- * Send a request to the Provider to get all the routes that the session can
- * use.
- *
- * @param record The session to get routes for.
- * @param requestId An id to identify this request.
- */
- public void getRoutes(MediaSessionRecord record, final int requestId) {
- // TODO change routes to have a system global id and maintain a mapping
- // to the original route
- if (mBinder == null) {
- Log.wtf(TAG, "Attempted to call getRoutes without a binder connection");
- return;
- }
- List<RouteRequest> requests = record.getRouteRequests();
- final String sessionId = record.getSessionInfo().getId();
- try {
- mBinder.getAvailableRoutes(requests, new ResultReceiver(mHandler) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode != RouteProviderService.RESULT_SUCCESS) {
- // ignore failures, just means no routes were generated
- return;
- }
- ArrayList<RouteInfo> routes
- = resultData.getParcelableArrayList(RouteProviderService.KEY_ROUTES);
- ArrayList<RouteInfo> sysRoutes = new ArrayList<RouteInfo>();
- for (int i = 0; i < routes.size(); i++) {
- RouteInfo route = routes.get(i);
- RouteInfo.Builder bob = new RouteInfo.Builder(route);
- bob.setProviderId(mId);
- sysRoutes.add(bob.build());
- }
- if (mRouteListener != null) {
- mRouteListener.onRoutesUpdated(sessionId, sysRoutes, requestId);
- }
- }
- });
- } catch (RemoteException e) {
- Log.d(TAG, "Error in getRoutes", e);
- }
- }
-
- /**
- * Try connecting again if we've been disconnected.
- */
- public void rebindIfDisconnected() {
- if (mBinder == null && shouldBind()) {
- unbind();
- bind();
- }
- }
-
- /**
- * Send a request to connect to a route.
- *
- * @param session The session that is trying to connect.
- * @param route The route it is connecting to.
- * @param request The request with the connection parameters.
- * @return true if the request was sent, false otherwise.
- */
- public boolean connectToRoute(MediaSessionRecord session, final RouteInfo route,
- final RouteRequest request) {
- final String sessionId = session.getSessionInfo().getId();
- try {
- mBinder.connect(route, request, new ResultReceiver(mHandler) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- if (resultCode != RouteProviderService.RESULT_SUCCESS) {
- // TODO handle connection failure
- return;
- }
- IBinder binder = resultData.getBinder(RouteProviderService.KEY_CONNECTION);
- IRouteConnection connection = null;
- if (binder != null) {
- connection = IRouteConnection.Stub.asInterface(binder);
- }
-
- if (connection != null) {
- RouteConnectionRecord record = new RouteConnectionRecord(
- connection, mComponentName.getPackageName(), mUserId);
- mConnections.add(record);
- if (mRouteListener != null) {
- mRouteListener.onRouteConnected(sessionId, route, request, record);
- }
- }
- }
- });
- } catch (RemoteException e) {
- Log.e(TAG, "Error connecting to route.", e);
- return false;
- }
- return true;
- }
-
- /**
- * Check if this is the provider you're looking for.
- */
- public boolean hasComponentName(String packageName, String className) {
- return mComponentName.getPackageName().equals(packageName)
- && mComponentName.getClassName().equals(className);
- }
-
- /**
- * Get the unique id for this provider.
- *
- * @return The provider's id.
- */
- public String getId() {
- return mId;
- }
-
- public void addSession(MediaSessionRecord session) {
- mSessions.add(session);
- }
-
- public void removeSession(MediaSessionRecord session) {
- mSessions.remove(session);
- updateBinding();
- }
-
- public int getSessionCount() {
- return mSessions.size();
- }
-
- public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + mId + " " + this);
- String indent = prefix + " ";
-
- pw.println(indent + "component=" + mComponentName.toString());
- pw.println(indent + "user id=" + mUserId);
- pw.println(indent + "interfaces=" + mInterfaces.toString());
- pw.println(indent + "connections=" + mConnections.toString());
- pw.println(indent + "running=" + mRunning);
- pw.println(indent + "interested=" + mInterested);
- pw.println(indent + "bound=" + mBound);
- }
-
- private void updateBinding() {
- if (shouldBind()) {
- bind();
- } else {
- unbind();
- }
- }
-
- // We want to bind as long as we're interested in this provider or there are
- // sessions connected to it.
- private boolean shouldBind() {
- return (mRunning && mInterested) || (!mSessions.isEmpty());
- }
-
- private void bind() {
- if (!mBound) {
- if (DEBUG) {
- Slog.d(TAG, this + ": Binding");
- }
-
- try {
- mBound = mContext.bindServiceAsUser(mBindIntent, mServiceConn,
- Context.BIND_AUTO_CREATE, new UserHandle(mUserId));
- if (!mBound && DEBUG) {
- Slog.d(TAG, this + ": Bind failed");
- }
- } catch (SecurityException ex) {
- if (DEBUG) {
- Slog.d(TAG, this + ": Bind failed", ex);
- }
- }
- }
- }
-
- private void unbind() {
- if (mBound) {
- if (DEBUG) {
- Slog.d(TAG, this + ": Unbinding");
- }
-
- mBound = false;
- mContext.unbindService(mServiceConn);
- }
- }
-
- private RouteConnectionRecord getConnectionLocked(IBinder binder) {
- for (int i = mConnections.size() - 1; i >= 0; i--) {
- RouteConnectionRecord record = mConnections.get(i);
- if (record.isConnection(binder)) {
- return record;
- }
- }
- return null;
- }
-
- private ServiceConnection mServiceConn = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mBinder = IRouteProvider.Stub.asInterface(service);
- if (DEBUG) {
- Slog.d(TAG, "Connected to route provider");
- }
- try {
- mBinder.registerCallback(mCbStub);
- } catch (RemoteException e) {
- Slog.e(TAG, "Error registering callback on route provider. Retry count: "
- + mRetryCount, e);
- if (mRetryCount < MAX_RETRIES) {
- mRetryCount++;
- rebindIfDisconnected();
- }
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mBinder = null;
- if (DEBUG) {
- Slog.d(TAG, "Disconnected from route provider");
- }
- }
-
- };
-
- private IRouteProviderCallback.Stub mCbStub = new IRouteProviderCallback.Stub() {
- @Override
- public void onConnectionStateChanged(IRouteConnection connection, int state)
- throws RemoteException {
- // TODO
- }
-
- @Override
- public void onRouteEvent(RouteEvent event) throws RemoteException {
- synchronized (mLock) {
- RouteConnectionRecord record = getConnectionLocked(event.getConnection());
- Log.d(TAG, "Received route event for record " + record);
- if (record != null) {
- record.sendEvent(event);
- }
- }
- }
-
- @Override
- public void onConnectionTerminated(IRouteConnection connection) throws RemoteException {
- synchronized (mLock) {
- RouteConnectionRecord record = getConnectionLocked(connection.asBinder());
- if (record != null) {
- record.disconnect();
- mConnections.remove(record);
- }
- }
- }
-
- @Override
- public void onRoutesChanged() throws RemoteException {
- // TODO
- }
- };
-
- /**
- * Listener for receiving responses to route requests on the provider.
- */
- public interface RoutesListener {
- /**
- * Called when routes have been returned from a request to getRoutes.
- *
- * @param record The session that the routes were requested for.
- * @param routes The matching routes returned by the provider.
- * @param reqId The request id this is responding to.
- */
- public void onRoutesUpdated(String sessionId, ArrayList<RouteInfo> routes,
- int reqId);
-
- /**
- * Called when a route has successfully connected.
- *
- * @param session The session that was connected.
- * @param route The route it connected to.
- * @param options The options that were used for the connection.
- * @param connection The connection instance that was created.
- */
- public void onRouteConnected(String sessionId, RouteInfo route,
- RouteRequest options, RouteConnectionRecord connection);
- }
-}
diff --git a/services/core/java/com/android/server/media/MediaRouteProviderWatcher.java b/services/core/java/com/android/server/media/MediaRouteProviderWatcher.java
deleted file mode 100644
index 734eab9..0000000
--- a/services/core/java/com/android/server/media/MediaRouteProviderWatcher.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.
- */
-package com.android.server.media;
-
-import android.Manifest;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.media.routeprovider.RouteProviderService;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.UUID;
-
-/**
- * Watches for media route provider services to be installed. Adds a provider to
- * the media session service for each registered service. For now just run all
- * providers. In the future define a policy for when to run providers.
- */
-public class MediaRouteProviderWatcher {
- private static final String TAG = "MRPWatcher";
- private static final boolean DEBUG = true; // Log.isLoggable(TAG,
- // Log.DEBUG);
-
- private final Context mContext;
- private final Callback mCallback;
- private final Handler mHandler;
- private final int mUserId;
- private final PackageManager mPackageManager;
-
- private final ArrayList<MediaRouteProviderProxy> mProviders =
- new ArrayList<MediaRouteProviderProxy>();
- private boolean mRunning;
-
- public MediaRouteProviderWatcher(Context context, Callback callback, Handler handler,
- int userId) {
- mContext = context;
- mCallback = callback;
- mHandler = handler;
- mUserId = userId;
- mPackageManager = context.getPackageManager();
- }
-
- public void dump(PrintWriter pw, String prefix) {
- pw.println(prefix + " mUserId=" + mUserId);
- pw.println(prefix + " mRunning=" + mRunning);
- pw.println(prefix + " mProviders.size()=" + mProviders.size());
- }
-
- public void start() {
- if (!mRunning) {
- mRunning = true;
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
- filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
- filter.addDataScheme("package");
- mContext.registerReceiverAsUser(mScanPackagesReceiver,
- new UserHandle(mUserId), filter, null, mHandler);
-
- // Scan packages.
- // Also has the side-effect of restarting providers if needed.
- mHandler.post(mScanPackagesRunnable);
- }
- }
-
- // Stop discovering providers and routes. Providers that still have an
- // active session connected to them will not unbind.
- public void stop() {
- if (mRunning) {
- mRunning = false;
-
- mContext.unregisterReceiver(mScanPackagesReceiver);
- mHandler.removeCallbacks(mScanPackagesRunnable);
-
- // Stop all inactive providers.
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- mProviders.get(i).stop();
- }
- }
- }
-
- // Clean up the providers forcibly unbinding if necessary
- public void destroy() {
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- mProviders.get(i).destroy();
- mProviders.remove(i);
- }
- }
-
- public ArrayList<MediaRouteProviderProxy> getProviders() {
- return mProviders;
- }
-
- public MediaRouteProviderProxy getProvider(String id) {
- int providerIndex = findProvider(id);
- if (providerIndex != -1) {
- return mProviders.get(providerIndex);
- }
- return null;
- }
-
- private void scanPackages() {
- if (!mRunning) {
- return;
- }
-
- // Add providers for all new services.
- // Reorder the list so that providers left at the end will be the ones
- // to remove.
- int targetIndex = 0;
- Intent intent = new Intent(RouteProviderService.SERVICE_INTERFACE);
- for (ResolveInfo resolveInfo : mPackageManager.queryIntentServicesAsUser(
- intent, 0, mUserId)) {
- ServiceInfo serviceInfo = resolveInfo.serviceInfo;
- if (DEBUG) {
- Slog.d(TAG, "Checking service " + (serviceInfo == null ? null : serviceInfo.name));
- }
- if (serviceInfo != null && verifyServiceTrusted(serviceInfo)) {
- int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name);
- if (sourceIndex < 0) {
- // TODO get declared interfaces from manifest
- if (DEBUG) {
- Slog.d(TAG, "Creating new provider proxy for service");
- }
- MediaRouteProviderProxy provider =
- new MediaRouteProviderProxy(mContext, UUID.randomUUID().toString(),
- new ComponentName(serviceInfo.packageName, serviceInfo.name),
- mUserId, null);
- provider.start();
- mProviders.add(targetIndex++, provider);
- mCallback.addProvider(provider);
- } else if (sourceIndex >= targetIndex) {
- MediaRouteProviderProxy provider = mProviders.get(sourceIndex);
- provider.start(); // restart the provider if needed
- provider.rebindIfDisconnected();
- Collections.swap(mProviders, sourceIndex, targetIndex++);
- }
- }
- }
-
- // Remove providers for missing services.
- if (targetIndex < mProviders.size()) {
- for (int i = mProviders.size() - 1; i >= targetIndex; i--) {
- MediaRouteProviderProxy provider = mProviders.get(i);
- mCallback.removeProvider(provider);
- mProviders.remove(provider);
- provider.stop();
- }
- }
- }
-
- private boolean verifyServiceTrusted(ServiceInfo serviceInfo) {
- if (serviceInfo.permission == null || !serviceInfo.permission.equals(
- Manifest.permission.BIND_ROUTE_PROVIDER)) {
- // If the service does not require this permission then any app
- // could potentially bind to it and mess with their routes. So we
- // only want to trust providers that require the
- // correct permissions.
- Slog.w(TAG, "Ignoring route provider service because it did not "
- + "require the BIND_ROUTE_PROVIDER permission in its manifest: "
- + serviceInfo.packageName + "/" + serviceInfo.name);
- return false;
- }
- // Looks good.
- return true;
- }
-
- private int findProvider(String id) {
- int count = mProviders.size();
- for (int i = 0; i < count; i++) {
- MediaRouteProviderProxy provider = mProviders.get(i);
- if (TextUtils.equals(id, provider.getId())) {
- return i;
- }
- }
- return -1;
- }
-
- private int findProvider(String packageName, String className) {
- int count = mProviders.size();
- for (int i = 0; i < count; i++) {
- MediaRouteProviderProxy provider = mProviders.get(i);
- if (provider.hasComponentName(packageName, className)) {
- return i;
- }
- }
- return -1;
- }
-
- private final BroadcastReceiver mScanPackagesReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (DEBUG) {
- Slog.d(TAG, "Received package manager broadcast: " + intent);
- }
- scanPackages();
- }
- };
-
- private final Runnable mScanPackagesRunnable = new Runnable() {
- @Override
- public void run() {
- scanPackages();
- }
- };
-
- public interface Callback {
- void addProvider(MediaRouteProviderProxy provider);
-
- void removeProvider(MediaRouteProviderProxy provider);
- }
-}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 0fbcd7e..ede3dab 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -19,19 +19,16 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.media.routeprovider.RouteRequest;
+import android.media.routing.IMediaRouter;
+import android.media.routing.IMediaRouterDelegate;
+import android.media.routing.IMediaRouterStateCallback;
import android.media.session.ISessionController;
import android.media.session.ISessionControllerCallback;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
import android.media.session.MediaController;
-import android.media.session.RouteCommand;
-import android.media.session.RouteInfo;
-import android.media.session.RouteOptions;
-import android.media.session.RouteEvent;
import android.media.session.MediaSession;
import android.media.session.MediaSessionInfo;
-import android.media.session.RouteInterface;
import android.media.session.PlaybackState;
import android.media.session.ParcelableVolumeInfo;
import android.media.AudioManager;
@@ -94,14 +91,9 @@
private final Object mLock = new Object();
private final ArrayList<ISessionControllerCallback> mControllerCallbacks =
new ArrayList<ISessionControllerCallback>();
- private final ArrayList<RouteRequest> mRequests = new ArrayList<RouteRequest>();
- private RouteInfo mRoute;
- private RouteOptions mRequest;
- private RouteConnectionRecord mConnection;
- // TODO define a RouteState class with relevant info
- private int mRouteState;
private long mFlags;
+ private IMediaRouter mMediaRouter;
private ComponentName mMediaButtonReceiver;
// TransportPerformer fields
@@ -160,24 +152,6 @@
}
/**
- * Get the set of route requests this session is interested in.
- *
- * @return The list of RouteRequests
- */
- public List<RouteRequest> getRouteRequests() {
- return mRequests;
- }
-
- /**
- * Get the route this session is currently on.
- *
- * @return The route the session is on.
- */
- public RouteInfo getRoute() {
- return mRoute;
- }
-
- /**
* Get the info for this session.
*
* @return Info that identifies this session.
@@ -229,74 +203,32 @@
}
/**
- * Set the selected route. This does not connect to the route, just notifies
- * the app that a new route has been selected.
+ * Send a volume adjustment to the session owner. Direction must be one of
+ * {@link AudioManager#ADJUST_LOWER}, {@link AudioManager#ADJUST_RAISE},
+ * {@link AudioManager#ADJUST_SAME}.
*
- * @param route The route that was selected.
+ * @param direction The direction to adjust volume in.
*/
- public void selectRoute(RouteInfo route) {
- synchronized (mLock) {
- if (route != mRoute) {
- disconnect(MediaSession.DISCONNECT_REASON_ROUTE_CHANGED);
- }
- mRoute = route;
- }
- mSessionCb.sendRouteChange(route);
- }
-
- /**
- * Update the state of the route this session is using and notify the
- * session.
- *
- * @param state The new state of the route.
- */
- public void setRouteState(int state) {
- mSessionCb.sendRouteStateChange(state);
- }
-
- /**
- * Send an event to this session from the route it is using.
- *
- * @param event The event to send.
- */
- public void sendRouteEvent(RouteEvent event) {
- mSessionCb.sendRouteEvent(event);
- }
-
- /**
- * Send a volume adjustment to the session owner.
- *
- * @param delta The amount to adjust the volume by.
- */
- public void adjustVolumeBy(int delta, int flags) {
+ public void adjustVolume(int direction, int flags) {
if (isPlaybackActive(false)) {
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}
+ if (direction > 1) {
+ direction = 1;
+ } else if (direction < -1) {
+ direction = -1;
+ }
if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
- if (delta == 0) {
- mAudioManager.adjustStreamVolume(mAudioStream, delta, flags);
- } else {
- int direction = 0;
- int steps = delta;
- if (delta > 0) {
- direction = 1;
- } else if (delta < 0) {
- direction = -1;
- steps = -delta;
- }
- for (int i = 0; i < steps; i++) {
- mAudioManager.adjustStreamVolume(mAudioStream, direction, flags);
- }
- }
+ mAudioManager.adjustStreamVolume(mAudioStream, direction, flags);
} else {
if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
// Nothing to do, the volume cannot be changed
return;
}
- mSessionCb.adjustVolumeBy(delta);
+ mSessionCb.adjustVolume(direction);
int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
- mOptimisticVolume = volumeBefore + delta;
+ mOptimisticVolume = volumeBefore + direction;
mOptimisticVolume = Math.max(0, Math.min(mOptimisticVolume, mMaxVolume));
mHandler.removeCallbacks(mClearOptimisticVolumeRunnable);
mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT);
@@ -338,40 +270,6 @@
}
/**
- * Set the connection to use for the selected route and notify the app it is
- * now connected.
- *
- * @param route The route the connection is to.
- * @param request The request that was used to connect.
- * @param connection The connection to the route.
- * @return True if this connection is still valid, false if it is stale.
- */
- public boolean setRouteConnected(RouteInfo route, RouteOptions request,
- RouteConnectionRecord connection) {
- synchronized (mLock) {
- if (mDestroyed) {
- Log.i(TAG, "setRouteConnected: session has been destroyed");
- connection.disconnect();
- return false;
- }
- if (mRoute == null || !TextUtils.equals(route.getId(), mRoute.getId())) {
- Log.w(TAG, "setRouteConnected: connected route is stale");
- connection.disconnect();
- return false;
- }
- if (request != mRequest) {
- Log.w(TAG, "setRouteConnected: connection request is stale");
- connection.disconnect();
- return false;
- }
- mConnection = connection;
- mConnection.setListener(mConnectionListener);
- mSessionCb.sendRouteConnected();
- }
- return true;
- }
-
- /**
* Check if this session has been set to active by the app.
*
* @return True if the session is active, false otherwise.
@@ -460,30 +358,6 @@
return mOptimisticVolume;
}
- /**
- * @return True if this session is currently connected to a route.
- */
- public boolean isConnected() {
- return mConnection != null;
- }
-
- public void disconnect(int reason) {
- synchronized (mLock) {
- if (!mDestroyed) {
- disconnectLocked(reason);
- }
- }
- }
-
- private void disconnectLocked(int reason) {
- if (mConnection != null) {
- mConnection.setListener(null);
- mConnection.disconnect();
- mConnection = null;
- pushDisconnected(reason);
- }
- }
-
public boolean isTransportControlEnabled() {
return hasFlag(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
}
@@ -502,11 +376,6 @@
if (mDestroyed) {
return;
}
- if (isConnected()) {
- disconnectLocked(MediaSession.DISCONNECT_REASON_SESSION_DESTROYED);
- }
- mRoute = null;
- mRequest = null;
mDestroyed = true;
}
}
@@ -532,15 +401,6 @@
pw.println(indent + "controllers: " + mControllerCallbacks.size());
pw.println(indent + "state=" + (mPlaybackState == null ? null : mPlaybackState.toString()));
pw.println(indent + "metadata:" + getShortMetadataString());
- pw.println(indent + "route requests {");
- int size = mRequests.size();
- for (int i = 0; i < size; i++) {
- pw.println(indent + " " + mRequests.get(i).toString());
- }
- pw.println(indent + "}");
- pw.println(indent + "route=" + (mRoute == null ? null : mRoute.toString()));
- pw.println(indent + "connection=" + (mConnection == null ? null : mConnection.toString()));
- pw.println(indent + "params=" + (mRequest == null ? null : mRequest.toString()));
}
private String getShortMetadataString() {
@@ -550,12 +410,6 @@
return "size=" + fields + ", title=" + title;
}
- private void pushDisconnected(int reason) {
- synchronized (mLock) {
- mSessionCb.sendRouteDisconnected(reason);
- }
- }
-
private void pushPlaybackStateUpdate() {
synchronized (mLock) {
if (mDestroyed) {
@@ -613,25 +467,6 @@
}
}
- private void pushRouteUpdate() {
- synchronized (mLock) {
- if (mDestroyed) {
- return;
- }
- for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
- ISessionControllerCallback cb = mControllerCallbacks.get(i);
- try {
- cb.onRouteChanged(mRoute);
- } catch (DeadObjectException e) {
- Log.w(TAG, "Removing dead callback in pushRouteUpdate.", e);
- mControllerCallbacks.remove(i);
- } catch (RemoteException e) {
- Log.w(TAG, "unexpected exception in pushRouteUpdate.", e);
- }
- }
- }
- }
-
private void pushEvent(String event, Bundle data) {
synchronized (mLock) {
if (mDestroyed) {
@@ -651,25 +486,6 @@
}
}
- private void pushRouteCommand(RouteCommand command, ResultReceiver cb) {
- synchronized (mLock) {
- if (mDestroyed) {
- return;
- }
- if (mRoute == null || !TextUtils.equals(command.getRouteInfo(), mRoute.getId())) {
- if (cb != null) {
- cb.send(RouteInterface.RESULT_ROUTE_IS_STALE, null);
- return;
- }
- }
- if (mConnection != null) {
- mConnection.sendCommand(command, cb);
- } else if (cb != null) {
- cb.send(RouteInterface.RESULT_NOT_CONNECTED, null);
- }
- }
- }
-
private PlaybackState getStateWithUpdatedPosition() {
PlaybackState state = mPlaybackState;
long duration = -1;
@@ -682,16 +498,19 @@
|| state.getState() == PlaybackState.STATE_FAST_FORWARDING
|| state.getState() == PlaybackState.STATE_REWINDING) {
long updateTime = state.getLastPositionUpdateTime();
+ long currentTime = SystemClock.elapsedRealtime();
if (updateTime > 0) {
- long position = (long) (state.getPlaybackRate()
- * (SystemClock.elapsedRealtime() - updateTime)) + state.getPosition();
+ long position = (long) (state.getPlaybackSpeed()
+ * (currentTime - updateTime)) + state.getPosition();
if (duration >= 0 && position > duration) {
position = duration;
} else if (position < 0) {
position = 0;
}
- result = new PlaybackState(state);
- result.setState(state.getState(), position, state.getPlaybackRate());
+ PlaybackState.Builder builder = new PlaybackState.Builder(state);
+ builder.setState(state.getState(), position, state.getPlaybackSpeed(),
+ currentTime);
+ result = builder.build();
}
}
}
@@ -708,21 +527,6 @@
return -1;
}
- private final RouteConnectionRecord.Listener mConnectionListener
- = new RouteConnectionRecord.Listener() {
- @Override
- public void onEvent(RouteEvent event) {
- RouteEvent eventForSession = new RouteEvent(null, event.getIface(),
- event.getEvent(), event.getExtras());
- mSessionCb.sendRouteEvent(eventForSession);
- }
-
- @Override
- public void disconnect() {
- MediaSessionRecord.this.disconnect(MediaSession.DISCONNECT_REASON_PROVIDER_DISCONNECTED);
- }
- };
-
private final Runnable mClearOptimisticVolumeRunnable = new Runnable() {
@Override
public void run() {
@@ -769,6 +573,12 @@
}
@Override
+ public void setMediaRouter(IMediaRouter router) {
+ mMediaRouter = router;
+ mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE);
+ }
+
+ @Override
public void setMediaButtonReceiver(ComponentName mbr) {
mMediaButtonReceiver = mbr;
}
@@ -797,46 +607,6 @@
}
@Override
- public void sendRouteCommand(RouteCommand command, ResultReceiver cb) {
- mHandler.post(MessageHandler.MSG_SEND_COMMAND,
- new Pair<RouteCommand, ResultReceiver>(command, cb));
- }
-
- @Override
- public boolean setRoute(RouteInfo route) throws RemoteException {
- // TODO decide if allowed to set route and if the route exists
- return false;
- }
-
- @Override
- public void connectToRoute(RouteInfo route, RouteOptions request)
- throws RemoteException {
- if (mRoute == null || !TextUtils.equals(route.getId(), mRoute.getId())) {
- throw new RemoteException("RouteInfo does not match current route");
- }
- mService.connectToRoute(MediaSessionRecord.this, route, request);
- mRequest = request;
- }
-
- @Override
- public void disconnectFromRoute(RouteInfo route) {
- if (route != null && mRoute != null
- && TextUtils.equals(route.getId(), mRoute.getId())) {
- disconnect(MediaSession.DISCONNECT_REASON_SESSION_DISCONNECTED);
- }
- }
-
- @Override
- public void setRouteOptions(List<RouteOptions> options) throws RemoteException {
- mRequests.clear();
- for (int i = options.size() - 1; i >= 0; i--) {
- RouteRequest request = new RouteRequest(mSessionInfo, options.get(i),
- false);
- mRequests.add(request);
- }
- }
-
- @Override
public void setCurrentVolume(int volume) {
mCurrentVolume = volume;
mHandler.post(MessageHandler.MSG_UPDATE_VOLUME);
@@ -903,46 +673,6 @@
}
}
- public void sendRouteChange(RouteInfo route) {
- try {
- mCb.onRequestRouteChange(route);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote failure in sendRouteChange.", e);
- }
- }
-
- public void sendRouteStateChange(int state) {
- try {
- mCb.onRouteStateChange(state);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote failure in sendRouteStateChange.", e);
- }
- }
-
- public void sendRouteEvent(RouteEvent event) {
- try {
- mCb.onRouteEvent(event);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote failure in sendRouteEvent.", e);
- }
- }
-
- public void sendRouteConnected() {
- try {
- mCb.onRouteConnected(mRoute, mRequest);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote failure in sendRouteStateChange.", e);
- }
- }
-
- public void sendRouteDisconnected(int reason) {
- try {
- mCb.onRouteDisconnected(mRoute, reason);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote failure in sendRouteDisconnected");
- }
- }
-
public void play() {
try {
mCb.onPlay();
@@ -1015,11 +745,11 @@
}
}
- public void adjustVolumeBy(int delta) {
+ public void adjustVolume(int direction) {
try {
- mCb.onAdjustVolumeBy(delta);
+ mCb.onAdjustVolume(direction);
} catch (RemoteException e) {
- Slog.e(TAG, "Remote failure in adjustVolumeBy.", e);
+ Slog.e(TAG, "Remote failure in adjustVolume.", e);
}
}
@@ -1027,7 +757,7 @@
try {
mCb.onSetVolumeTo(value);
} catch (RemoteException e) {
- Slog.e(TAG, "Remote failure in adjustVolumeBy.", e);
+ Slog.e(TAG, "Remote failure in setVolumeTo.", e);
}
}
}
@@ -1101,10 +831,10 @@
}
@Override
- public void adjustVolumeBy(int delta, int flags) {
+ public void adjustVolume(int direction, int flags) {
final long token = Binder.clearCallingIdentity();
try {
- MediaSessionRecord.this.adjustVolumeBy(delta, flags);
+ MediaSessionRecord.this.adjustVolume(direction, flags);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1187,20 +917,19 @@
}
@Override
- public void showRoutePicker() {
- mService.showRoutePickerForSession(MediaSessionRecord.this);
+ public IMediaRouterDelegate createMediaRouterDelegate(
+ IMediaRouterStateCallback callback) {
+ // todo
+ return null;
}
}
private class MessageHandler extends Handler {
private static final int MSG_UPDATE_METADATA = 1;
private static final int MSG_UPDATE_PLAYBACK_STATE = 2;
- private static final int MSG_UPDATE_ROUTE = 3;
- private static final int MSG_SEND_EVENT = 4;
- private static final int MSG_UPDATE_ROUTE_FILTERS = 5;
- private static final int MSG_SEND_COMMAND = 6;
- private static final int MSG_UPDATE_SESSION_STATE = 7;
- private static final int MSG_UPDATE_VOLUME = 8;
+ private static final int MSG_SEND_EVENT = 3;
+ private static final int MSG_UPDATE_SESSION_STATE = 4;
+ private static final int MSG_UPDATE_VOLUME = 5;
public MessageHandler(Looper looper) {
super(looper);
@@ -1214,17 +943,9 @@
case MSG_UPDATE_PLAYBACK_STATE:
pushPlaybackStateUpdate();
break;
- case MSG_UPDATE_ROUTE:
- pushRouteUpdate();
- break;
case MSG_SEND_EVENT:
pushEvent((String) msg.obj, msg.getData());
break;
- case MSG_SEND_COMMAND:
- Pair<RouteCommand, ResultReceiver> cmd =
- (Pair<RouteCommand, ResultReceiver>) msg.obj;
- pushRouteCommand(cmd.first, cmd.second);
- break;
case MSG_UPDATE_SESSION_STATE:
// TODO add session state
break;
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 310f3e9..a2dd15e 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -30,14 +30,11 @@
import android.media.AudioManager;
import android.media.IAudioService;
import android.media.IRemoteVolumeController;
-import android.media.routeprovider.RouteRequest;
import android.media.session.IActiveSessionsListener;
import android.media.session.ISession;
import android.media.session.ISessionCallback;
import android.media.session.ISessionManager;
import android.media.session.MediaSession;
-import android.media.session.RouteInfo;
-import android.media.session.RouteOptions;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -74,15 +71,12 @@
private static final int WAKELOCK_TIMEOUT = 5000;
private final SessionManagerImpl mSessionManagerImpl;
- // private final MediaRouteProviderWatcher mRouteProviderWatcher;
private final MediaSessionStack mPriorityStack;
private final ArrayList<MediaSessionRecord> mAllSessions = new ArrayList<MediaSessionRecord>();
private final SparseArray<UserRecord> mUserRecords = new SparseArray<UserRecord>();
private final ArrayList<SessionsListenerRecord> mSessionsListeners
= new ArrayList<SessionsListenerRecord>();
- // private final ArrayList<MediaRouteProviderProxy> mProviders
- // = new ArrayList<MediaRouteProviderProxy>();
private final Object mLock = new Object();
private final MessageHandler mHandler = new MessageHandler();
private final PowerManager.WakeLock mMediaEventWakeLock;
@@ -94,10 +88,6 @@
private MediaSessionRecord mPrioritySession;
private int mCurrentUserId = -1;
- // Used to keep track of the current request to show routes for a specific
- // session so we drop late callbacks properly.
- private int mShowRoutesRequestId = 0;
-
// Used to notify system UI when remote volume was changed. TODO find a
// better way to handle this.
private IRemoteVolumeController mRvc;
@@ -126,69 +116,6 @@
return IAudioService.Stub.asInterface(b);
}
- /**
- * Should trigger showing the Media route picker dialog. Right now it just
- * kicks off a query to all the providers to get routes.
- *
- * @param record The session to show the picker for.
- */
- public void showRoutePickerForSession(MediaSessionRecord record) {
- // TODO for now just toggle the route to test (we will only have one
- // match for now)
- synchronized (mLock) {
- if (!mAllSessions.contains(record)) {
- Log.d(TAG, "Unknown session tried to show route picker. Ignoring.");
- return;
- }
- RouteInfo current = record.getRoute();
- UserRecord user = mUserRecords.get(record.getUserId());
- if (current != null) {
- // For now send null to mean the local route
- MediaRouteProviderProxy proxy = user.getProviderLocked(current.getProvider());
- if (proxy != null) {
- proxy.removeSession(record);
- }
- record.selectRoute(null);
- return;
- }
- ArrayList<MediaRouteProviderProxy> providers = user.getProvidersLocked();
- mShowRoutesRequestId++;
- for (int i = providers.size() - 1; i >= 0; i--) {
- MediaRouteProviderProxy provider = providers.get(i);
- provider.getRoutes(record, mShowRoutesRequestId);
- }
- }
- }
-
- /**
- * Connect a session to the given route.
- *
- * @param session The session to connect.
- * @param route The route to connect to.
- * @param options The options to use for the connection.
- */
- public void connectToRoute(MediaSessionRecord session, RouteInfo route,
- RouteOptions options) {
- synchronized (mLock) {
- if (!mAllSessions.contains(session)) {
- Log.d(TAG, "Unknown session attempting to connect to route. Ignoring");
- return;
- }
- UserRecord user = mUserRecords.get(session.getUserId());
- if (user == null) {
- Log.wtf(TAG, "connectToRoute: User " + session.getUserId() + " does not exist.");
- return;
- }
- MediaRouteProviderProxy proxy = user.getProviderLocked(route.getProvider());
- if (proxy == null) {
- Log.w(TAG, "Provider for route " + route.getName() + " does not exist.");
- return;
- }
- RouteRequest request = new RouteRequest(session.getSessionInfo(), options, true);
- proxy.connectToRoute(session, route, request);
- }
- }
-
public void updateSession(MediaSessionRecord record) {
synchronized (mLock) {
if (!mAllSessions.contains(record)) {
@@ -552,110 +479,49 @@
}
}
- private MediaRouteProviderProxy.RoutesListener mRoutesCallback
- = new MediaRouteProviderProxy.RoutesListener() {
- @Override
- public void onRoutesUpdated(String sessionId, ArrayList<RouteInfo> routes,
- int reqId) {
- // TODO for now select the first route to test, eventually add the
- // new routes to the dialog if it is still open
- synchronized (mLock) {
- int index = findIndexOfSessionForIdLocked(sessionId);
- if (index != -1 && routes != null && routes.size() > 0) {
- MediaSessionRecord record = mAllSessions.get(index);
- RouteInfo route = routes.get(0);
- record.selectRoute(route);
- UserRecord user = mUserRecords.get(record.getUserId());
- MediaRouteProviderProxy provider = user.getProviderLocked(route.getProvider());
- provider.addSession(record);
- }
- }
- }
-
- @Override
- public void onRouteConnected(String sessionId, RouteInfo route,
- RouteRequest options, RouteConnectionRecord connection) {
- synchronized (mLock) {
- int index = findIndexOfSessionForIdLocked(sessionId);
- if (index != -1) {
- MediaSessionRecord session = mAllSessions.get(index);
- session.setRouteConnected(route, options.getConnectionOptions(), connection);
- }
- }
- }
- };
-
/**
* Information about a particular user. The contents of this object is
* guarded by mLock.
*/
final class UserRecord {
private final int mUserId;
- private final MediaRouteProviderWatcher mRouteProviderWatcher;
- private final ArrayList<MediaRouteProviderProxy> mProviders
- = new ArrayList<MediaRouteProviderProxy>();
private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>();
public UserRecord(Context context, int userId) {
mUserId = userId;
- mRouteProviderWatcher = new MediaRouteProviderWatcher(context,
- mProviderWatcherCallback, mHandler, userId);
}
public void startLocked() {
- mRouteProviderWatcher.start();
+ // nothing for now
}
public void stopLocked() {
- mRouteProviderWatcher.stop();
- updateInterestLocked();
+ // nothing for now
}
public void destroyLocked() {
for (int i = mSessions.size() - 1; i >= 0; i--) {
MediaSessionRecord session = mSessions.get(i);
MediaSessionService.this.destroySessionLocked(session);
- if (session.isConnected()) {
- session.disconnect(MediaSession.DISCONNECT_REASON_USER_STOPPING);
- }
}
}
- public ArrayList<MediaRouteProviderProxy> getProvidersLocked() {
- return mProviders;
- }
-
public ArrayList<MediaSessionRecord> getSessionsLocked() {
return mSessions;
}
public void addSessionLocked(MediaSessionRecord session) {
mSessions.add(session);
- updateInterestLocked();
}
public void removeSessionLocked(MediaSessionRecord session) {
mSessions.remove(session);
- RouteInfo route = session.getRoute();
- if (route != null) {
- MediaRouteProviderProxy provider = getProviderLocked(route.getProvider());
- if (provider != null) {
- provider.removeSession(session);
- }
- }
- updateInterestLocked();
}
public void dumpLocked(PrintWriter pw, String prefix) {
pw.println(prefix + "Record for user " + mUserId);
String indent = prefix + " ";
- int size = mProviders.size();
- pw.println(indent + size + " Providers:");
- for (int i = 0; i < size; i++) {
- mProviders.get(i).dump(pw, indent);
- }
- pw.println();
- size = mSessions.size();
+ int size = mSessions.size();
pw.println(indent + size + " Sessions:");
for (int i = 0; i < size; i++) {
// Just print the session info, the full session dump will
@@ -663,48 +529,6 @@
pw.println(indent + mSessions.get(i).getSessionInfo());
}
}
-
- public void updateInterestLocked() {
- // TODO go through the sessions and build up the set of interfaces
- // we're interested in. Update the provider watcher.
- // For now, just express interest in all providers for the current
- // user
- boolean interested = mUserId == mCurrentUserId;
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- mProviders.get(i).setInterested(interested);
- }
- }
-
- private MediaRouteProviderProxy getProviderLocked(String providerId) {
- for (int i = mProviders.size() - 1; i >= 0; i--) {
- MediaRouteProviderProxy provider = mProviders.get(i);
- if (TextUtils.equals(providerId, provider.getId())) {
- return provider;
- }
- }
- return null;
- }
-
- private MediaRouteProviderWatcher.Callback mProviderWatcherCallback
- = new MediaRouteProviderWatcher.Callback() {
- @Override
- public void removeProvider(MediaRouteProviderProxy provider) {
- synchronized (mLock) {
- mProviders.remove(provider);
- provider.setRoutesListener(null);
- provider.setInterested(false);
- }
- }
-
- @Override
- public void addProvider(MediaRouteProviderProxy provider) {
- synchronized (mLock) {
- mProviders.add(provider);
- provider.setRoutesListener(mRoutesCallback);
- provider.setInterested(true);
- }
- }
- };
}
final class SessionsListenerRecord implements IBinder.DeathRecipient {
@@ -857,7 +681,7 @@
}
@Override
- public void dispatchAdjustVolumeBy(int suggestedStream, int delta, int flags)
+ public void dispatchAdjustVolume(int suggestedStream, int delta, int flags)
throws RemoteException {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -866,7 +690,7 @@
synchronized (mLock) {
MediaSessionRecord session = mPriorityStack
.getDefaultVolumeSession(mCurrentUserId);
- dispatchAdjustVolumeByLocked(suggestedStream, delta, flags, session);
+ dispatchAdjustVolumeLocked(suggestedStream, delta, flags, session);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -940,11 +764,11 @@
return resolvedUserId;
}
- private void dispatchAdjustVolumeByLocked(int suggestedStream, int delta, int flags,
+ private void dispatchAdjustVolumeLocked(int suggestedStream, int direction, int flags,
MediaSessionRecord session) {
if (DEBUG) {
String sessionInfo = session == null ? null : session.getSessionInfo().toString();
- Log.d(TAG, "Adjusting session " + sessionInfo + " by " + delta + ". flags=" + flags
+ Log.d(TAG, "Adjusting session " + sessionInfo + " by " + direction + ". flags=" + flags
+ ", suggestedStream=" + suggestedStream);
}
@@ -956,28 +780,13 @@
}
}
try {
- if (delta == 0) {
- mAudioService.adjustSuggestedStreamVolume(delta, suggestedStream, flags,
- getContext().getOpPackageName());
- } else {
- int direction = 0;
- int steps = delta;
- if (delta > 0) {
- direction = 1;
- } else if (delta < 0) {
- direction = -1;
- steps = -delta;
- }
- for (int i = 0; i < steps; i++) {
- mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
- flags, getContext().getOpPackageName());
- }
- }
+ mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream, flags,
+ getContext().getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error adjusting default volume.", e);
}
} else {
- session.adjustVolumeBy(delta, flags);
+ session.adjustVolume(direction, flags);
if (session.getPlaybackType() == MediaSession.PLAYBACK_TYPE_REMOTE
&& mRvc != null) {
try {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index e26a2eb..3d1ecb3 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -25,7 +25,7 @@
/**
* Keeps track of media sessions and their priority for notifications, media
- * button routing, etc.
+ * button dispatch, etc.
*/
public class MediaSessionStack {
/**
@@ -277,8 +277,8 @@
lastActiveIndex++;
lastPublishedIndex++;
} else if (session.isPlaybackActive(true)) {
- // TODO replace getRoute() == null with real local route check
- if(session.getRoute() == null) {
+ // TODO this with real local route check
+ if (true) {
// Active local sessions get top priority
result.add(lastLocalIndex, session);
lastLocalIndex++;
diff --git a/services/core/java/com/android/server/media/RouteConnectionRecord.java b/services/core/java/com/android/server/media/RouteConnectionRecord.java
deleted file mode 100644
index 90ddf29..0000000
--- a/services/core/java/com/android/server/media/RouteConnectionRecord.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.
- */
-package com.android.server.media;
-
-import android.media.routeprovider.IRouteConnection;
-import android.media.session.RouteCommand;
-import android.media.session.RouteEvent;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.util.Log;
-
-/**
- * A connection between a Session and a Route.
- */
-public class RouteConnectionRecord {
- private static final String TAG = "RouteConnRecord";
- private final IRouteConnection mBinder;
- private final String mPackageName;
- private final int mUid;
- private Listener mListener;
-
- public RouteConnectionRecord(IRouteConnection binder, String packageName, int uid) {
- mBinder = binder;
- mPackageName = packageName;
- mUid = uid;
- }
-
- /**
- * Add a listener to get route events on.
- *
- * @param listener The listener to get events on.
- */
- public void setListener(Listener listener) {
- mListener = listener;
- }
-
- /**
- * Check if this connection matches the token given.
- *
- * @param binder The token to check
- * @return True if this is the connection you're looking for, false
- * otherwise.
- */
- public boolean isConnection(IBinder binder) {
- return binder != null && binder.equals(mBinder.asBinder());
- }
-
- /**
- * Send an event from this connection.
- *
- * @param event The event to send.
- */
- public void sendEvent(RouteEvent event) {
- if (mListener != null) {
- mListener.onEvent(event);
- }
- }
-
- /**
- * Send a command to this connection.
- *
- * @param command The command to send.
- * @param cb The receiver to get a result on.
- */
- public void sendCommand(RouteCommand command, ResultReceiver cb) {
- try {
- mBinder.onCommand(command, cb);
- } catch (RemoteException e) {
- Log.e(TAG, "Error in sendCommand", e);
- }
- }
-
- /**
- * Tell the session that the provider has disconnected it.
- */
- public void disconnect() {
- if (mListener != null) {
- mListener.disconnect();
- }
- }
-
- @Override
- public String toString() {
- return "RouteConnection { binder=" + mBinder.toString() + ", package=" + mPackageName
- + ", uid=" + mUid + "}";
- }
-
- /**
- * Listener to receive updates from the provider for this connection.
- */
- public static interface Listener {
- /**
- * Called when an event is sent on this connection.
- *
- * @param event The event that was sent.
- */
- public void onEvent(RouteEvent event);
-
- /**
- * Called when the provider has disconnected the route.
- */
- public void disconnect();
- }
-}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index f0ec3bb..0da1fa4 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -815,6 +815,7 @@
final CharSequence body = res.getText(R.string.data_usage_limit_body);
final CharSequence title;
+ int icon = R.drawable.stat_notify_disabled_data;
switch (policy.template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
title = res.getText(R.string.data_usage_3g_limit_title);
@@ -827,6 +828,7 @@
break;
case MATCH_WIFI:
title = res.getText(R.string.data_usage_wifi_limit_title);
+ icon = R.drawable.stat_notify_error;
break;
default:
title = null;
@@ -834,7 +836,7 @@
}
builder.setOngoing(true);
- builder.setSmallIcon(R.drawable.stat_notify_disabled);
+ builder.setSmallIcon(icon);
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(body);
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 08c8271..a06daf6 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -53,6 +53,7 @@
private final CountdownConditionProvider mCountdown = new CountdownConditionProvider();
private Uri mExitConditionId;
+ private ComponentName mExitConditionComponent;
public ConditionProviders(Context context, Handler handler,
UserProfiles userProfiles, ZenModeHelper zenModeHelper) {
@@ -95,6 +96,7 @@
}
}
}
+ mCountdown.dump(pw, filter);
}
@Override
@@ -120,20 +122,20 @@
// we tried
}
synchronized (mMutex) {
+ if (info.component.equals(mExitConditionComponent)) {
+ // ensure record exists, we'll wire it up and subscribe below
+ final ConditionRecord manualRecord =
+ getRecordLocked(mExitConditionId, mExitConditionComponent);
+ manualRecord.isManual = true;
+ }
final int N = mRecords.size();
for(int i = 0; i < N; i++) {
final ConditionRecord r = mRecords.get(i);
if (!r.component.equals(info.component)) continue;
r.info = info;
- // if automatic, auto-subscribe
- if (r.isAutomatic) {
- try {
- final Uri id = r.id;
- if (DEBUG) Slog.d(TAG, "Auto-subscribing to configured condition " + id);
- provider.onSubscribe(id);
- } catch (RemoteException e) {
- // we tried
- }
+ // if automatic or manual, auto-subscribe
+ if (r.isAutomatic || r.isManual) {
+ subscribeLocked(r);
}
}
}
@@ -271,9 +273,10 @@
}
}
- public void setZenModeCondition(Uri conditionId) {
+ public void setZenModeCondition(Uri conditionId, String reason) {
if (DEBUG) Slog.d(TAG, "setZenModeCondition " + conditionId);
synchronized(mMutex) {
+ ComponentName conditionComponent = null;
if (ZenModeConfig.isValidCountdownConditionId(conditionId)) {
// constructed by the client, make sure the record exists...
final ConditionRecord r = getRecordLocked(conditionId,
@@ -296,9 +299,14 @@
subscribeLocked(r);
r.isManual = true;
}
+ if (idEqual) {
+ conditionComponent = r.component;
+ }
}
if (!Objects.equals(mExitConditionId, conditionId)) {
mExitConditionId = conditionId;
+ mExitConditionComponent = conditionComponent;
+ ZenLog.traceExitCondition(mExitConditionId, mExitConditionComponent, reason);
saveZenConfigLocked();
}
}
@@ -307,15 +315,16 @@
private void subscribeLocked(ConditionRecord r) {
if (DEBUG) Slog.d(TAG, "subscribeLocked " + r);
final IConditionProvider provider = provider(r);
- if (provider == null) {
- Slog.w(TAG, "subscribeLocked: no provider");
- return;
+ RemoteException re = null;
+ if (provider != null) {
+ try {
+ provider.onSubscribe(r.id);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Error subscribing to " + r, e);
+ re = e;
+ }
}
- try {
- provider.onSubscribe(r.id);
- } catch (RemoteException e) {
- Slog.w(TAG, "Error subscribing to " + r, e);
- }
+ ZenLog.traceSubscribe(r != null ? r.id : null, provider, re);
}
private static <T> ArraySet<T> safeSet(T... items) {
@@ -381,15 +390,16 @@
private void unsubscribeLocked(ConditionRecord r) {
if (DEBUG) Slog.d(TAG, "unsubscribeLocked " + r);
final IConditionProvider provider = provider(r);
- if (provider == null) {
- Slog.w(TAG, "unsubscribeLocked: no provider");
- return;
+ RemoteException re = null;
+ if (provider != null) {
+ try {
+ provider.onUnsubscribe(r.id);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Error unsubscribing to " + r, e);
+ re = e;
+ }
}
- try {
- provider.onUnsubscribe(r.id);
- } catch (RemoteException e) {
- Slog.w(TAG, "Error unsubscribing to " + r, e);
- }
+ ZenLog.traceUnsubscribe(r != null ? r.id : null, provider, re);
}
private static IConditionProvider provider(ConditionRecord r) {
@@ -404,6 +414,13 @@
for (ManagedServiceInfo info : mServices) {
final IConditionProvider provider = provider(info);
if (provider == null) continue;
+ // clear all stored conditions from this provider that we no longer care about
+ for (int i = mRecords.size() - 1; i >= 0; i--) {
+ final ConditionRecord r = mRecords.get(i);
+ if (r.info != info) continue;
+ if (r.isManual || r.isAutomatic) continue;
+ mRecords.remove(i);
+ }
try {
provider.onRequestConditions(flags);
} catch (RemoteException e) {
@@ -419,7 +436,12 @@
return;
}
synchronized (mMutex) {
+ final boolean changingExit = !Objects.equals(mExitConditionId, config.exitConditionId);
mExitConditionId = config.exitConditionId;
+ mExitConditionComponent = config.exitConditionComponent;
+ if (changingExit) {
+ ZenLog.traceExitCondition(mExitConditionId, mExitConditionComponent, "config");
+ }
if (config.conditionComponents == null || config.conditionIds == null
|| config.conditionComponents.length != config.conditionIds.length) {
if (DEBUG) Slog.d(TAG, "loadZenConfig: no conditions");
@@ -467,6 +489,7 @@
}
}
config.exitConditionId = mExitConditionId;
+ config.exitConditionComponent = mExitConditionComponent;
if (DEBUG) Slog.d(TAG, "Setting zen config to: " + config);
mZenModeHelper.setConfig(config);
}
@@ -482,7 +505,7 @@
final int mode = mZenModeHelper.getZenMode();
if (mode == Global.ZEN_MODE_OFF) {
// ensure any manual condition is cleared
- setZenModeCondition(null);
+ setZenModeCondition(null, "zenOff");
}
}
}
diff --git a/services/core/java/com/android/server/notification/CountdownConditionProvider.java b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
index 0884f76..aaf7cfc 100644
--- a/services/core/java/com/android/server/notification/CountdownConditionProvider.java
+++ b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
@@ -31,6 +31,9 @@
import android.text.format.DateUtils;
import android.util.Slog;
+import com.android.server.notification.NotificationManagerService.DumpFilter;
+
+import java.io.PrintWriter;
import java.util.Date;
/** Built-in zen condition provider for simple time-based conditions */
@@ -49,11 +52,18 @@
private final Receiver mReceiver = new Receiver();
private boolean mConnected;
+ private long mTime;
public CountdownConditionProvider() {
if (DEBUG) Slog.d(TAG, "new CountdownConditionProvider()");
}
+ public void dump(PrintWriter pw, DumpFilter filter) {
+ pw.println(" CountdownConditionProvider:");
+ pw.print(" mConnected="); pw.println(mConnected);
+ pw.print(" mTime="); pw.println(mTime);
+ }
+
@Override
public void onConnected() {
if (DEBUG) Slog.d(TAG, "onConnected");
@@ -79,7 +89,7 @@
@Override
public void onSubscribe(Uri conditionId) {
if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
- final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
+ mTime = ZenModeConfig.tryParseCountdownConditionId(conditionId);
final AlarmManager alarms = (AlarmManager)
mContext.getSystemService(Context.ALARM_SERVICE);
final Intent intent = new Intent(ACTION).putExtra(EXTRA_CONDITION_ID, conditionId)
@@ -87,14 +97,21 @@
final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarms.cancel(pendingIntent);
- if (time > 0) {
+ if (mTime > 0) {
final long now = System.currentTimeMillis();
final CharSequence span =
- DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
+ DateUtils.getRelativeTimeSpanString(mTime, now, DateUtils.MINUTE_IN_MILLIS);
+ if (mTime <= now) {
+ // in the past, already false
+ notifyCondition(newCondition(mTime, Condition.STATE_FALSE));
+ } else {
+ // in the future, set an alarm
+ alarms.setExact(AlarmManager.RTC_WAKEUP, mTime, pendingIntent);
+ }
if (DEBUG) Slog.d(TAG, String.format(
- "Scheduling %s for %s, %s in the future (%s), now=%s",
- ACTION, ts(time), time - now, span, ts(now)));
- alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
+ "%s %s for %s, %s in the future (%s), now=%s",
+ (mTime <= now ? "Not scheduling" : "Scheduling"),
+ ACTION, ts(mTime), mTime - now, span, ts(now)));
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 6cd4019..0546a55 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -28,6 +28,12 @@
if (lhs.isRecentlyIntrusive() != rhs.isRecentlyIntrusive()) {
return lhs.isRecentlyIntrusive() ? -1 : 1;
}
+ final int leftPackagePriority = lhs.getPackagePriority();
+ final int rightPackagePriority = rhs.getPackagePriority();
+ if (leftPackagePriority != rightPackagePriority) {
+ // by priority, high to low
+ return -1 * Integer.compare(leftPackagePriority, rightPackagePriority);
+ }
final int leftScore = lhs.sbn.getScore();
final int rightScore = rhs.sbn.getScore();
if (leftScore != rightScore) {
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index d8ab9d7..1335706 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -63,4 +63,9 @@
}
};
}
-}
\ No newline at end of file
+
+ @Override
+ public void setConfig(RankingConfig config) {
+ // ignore: config has no relevant information yet.
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 892f61f..aa9e151 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -103,11 +103,9 @@
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import java.util.concurrent.TimeUnit;
/** {@hide} */
public class NotificationManagerService extends SystemService {
@@ -120,7 +118,8 @@
static final int MESSAGE_TIMEOUT = 2;
static final int MESSAGE_SAVE_POLICY_FILE = 3;
static final int MESSAGE_RECONSIDER_RANKING = 4;
- static final int MESSAGE_SEND_RANKING_UPDATE = 5;
+ static final int MESSAGE_RANKING_CONFIG_CHANGE = 5;
+ static final int MESSAGE_SEND_RANKING_UPDATE = 6;
static final int LONG_DELAY = 3500; // 3.5 seconds
static final int SHORT_DELAY = 2000; // 2 seconds
@@ -152,7 +151,6 @@
private WorkerHandler mHandler;
private final HandlerThread mRankingThread = new HandlerThread("ranker",
Process.THREAD_PRIORITY_BACKGROUND);
- private Handler mRankingHandler = null;
private Light mNotificationLight;
Light mAttentionLight;
@@ -178,7 +176,6 @@
// used as a mutex for access to all active notifications & listeners
final ArrayList<NotificationRecord> mNotificationList =
new ArrayList<NotificationRecord>();
- final NotificationComparator mRankingComparator = new NotificationComparator();
final ArrayMap<String, NotificationRecord> mNotificationsByKey =
new ArrayMap<String, NotificationRecord>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
@@ -203,7 +200,7 @@
private static final String TAG_PACKAGE = "package";
private static final String ATTR_NAME = "name";
- final ArrayList<NotificationSignalExtractor> mSignalExtractors = new ArrayList<NotificationSignalExtractor>();
+ private RankingHelper mRankingHelper;
private final UserProfiles mUserProfiles = new UserProfiles();
private NotificationListeners mListeners;
@@ -360,6 +357,7 @@
}
}
mZenModeHelper.readXml(parser);
+ mRankingHelper.readXml(parser);
}
} catch (FileNotFoundException e) {
// No data yet
@@ -398,6 +396,7 @@
out.startTag(null, TAG_BODY);
out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION));
mZenModeHelper.writeXml(out);
+ mRankingHelper.writeXml(out);
out.endTag(null, TAG_BODY);
out.endDocument();
mPolicyFile.finishWrite(stream);
@@ -752,13 +751,23 @@
@Override
public void onStart() {
+ Resources resources = getContext().getResources();
+
mAm = ActivityManagerNative.getDefault();
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
mHandler = new WorkerHandler();
mRankingThread.start();
- mRankingHandler = new RankingWorkerHandler(mRankingThread.getLooper());
+ String[] extractorNames;
+ try {
+ extractorNames = resources.getStringArray(R.array.config_notificationSignalExtractors);
+ } catch (Resources.NotFoundException e) {
+ extractorNames = new String[0];
+ }
+ mRankingHelper = new RankingHelper(getContext(),
+ new RankingWorkerHandler(mRankingThread.getLooper()),
+ extractorNames);
mZenModeHelper = new ZenModeHelper(getContext(), mHandler);
mZenModeHelper.addCallback(new ZenModeHelper.Callback() {
@Override
@@ -782,7 +791,6 @@
mNotificationLight = lights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);
mAttentionLight = lights.getLight(LightsManager.LIGHT_ID_ATTENTION);
- Resources resources = getContext().getResources();
mDefaultNotificationColor = resources.getColor(
R.color.config_defaultNotificationColor);
mDefaultNotificationLedOn = resources.getInteger(
@@ -837,25 +845,6 @@
mSettingsObserver = new SettingsObserver(mHandler);
- // spin up NotificationSignalExtractors
- String[] extractorNames = resources.getStringArray(
- R.array.config_notificationSignalExtractors);
- for (String extractorName : extractorNames) {
- try {
- Class<?> extractorClass = getContext().getClassLoader().loadClass(extractorName);
- NotificationSignalExtractor extractor =
- (NotificationSignalExtractor) extractorClass.newInstance();
- extractor.initialize(getContext());
- mSignalExtractors.add(extractor);
- } catch (ClassNotFoundException e) {
- Slog.w(TAG, "Couldn't find extractor " + extractorName + ".", e);
- } catch (InstantiationException e) {
- Slog.w(TAG, "Couldn't instantiate extractor " + extractorName + ".", e);
- } catch (IllegalAccessException e) {
- Slog.w(TAG, "Problem accessing extractor " + extractorName + ".", e);
- }
- }
-
mArchive = new Archive(resources.getInteger(
R.integer.config_notificationServiceArchiveSize));
@@ -1062,6 +1051,19 @@
== AppOpsManager.MODE_ALLOWED);
}
+ @Override
+ public void setPackagePriority(String pkg, int uid, int priority) {
+ checkCallerIsSystem();
+ mRankingHelper.setPackagePriority(pkg, uid, priority);
+ savePolicyFile();
+ }
+
+ @Override
+ public int getPackagePriority(String pkg, int uid) {
+ checkCallerIsSystem();
+ return mRankingHelper.getPackagePriority(pkg, uid);
+ }
+
/**
* System-only API for getting a list of current (i.e. not cleared) notifications.
*
@@ -1280,7 +1282,7 @@
enforceSystemOrSystemUI("INotificationManager.setZenModeCondition");
final long identity = Binder.clearCallingIdentity();
try {
- mConditionProviders.setZenModeCondition(conditionId);
+ mConditionProviders.setZenModeCondition(conditionId, "binderCall");
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1338,72 +1340,87 @@
void dumpImpl(PrintWriter pw, DumpFilter filter) {
pw.print("Current Notification Manager state");
if (filter != null) {
- pw.print(" (filtered to '"); pw.print(filter.pkgFilter); pw.print("')");
+ pw.print(" (filtered to "); pw.print(filter); pw.print(")");
}
pw.println(':');
int N;
+ final boolean zenOnly = filter != null && filter.zen;
- synchronized (mToastQueue) {
- N = mToastQueue.size();
- if (N > 0) {
- pw.println(" Toast Queue:");
- for (int i=0; i<N; i++) {
- mToastQueue.get(i).dump(pw, " ", filter);
+ if (!zenOnly) {
+ synchronized (mToastQueue) {
+ N = mToastQueue.size();
+ if (N > 0) {
+ pw.println(" Toast Queue:");
+ for (int i=0; i<N; i++) {
+ mToastQueue.get(i).dump(pw, " ", filter);
+ }
+ pw.println(" ");
}
- pw.println(" ");
}
}
synchronized (mNotificationList) {
- N = mNotificationList.size();
- if (N > 0) {
- pw.println(" Notification List:");
- for (int i=0; i<N; i++) {
- final NotificationRecord nr = mNotificationList.get(i);
- if (filter != null && !filter.matches(nr.sbn)) continue;
- nr.dump(pw, " ", getContext());
- }
- pw.println(" ");
- }
-
- if (filter == null) {
- N = mLights.size();
+ if (!zenOnly) {
+ N = mNotificationList.size();
if (N > 0) {
- pw.println(" Lights List:");
+ pw.println(" Notification List:");
for (int i=0; i<N; i++) {
- pw.println(" " + mLights.get(i));
+ final NotificationRecord nr = mNotificationList.get(i);
+ if (filter != null && !filter.matches(nr.sbn)) continue;
+ nr.dump(pw, " ", getContext());
}
pw.println(" ");
}
- pw.println(" mSoundNotification=" + mSoundNotification);
- pw.println(" mVibrateNotification=" + mVibrateNotification);
- pw.println(" mDisableNotificationAlerts=" + mDisableNotificationAlerts);
- pw.println(" mSystemReady=" + mSystemReady);
- }
- pw.println(" mArchive=" + mArchive.toString());
- Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
- int i=0;
- while (iter.hasNext()) {
- final StatusBarNotification sbn = iter.next();
- if (filter != null && !filter.matches(sbn)) continue;
- pw.println(" " + sbn);
- if (++i >= 5) {
- if (iter.hasNext()) pw.println(" ...");
- break;
+ if (filter == null) {
+ N = mLights.size();
+ if (N > 0) {
+ pw.println(" Lights List:");
+ for (int i=0; i<N; i++) {
+ pw.println(" " + mLights.get(i));
+ }
+ pw.println(" ");
+ }
+
+ pw.println(" mSoundNotification=" + mSoundNotification);
+ pw.println(" mVibrateNotification=" + mVibrateNotification);
+ pw.println(" mDisableNotificationAlerts=" + mDisableNotificationAlerts);
+ pw.println(" mSystemReady=" + mSystemReady);
+ }
+ pw.println(" mArchive=" + mArchive.toString());
+ Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
+ int i=0;
+ while (iter.hasNext()) {
+ final StatusBarNotification sbn = iter.next();
+ if (filter != null && !filter.matches(sbn)) continue;
+ pw.println(" " + sbn);
+ if (++i >= 5) {
+ if (iter.hasNext()) pw.println(" ...");
+ break;
+ }
}
}
- pw.println("\n Usage Stats:");
- mUsageStats.dump(pw, " ", filter);
-
- if (filter == null) {
- pw.println("\n Zen Mode:");
- mZenModeHelper.dump(pw, " ");
+ if (!zenOnly) {
+ pw.println("\n Usage Stats:");
+ mUsageStats.dump(pw, " ", filter);
}
- pw.println("\n Notification listeners:");
- mListeners.dump(pw, filter);
+ if (filter == null || zenOnly) {
+ pw.println("\n Zen Mode:");
+ mZenModeHelper.dump(pw, " ");
+
+ pw.println("\n Zen Log:");
+ ZenLog.dump(pw, " ");
+ }
+
+ if (!zenOnly) {
+ pw.println("\n Ranking Config:");
+ mRankingHelper.dump(pw, " ", filter);
+
+ pw.println("\n Notification listeners:");
+ mListeners.dump(pw, filter);
+ }
pw.println("\n Condition providers:");
mConditionProviders.dump(pw, filter);
@@ -1509,16 +1526,7 @@
// Retain ranking information from previous record
r.copyRankingInformation(old);
}
- if (!mSignalExtractors.isEmpty()) {
- for (NotificationSignalExtractor extractor : mSignalExtractors) {
- try {
- RankingReconsideration recon = extractor.process(r);
- scheduleRankingReconsideration(recon);
- } catch (Throwable t) {
- Slog.w(TAG, "NotificationSignalExtractor failed.", t);
- }
- }
- }
+ mRankingHelper.extractSignals(r);
// 3. Apply local rules
@@ -1563,7 +1571,7 @@
applyZenModeLocked(r);
- Collections.sort(mNotificationList, mRankingComparator);
+ mRankingHelper.sort(mNotificationList);
if (notification.icon != 0) {
mListeners.notifyPostedLocked(n);
@@ -1838,14 +1846,6 @@
}
}
- private void scheduleRankingReconsideration(RankingReconsideration recon) {
- if (recon != null) {
- Message m = Message.obtain(mRankingHandler, MESSAGE_RECONSIDER_RANKING, recon);
- long delay = recon.getDelay(TimeUnit.MILLISECONDS);
- mRankingHandler.sendMessageDelayed(m, delay);
- }
- }
-
private void handleRankingReconsideration(Message message) {
if (!(message.obj instanceof RankingReconsideration)) return;
RankingReconsideration recon = (RankingReconsideration) message.obj;
@@ -1860,7 +1860,7 @@
boolean interceptBefore = record.isIntercepted();
recon.applyChangesLocked(record);
applyZenModeLocked(record);
- Collections.sort(mNotificationList, mRankingComparator);
+ mRankingHelper.sort(mNotificationList);
int indexAfter = findNotificationRecordIndexLocked(record);
boolean interceptAfter = record.isIntercepted();
changed = indexBefore != indexAfter || interceptBefore != interceptAfter;
@@ -1873,6 +1873,25 @@
}
}
+ private void handleRankingConfigChange() {
+ synchronized (mNotificationList) {
+ final int N = mNotificationList.size();
+ ArrayList<String> orderBefore = new ArrayList<String>(N);
+ for (int i = 0; i < N; i++) {
+ final NotificationRecord r = mNotificationList.get(i);
+ orderBefore.add(r.getKey());
+ mRankingHelper.extractSignals(r);
+ }
+ mRankingHelper.sort(mNotificationList);
+ for (int i = 0; i < N; i++) {
+ if (!orderBefore.get(i).equals(mNotificationList.get(i).getKey())) {
+ scheduleSendRankingUpdate();
+ return;
+ }
+ }
+ }
+ }
+
// let zen mode evaluate this record
private void applyZenModeLocked(NotificationRecord record) {
record.setIntercepted(mZenModeHelper.shouldIntercept(record));
@@ -1880,7 +1899,7 @@
// lock on mNotificationList
private int findNotificationRecordIndexLocked(NotificationRecord target) {
- return Collections.binarySearch(mNotificationList, target, mRankingComparator);
+ return mRankingHelper.indexOf(mNotificationList, target);
}
private void scheduleSendRankingUpdate() {
@@ -1928,6 +1947,9 @@
case MESSAGE_RECONSIDER_RANKING:
handleRankingReconsideration(msg);
break;
+ case MESSAGE_RANKING_CONFIG_CHANGE:
+ handleRankingConfigChange();
+ break;
}
}
}
@@ -2461,27 +2483,39 @@
public static final class DumpFilter {
public String pkgFilter;
+ public boolean zen;
public static DumpFilter parseFromArguments(String[] args) {
- if (args == null || args.length != 2 || !"p".equals(args[0])
- || args[1] == null || args[1].trim().isEmpty()) {
- return null;
+ if (args != null && args.length == 2 && "p".equals(args[0])
+ && args[1] != null && !args[1].trim().isEmpty()) {
+ final DumpFilter filter = new DumpFilter();
+ filter.pkgFilter = args[1].trim().toLowerCase();
+ return filter;
}
- final DumpFilter filter = new DumpFilter();
- filter.pkgFilter = args[1].trim().toLowerCase();
- return filter;
+ if (args != null && args.length == 1 && "zen".equals(args[0])) {
+ final DumpFilter filter = new DumpFilter();
+ filter.zen = true;
+ return filter;
+ }
+ return null;
}
public boolean matches(StatusBarNotification sbn) {
- return sbn != null && (matches(sbn.getPackageName()) || matches(sbn.getOpPkg()));
+ return zen ? true : sbn != null
+ && (matches(sbn.getPackageName()) || matches(sbn.getOpPkg()));
}
public boolean matches(ComponentName component) {
- return component != null && matches(component.getPackageName());
+ return zen ? true : component != null && matches(component.getPackageName());
}
public boolean matches(String pkg) {
- return pkg != null && pkg.toLowerCase().contains(pkgFilter);
+ return zen ? true : pkg != null && pkg.toLowerCase().contains(pkgFilter);
+ }
+
+ @Override
+ public String toString() {
+ return zen ? "zen" : ('\'' + pkgFilter + '\'');
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 0e6265c..088b813 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -58,6 +58,7 @@
// Is this record an update of an old record?
public boolean isUpdate;
+ private int mPackagePriority;
NotificationRecord(StatusBarNotification sbn, int score)
{
@@ -70,6 +71,7 @@
public void copyRankingInformation(NotificationRecord previous) {
mContactAffinity = previous.mContactAffinity;
mRecentlyIntrusive = previous.mRecentlyIntrusive;
+ mPackagePriority = previous.mPackagePriority;
mIntercept = previous.mIntercept;
mRankingTimeMs = calculateRankingTimeMs(previous.getRankingTimeMs());
}
@@ -141,6 +143,7 @@
pw.println(prefix + " stats=" + stats.toString());
pw.println(prefix + " mContactAffinity=" + mContactAffinity);
pw.println(prefix + " mRecentlyIntrusive=" + mRecentlyIntrusive);
+ pw.println(prefix + " mPackagePriority=" + mPackagePriority);
pw.println(prefix + " mIntercept=" + mIntercept);
pw.println(prefix + " mRankingTimeMs=" + mRankingTimeMs);
}
@@ -193,6 +196,14 @@
return mRecentlyIntrusive;
}
+ public void setPackagePriority(int packagePriority) {
+ mPackagePriority = packagePriority;
+ }
+
+ public int getPackagePriority() {
+ return mPackagePriority;
+ }
+
public boolean setIntercepted(boolean intercept) {
mIntercept = intercept;
return mIntercept;
@@ -230,5 +241,4 @@
}
return sbn.getPostTime();
}
-
}
diff --git a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
index 1537ea9..43d05d0 100644
--- a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
@@ -38,4 +38,10 @@
*/
public RankingReconsideration process(NotificationRecord notification);
+ /**
+ * Called whenever the {@link RankingConfig} changes.
+ *
+ * @param config information about which signals are important.
+ */
+ void setConfig(RankingConfig config);
}
diff --git a/services/core/java/com/android/server/notification/PackagePriorityExtractor.java b/services/core/java/com/android/server/notification/PackagePriorityExtractor.java
new file mode 100644
index 0000000..9cdb3e1
--- /dev/null
+++ b/services/core/java/com/android/server/notification/PackagePriorityExtractor.java
@@ -0,0 +1,54 @@
+/*
+* 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.
+*/
+package com.android.server.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.util.Slog;
+
+public class PackagePriorityExtractor implements NotificationSignalExtractor {
+ private static final String TAG = "ImportantPackageExtractor";
+ private static final boolean DBG = false;
+
+ private RankingConfig mConfig;
+
+ public void initialize(Context ctx) {
+ if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
+ }
+
+ public RankingReconsideration process(NotificationRecord record) {
+ if (record == null || record.getNotification() == null) {
+ if (DBG) Slog.d(TAG, "skipping empty notification");
+ return null;
+ }
+
+ if (mConfig == null) {
+ if (DBG) Slog.d(TAG, "missing config");
+ return null;
+ }
+
+ final int packagePriority = mConfig.getPackagePriority(
+ record.sbn.getPackageName(), record.sbn.getUid());
+ record.setPackagePriority(packagePriority);
+
+ return null;
+ }
+
+ @Override
+ public void setConfig(RankingConfig config) {
+ mConfig = config;
+ }
+}
diff --git a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl b/services/core/java/com/android/server/notification/RankingConfig.java
similarity index 67%
copy from telecomm/java/android/telecomm/CallServiceDescriptor.aidl
copy to services/core/java/com/android/server/notification/RankingConfig.java
index f517c73..7d0bd59 100644
--- a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -1,5 +1,5 @@
-/*
- * Copyright 2014, The Android Open Source Project
+/**
+ * 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.
@@ -13,7 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.server.notification;
-package android.telecomm;
+public interface RankingConfig {
+ int getPackagePriority(String packageName, int uid);
-parcelable CallServiceDescriptor;
+ void setPackagePriority(String packageName, int uid, int priority);
+}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
new file mode 100644
index 0000000..fc03c17
--- /dev/null
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -0,0 +1,250 @@
+/**
+ * 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.
+ */
+package com.android.server.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Slog;
+import android.util.SparseIntArray;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+public class RankingHelper implements RankingConfig {
+ private static final String TAG = "RankingHelper";
+ private static final boolean DEBUG = false;
+
+ private static final int XML_VERSION = 1;
+
+ private static final String TAG_RANKING = "ranking";
+ private static final String TAG_PACKAGE = "package";
+ private static final String ATT_VERSION = "version";
+
+ private static final String ATT_NAME = "name";
+ private static final String ATT_UID = "uid";
+ private static final String ATT_PRIORITY = "priority";
+
+ private static final String VALUE_HIGH = "high";
+
+ private final NotificationSignalExtractor[] mSignalExtractors;
+ private final NotificationComparator mRankingComparator = new NotificationComparator();
+
+ // Package name to uid, to priority. Would be better as Table<String, Int, Int>
+ private final ArrayMap<String, SparseIntArray> mPackagePriorities;
+
+ private final Context mContext;
+ private final Handler mRankingHandler;
+
+ public RankingHelper(Context context, Handler rankingHandler, String[] extractorNames) {
+ mContext = context;
+ mRankingHandler = rankingHandler;
+ mPackagePriorities = new ArrayMap<String, SparseIntArray>();
+
+ final int N = extractorNames.length;
+ mSignalExtractors = new NotificationSignalExtractor[N];
+ for (int i = 0; i < N; i++) {
+ try {
+ Class<?> extractorClass = mContext.getClassLoader().loadClass(extractorNames[i]);
+ NotificationSignalExtractor extractor =
+ (NotificationSignalExtractor) extractorClass.newInstance();
+ extractor.initialize(mContext);
+ extractor.setConfig(this);
+ mSignalExtractors[i] = extractor;
+ } catch (ClassNotFoundException e) {
+ Slog.w(TAG, "Couldn't find extractor " + extractorNames[i] + ".", e);
+ } catch (InstantiationException e) {
+ Slog.w(TAG, "Couldn't instantiate extractor " + extractorNames[i] + ".", e);
+ } catch (IllegalAccessException e) {
+ Slog.w(TAG, "Problem accessing extractor " + extractorNames[i] + ".", e);
+ }
+ }
+ }
+
+ public void extractSignals(NotificationRecord r) {
+ final int N = mSignalExtractors.length;
+ for (int i = 0; i < N; i++) {
+ NotificationSignalExtractor extractor = mSignalExtractors[i];
+ try {
+ RankingReconsideration recon = extractor.process(r);
+ if (recon != null) {
+ Message m = Message.obtain(mRankingHandler,
+ NotificationManagerService.MESSAGE_RECONSIDER_RANKING, recon);
+ long delay = recon.getDelay(TimeUnit.MILLISECONDS);
+ mRankingHandler.sendMessageDelayed(m, delay);
+ }
+ } catch (Throwable t) {
+ Slog.w(TAG, "NotificationSignalExtractor failed.", t);
+ }
+ }
+ }
+
+ public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException {
+ int type = parser.getEventType();
+ if (type != XmlPullParser.START_TAG) return;
+ String tag = parser.getName();
+ if (!TAG_RANKING.equals(tag)) return;
+ mPackagePriorities.clear();
+ final int version = safeInt(parser, ATT_VERSION, XML_VERSION);
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ tag = parser.getName();
+ if (type == XmlPullParser.END_TAG && TAG_RANKING.equals(tag)) {
+ return;
+ }
+ if (type == XmlPullParser.START_TAG) {
+ if (TAG_PACKAGE.equals(tag)) {
+ int uid = safeInt(parser, ATT_UID, UserHandle.USER_ALL);
+ int priority = safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT);
+ String name = parser.getAttributeValue(null, ATT_NAME);
+
+ if (!TextUtils.isEmpty(name) && priority != Notification.PRIORITY_DEFAULT) {
+ SparseIntArray priorityByUid = mPackagePriorities.get(name);
+ if (priorityByUid == null) {
+ priorityByUid = new SparseIntArray();
+ mPackagePriorities.put(name, priorityByUid);
+ }
+ priorityByUid.put(uid, priority);
+ }
+ }
+ }
+ }
+ throw new IllegalStateException("Failed to reach END_DOCUMENT");
+ }
+
+ public void writeXml(XmlSerializer out) throws IOException {
+ out.startTag(null, TAG_RANKING);
+ out.attribute(null, ATT_VERSION, Integer.toString(XML_VERSION));
+
+ final int N = mPackagePriorities.size();
+ for (int i = 0; i < N; i ++) {
+ String name = mPackagePriorities.keyAt(i);
+ SparseIntArray priorityByUid = mPackagePriorities.get(name);
+ final int M = priorityByUid.size();
+ for (int j = 0; j < M; j++) {
+ int uid = priorityByUid.keyAt(j);
+ int priority = priorityByUid.get(uid);
+ out.startTag(null, TAG_PACKAGE);
+ out.attribute(null, ATT_NAME, name);
+ out.attribute(null, ATT_UID, Integer.toString(uid));
+ out.attribute(null, ATT_PRIORITY, Integer.toString(priority));
+ out.endTag(null, TAG_PACKAGE);
+ }
+ }
+ out.endTag(null, TAG_RANKING);
+ }
+
+ private void updateConfig() {
+ final int N = mSignalExtractors.length;
+ for (int i = 0; i < N; i++) {
+ mSignalExtractors[i].setConfig(this);
+ }
+ mRankingHandler.sendEmptyMessage(NotificationManagerService.MESSAGE_RANKING_CONFIG_CHANGE);
+ }
+
+ public void sort(ArrayList<NotificationRecord> notificationList) {
+ Collections.sort(notificationList, mRankingComparator);
+ }
+
+ public int indexOf(ArrayList<NotificationRecord> notificationList, NotificationRecord target) {
+ return Collections.binarySearch(notificationList, target, mRankingComparator);
+ }
+
+ private static int safeInt(XmlPullParser parser, String att, int defValue) {
+ final String val = parser.getAttributeValue(null, att);
+ return tryParseInt(val, defValue);
+ }
+
+ private static int tryParseInt(String value, int defValue) {
+ if (TextUtils.isEmpty(value)) return defValue;
+ try {
+ return Integer.valueOf(value);
+ } catch (NumberFormatException e) {
+ return defValue;
+ }
+ }
+
+ @Override
+ public int getPackagePriority(String packageName, int uid) {
+ int priority = Notification.PRIORITY_DEFAULT;
+ SparseIntArray priorityByUid = mPackagePriorities.get(packageName);
+ if (priorityByUid != null) {
+ priority = priorityByUid.get(uid, Notification.PRIORITY_DEFAULT);
+ }
+ return priority;
+ }
+
+ @Override
+ public void setPackagePriority(String packageName, int uid, int priority) {
+ if (priority == getPackagePriority(packageName, uid)) {
+ return;
+ }
+ SparseIntArray priorityByUid = mPackagePriorities.get(packageName);
+ if (priorityByUid == null) {
+ priorityByUid = new SparseIntArray();
+ mPackagePriorities.put(packageName, priorityByUid);
+ }
+ priorityByUid.put(uid, priority);
+ updateConfig();
+ }
+
+ public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
+ if (filter == null) {
+ final int N = mSignalExtractors.length;
+ pw.print(prefix);
+ pw.print("mSignalExtractors.length = ");
+ pw.println(N);
+ for (int i = 0; i < N; i++) {
+ pw.print(prefix);
+ pw.print(" ");
+ pw.println(mSignalExtractors[i]);
+ }
+ }
+ final int N = mPackagePriorities.size();
+ if (filter == null) {
+ pw.print(prefix);
+ pw.println("package priorities:");
+ }
+ for (int i = 0; i < N; i++) {
+ String name = mPackagePriorities.keyAt(i);
+ if (filter == null || filter.matches(name)) {
+ SparseIntArray priorityByUid = mPackagePriorities.get(name);
+ final int M = priorityByUid.size();
+ for (int j = 0; j < M; j++) {
+ int uid = priorityByUid.keyAt(j);
+ int priority = priorityByUid.get(uid);
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print(name);
+ pw.print(" (");
+ pw.print(uid);
+ pw.print(") has priority: ");
+ pw.println(priority);
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index 4ac2dcc..bdc364c 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -264,6 +264,11 @@
return validatePeople(record);
}
+ @Override
+ public void setConfig(RankingConfig config) {
+ // ignore: config has no relevant information yet.
+ }
+
private static class LookupResult {
private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000; // 1hr
public static final int INVALID_ID = -1;
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
new file mode 100644
index 0000000..81f64b1
--- /dev/null
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -0,0 +1,164 @@
+/**
+ * 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.
+ */
+
+package com.android.server.notification;
+
+import android.content.ComponentName;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.RemoteException;
+import android.provider.Settings.Global;
+import android.service.notification.IConditionProvider;
+import android.service.notification.ZenModeConfig;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+
+public class ZenLog {
+ private static final String TAG = "ZenLog";
+
+ private static final int SIZE = Build.IS_DEBUGGABLE ? 100 : 20;
+
+ private static final long[] TIMES = new long[SIZE];
+ private static final int[] TYPES = new int[SIZE];
+ private static final String[] MSGS = new String[SIZE];
+
+ private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+
+ private static final int TYPE_INTERCEPTED = 1;
+ private static final int TYPE_ALLOW_DISABLE = 2;
+ private static final int TYPE_SET_RINGER_MODE = 3;
+ private static final int TYPE_DOWNTIME = 4;
+ private static final int TYPE_ZEN_MODE = 5;
+ private static final int TYPE_EXIT_CONDITION = 6;
+ private static final int TYPE_SUBSCRIBE = 7;
+ private static final int TYPE_UNSUBSCRIBE = 8;
+ private static final int TYPE_CONFIG = 9;
+
+ private static int sNext;
+ private static int sSize;
+
+ public static void traceIntercepted(NotificationRecord record, String reason) {
+ if (record != null && record.isIntercepted()) return; // already logged
+ append(TYPE_INTERCEPTED, record.getKey() + "," + reason);
+ }
+
+ public static void traceAllowDisable(String pkg, boolean allowDisable, String reason) {
+ append(TYPE_ALLOW_DISABLE, allowDisable + "," + pkg + "," + reason);
+ }
+
+ public static void traceSetRingerMode(int ringerMode) {
+ append(TYPE_SET_RINGER_MODE, ringerModeToString(ringerMode));
+ }
+
+ public static void traceDowntime(boolean enter, int day, int[] days) {
+ append(TYPE_DOWNTIME, enter + ",day=" + day + ",days=" + (days != null ? Arrays.asList(days)
+ : null));
+ }
+
+ public static void traceUpdateZenMode(int fromMode, int toMode) {
+ append(TYPE_ZEN_MODE, zenModeToString(fromMode) + " -> " + zenModeToString(toMode));
+ }
+
+ public static void traceExitCondition(Uri id, ComponentName component, String reason) {
+ append(TYPE_EXIT_CONDITION, id + "," + componentToString(component) + "," + reason);
+ }
+
+ public static void traceSubscribe(Uri uri, IConditionProvider provider, RemoteException e) {
+ append(TYPE_SUBSCRIBE, uri + "," + subscribeResult(provider, e));
+ }
+
+ public static void traceUnsubscribe(Uri uri, IConditionProvider provider, RemoteException e) {
+ append(TYPE_UNSUBSCRIBE, uri + "," + subscribeResult(provider, e));
+ }
+
+ public static void traceConfig(ZenModeConfig oldConfig, ZenModeConfig newConfig) {
+ append(TYPE_CONFIG, newConfig != null ? newConfig.toString() : null);
+ }
+
+ private static String subscribeResult(IConditionProvider provider, RemoteException e) {
+ return provider == null ? "no provider" : e != null ? e.getMessage() : "ok";
+ }
+
+ private static String typeToString(int type) {
+ switch (type) {
+ case TYPE_INTERCEPTED: return "intercepted";
+ case TYPE_ALLOW_DISABLE: return "allow_disable";
+ case TYPE_SET_RINGER_MODE: return "set_ringer_mode";
+ case TYPE_DOWNTIME: return "downtime";
+ case TYPE_ZEN_MODE: return "zen_mode";
+ case TYPE_EXIT_CONDITION: return "exit_condition";
+ case TYPE_SUBSCRIBE: return "subscribe";
+ case TYPE_UNSUBSCRIBE: return "unsubscribe";
+ case TYPE_CONFIG: return "config";
+ default: return "unknown";
+ }
+ }
+
+ private static String ringerModeToString(int ringerMode) {
+ switch (ringerMode) {
+ case AudioManager.RINGER_MODE_SILENT: return "silent";
+ case AudioManager.RINGER_MODE_VIBRATE: return "vibrate";
+ case AudioManager.RINGER_MODE_NORMAL: return "normal";
+ default: return "unknown";
+ }
+ }
+
+ private static String zenModeToString(int zenMode) {
+ switch (zenMode) {
+ case Global.ZEN_MODE_OFF: return "off";
+ case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return "important_interruptions";
+ case Global.ZEN_MODE_NO_INTERRUPTIONS: return "no_interruptions";
+ default: return "unknown";
+ }
+ }
+
+ private static String componentToString(ComponentName component) {
+ return component != null ? component.toShortString() : null;
+ }
+
+ private static void append(int type, String msg) {
+ synchronized(MSGS) {
+ TIMES[sNext] = System.currentTimeMillis();
+ TYPES[sNext] = type;
+ MSGS[sNext] = msg;
+ sNext = (sNext + 1) % SIZE;
+ if (sSize < SIZE) {
+ sSize++;
+ }
+ }
+ Slog.d(TAG, typeToString(type) + ": " + msg);
+ }
+
+ public static void dump(PrintWriter pw, String prefix) {
+ synchronized(MSGS) {
+ final int start = (sNext - sSize + SIZE) % SIZE;
+ for (int i = 0; i < sSize; i++) {
+ final int j = (start + i) % SIZE;
+ pw.print(prefix);
+ pw.print(FORMAT.format(new Date(TIMES[j])));
+ pw.print(' ');
+ pw.print(typeToString(TYPES[j]));
+ pw.print(": ");
+ pw.println(MSGS[j]);
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index f74e371..118b9fc 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -139,18 +139,32 @@
return false;
}
if (isAlarm(record)) {
- return mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+ if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+ ZenLog.traceIntercepted(record, "alarm");
+ return true;
+ }
+ return false;
}
// audience has veto power over all following rules
if (!audienceMatches(record)) {
+ ZenLog.traceIntercepted(record, "!audienceMatches");
return true;
}
if (isCall(record)) {
- return !mConfig.allowCalls;
+ if (!mConfig.allowCalls) {
+ ZenLog.traceIntercepted(record, "!allowCalls");
+ return true;
+ }
+ return false;
}
if (isMessage(record)) {
- return !mConfig.allowMessages;
+ if (!mConfig.allowMessages) {
+ ZenLog.traceIntercepted(record, "!allowMessages");
+ return true;
+ }
+ return false;
}
+ ZenLog.traceIntercepted(record, "!allowed");
return true;
}
return false;
@@ -171,6 +185,7 @@
Slog.d(TAG, String.format("updateZenMode: %s -> %s",
Global.zenModeToString(mZenMode),
Global.zenModeToString(mode)));
+ ZenLog.traceUpdateZenMode(mZenMode, mode);
}
mZenMode = mode;
final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
@@ -202,30 +217,41 @@
// force ringer mode into compliance
if (mAudioManager != null) {
int ringerMode = mAudioManager.getRingerMode();
+ int forcedRingerMode = -1;
if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
if (ringerMode != AudioManager.RINGER_MODE_SILENT) {
mPreviousRingerMode = ringerMode;
Slog.d(TAG, "Silencing ringer");
- mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
+ forcedRingerMode = AudioManager.RINGER_MODE_SILENT;
}
} else {
if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
Slog.d(TAG, "Unsilencing ringer");
- mAudioManager.setRingerMode(mPreviousRingerMode != -1 ? mPreviousRingerMode
- : AudioManager.RINGER_MODE_NORMAL);
+ forcedRingerMode = mPreviousRingerMode != -1 ? mPreviousRingerMode
+ : AudioManager.RINGER_MODE_NORMAL;
mPreviousRingerMode = -1;
}
}
+ if (forcedRingerMode != -1) {
+ mAudioManager.setRingerMode(forcedRingerMode);
+ ZenLog.traceSetRingerMode(forcedRingerMode);
+ }
}
dispatchOnZenModeChanged();
}
public boolean allowDisable(int what, IBinder token, String pkg) {
// TODO(cwren): delete this API before the next release. Bug:15344099
+ boolean allowDisable = true;
+ String reason = null;
if (isDefaultPhoneApp(pkg)) {
- return mZenMode == Global.ZEN_MODE_OFF || mConfig.allowCalls;
+ allowDisable = mZenMode == Global.ZEN_MODE_OFF || mConfig.allowCalls;
+ reason = mZenMode == Global.ZEN_MODE_OFF ? "zenOff" : "allowCalls";
}
- return true;
+ if (!SYSTEM_PACKAGES.contains(pkg)) {
+ ZenLog.traceAllowDisable(pkg, allowDisable, reason);
+ }
+ return allowDisable;
}
public void dump(PrintWriter pw, String prefix) {
@@ -255,8 +281,8 @@
public boolean setConfig(ZenModeConfig config) {
if (config == null || !config.isValid()) return false;
if (config.equals(mConfig)) return true;
+ ZenLog.traceConfig(mConfig, config);
mConfig = config;
- Slog.d(TAG, "mConfig=" + mConfig);
dispatchOnConfigChanged();
final String val = Integer.toString(mConfig.hashCode());
Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
@@ -398,20 +424,18 @@
intent.getAction(), ts(schTime), ts(now), now - schTime));
final int[] days = ZenModeConfig.tryParseDays(mConfig.sleepMode);
+ boolean enter = false;
+ final int day = getDayOfWeek(schTime);
if (days != null) {
- final int day = getDayOfWeek(schTime);
for (int i = 0; i < days.length; i++) {
if (days[i] == day) {
- Slog.d(TAG, "Enter downtime, day=" + day + " days=" + Arrays.asList(days));
+ enter = true;
ZenModeHelper.this.setZenMode(zenModeValue);
break;
- } else {
- Slog.d(TAG, "Skip downtime, day=" + day + " days=" + Arrays.asList(days));
}
}
- } else {
- Slog.d(TAG, "Skip downtime, no days configured");
}
+ ZenLog.traceDowntime(enter, day, days);
updateAlarms();
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 1d53016..355f34f 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -75,7 +75,7 @@
schedule(BackgroundDexOptService.this);
return;
}
- pm.performDexOpt(pkg, false);
+ pm.performDexOpt(pkg, null /* instruction set */, false);
}
// ran to completion, so we abandon our timeslice and do not reschedule
jobFinished(jobParams, false);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 1193968..8b0a46d 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -309,6 +309,15 @@
return execute(builder.toString());
}
+ public int deleteCodeCacheFiles(String name, int userId) {
+ StringBuilder builder = new StringBuilder("rmcodecache");
+ builder.append(' ');
+ builder.append(name);
+ builder.append(' ');
+ builder.append(userId);
+ return execute(builder.toString());
+ }
+
public int createUserData(String name, int uid, int userId, String seinfo) {
StringBuilder builder = new StringBuilder("mkuserdata");
builder.append(' ');
diff --git a/services/core/java/com/android/server/pm/KeySetHandle.java b/services/core/java/com/android/server/pm/KeySetHandle.java
new file mode 100644
index 0000000..640feb3
--- /dev/null
+++ b/services/core/java/com/android/server/pm/KeySetHandle.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 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.
+ */
+
+package com.android.server.pm;
+
+import android.os.Binder;
+
+public class KeySetHandle extends Binder {
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index c19951f..37bedf3 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -16,7 +16,6 @@
package com.android.server.pm;
-import android.content.pm.KeySet;
import android.content.pm.PackageParser;
import android.os.Binder;
import android.util.ArraySet;
@@ -52,7 +51,7 @@
/** Sentinel value returned when public key is not found. */
protected static final long PUBLIC_KEY_NOT_FOUND = -1;
- private final LongSparseArray<KeySet> mKeySets;
+ private final LongSparseArray<KeySetHandle> mKeySets;
private final LongSparseArray<PublicKey> mPublicKeys;
@@ -65,7 +64,7 @@
private static long lastIssuedKeyId = 0;
public KeySetManagerService(Map<String, PackageSetting> packages) {
- mKeySets = new LongSparseArray<KeySet>();
+ mKeySets = new LongSparseArray<KeySetHandle>();
mPublicKeys = new LongSparseArray<PublicKey>();
mKeySetMapping = new LongSparseArray<ArraySet<Long>>();
mPackages = packages;
@@ -82,7 +81,7 @@
*
* Note that this can return true for multiple KeySets.
*/
- public boolean packageIsSignedByLPr(String packageName, KeySet ks) {
+ public boolean packageIsSignedByLPr(String packageName, KeySetHandle ks) {
PackageSetting pkg = mPackages.get(packageName);
if (pkg == null) {
throw new NullPointerException("Invalid package name");
@@ -91,16 +90,42 @@
throw new NullPointerException("Package has no KeySet data");
}
long id = getIdByKeySetLPr(ks);
+ if (id == KEYSET_NOT_FOUND) {
+ return false;
+ }
return pkg.keySetData.packageIsSignedBy(id);
}
/**
+ * Determine if a package is signed by the given KeySet.
+ *
+ * Returns false if the package was not signed by all the
+ * keys in the KeySet, or if the package was signed by keys
+ * not in the KeySet.
+ *
+ * Note that this can return only for one KeySet.
+ */
+ public boolean packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks) {
+ PackageSetting pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ throw new NullPointerException("Invalid package name");
+ }
+ if (pkg.keySetData == null
+ || pkg.keySetData.getProperSigningKeySet()
+ == PackageKeySetData.KEYSET_UNASSIGNED) {
+ throw new NullPointerException("Package has no KeySet data");
+ }
+ long id = getIdByKeySetLPr(ks);
+ return pkg.keySetData.getProperSigningKeySet() == id;
+ }
+
+ /**
* This informs the system that the given package has defined a KeySet
* in its manifest that a) contains the given keys and b) is named
* alias by that package.
*/
public void addDefinedKeySetToPackageLPw(String packageName,
- Set<PublicKey> keys, String alias) {
+ ArraySet<PublicKey> keys, String alias) {
if ((packageName == null) || (keys == null) || (alias == null)) {
Slog.w(TAG, "Got null argument for a defined keyset, ignoring!");
return;
@@ -110,7 +135,7 @@
throw new NullPointerException("Unknown package");
}
// Add to KeySets, then to package
- KeySet ks = addKeySetLPw(keys);
+ KeySetHandle ks = addKeySetLPw(keys);
long id = getIdByKeySetLPr(ks);
pkg.keySetData.addDefinedKeySet(id, alias);
}
@@ -137,19 +162,18 @@
* was signed by the provided KeySet.
*/
public void addSigningKeySetToPackageLPw(String packageName,
- Set<PublicKey> signingKeys) {
+ ArraySet<PublicKey> signingKeys) {
if ((packageName == null) || (signingKeys == null)) {
Slog.w(TAG, "Got null argument for a signing keyset, ignoring!");
return;
}
// add the signing KeySet
- KeySet ks = addKeySetLPw(signingKeys);
+ KeySetHandle ks = addKeySetLPw(signingKeys);
long id = getIdByKeySetLPr(ks);
- Set<Long> publicKeyIds = mKeySetMapping.get(id);
+ ArraySet<Long> publicKeyIds = mKeySetMapping.get(id);
if (publicKeyIds == null) {
throw new NullPointerException("Got invalid KeySet id");
}
-
// attach it to the package
PackageSetting pkg = mPackages.get(packageName);
if (pkg == null) {
@@ -160,7 +184,7 @@
// KeySet id to the package's signing KeySets
for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
long keySetID = mKeySets.keyAt(keySetIndex);
- Set<Long> definedKeys = mKeySetMapping.get(keySetID);
+ ArraySet<Long> definedKeys = mKeySetMapping.get(keySetID);
if (publicKeyIds.containsAll(definedKeys)) {
pkg.keySetData.addSigningKeySet(keySetID);
}
@@ -171,9 +195,9 @@
* Fetches the stable identifier associated with the given KeySet. Returns
* {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found.
*/
- private long getIdByKeySetLPr(KeySet ks) {
+ private long getIdByKeySetLPr(KeySetHandle ks) {
for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
- KeySet value = mKeySets.valueAt(keySetIndex);
+ KeySetHandle value = mKeySets.valueAt(keySetIndex);
if (ks.equals(value)) {
return mKeySets.keyAt(keySetIndex);
}
@@ -187,25 +211,24 @@
* Returns {@link #KEYSET_NOT_FOUND} if the identifier doesn't
* identify a {@link KeySet}.
*/
- public KeySet getKeySetByIdLPr(long id) {
+ public KeySetHandle getKeySetByIdLPr(long id) {
return mKeySets.get(id);
}
/**
- * Fetches the {@link KeySet} that a given package refers to by the provided alias.
- *
- * @throws IllegalArgumentException if the package has no keyset data.
- * @throws NullPointerException if the package is unknown.
+ * Fetches the {@link KeySetHandle} that a given package refers to by the
+ * provided alias. Returns null if the package is unknown or does not have a
+ * KeySet corresponding to that alias.
*/
- public KeySet getKeySetByAliasAndPackageNameLPr(String packageName, String alias) {
+ public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) {
PackageSetting p = mPackages.get(packageName);
- if (p == null) {
- throw new NullPointerException("Unknown package");
+ if (p == null || p.keySetData == null) {
+ return null;
}
- if (p.keySetData == null) {
- throw new IllegalArgumentException("Package has no keySet data");
+ Long keySetId = p.keySetData.getAliases().get(alias);
+ if (keySetId == null) {
+ throw new IllegalArgumentException("Unknown KeySet alias: " + alias);
}
- long keySetId = p.keySetData.getAliases().get(alias);
return mKeySets.get(keySetId);
}
@@ -214,7 +237,7 @@
* KeySet id.
*
* Returns {@code null} if the identifier doesn't
- * identify a {@link KeySet}.
+ * identify a {@link KeySetHandle}.
*/
public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) {
if(mKeySetMapping.get(id) == null) {
@@ -228,36 +251,32 @@
}
/**
- * Fetches all the known {@link KeySet KeySets} that signed the given
+ * Fetches the proper {@link KeySetHandle KeySet} that signed the given
* package.
*
* @throws IllegalArgumentException if the package has no keyset data.
* @throws NullPointerException if the package is unknown.
*/
- public Set<KeySet> getSigningKeySetsByPackageNameLPr(String packageName) {
- Set<KeySet> signingKeySets = new ArraySet<KeySet>();
+ public KeySetHandle getSigningKeySetByPackageNameLPr(String packageName) {
PackageSetting p = mPackages.get(packageName);
- if (p == null) {
- throw new NullPointerException("Unknown package");
+ if (p == null
+ || p.keySetData == null
+ || p.keySetData.getProperSigningKeySet()
+ == PackageKeySetData.KEYSET_UNASSIGNED) {
+ return null;
}
- if (p.keySetData == null || p.keySetData.getSigningKeySets() == null) {
- throw new IllegalArgumentException("Package has no keySet data");
- }
- for (long l : p.keySetData.getSigningKeySets()) {
- signingKeySets.add(mKeySets.get(l));
- }
- return signingKeySets;
+ return mKeySets.get(p.keySetData.getProperSigningKeySet());
}
/**
- * Fetches all the known {@link KeySet KeySets} that may upgrade the given
+ * Fetches all the known {@link KeySetHandle KeySets} that may upgrade the given
* package.
*
* @throws IllegalArgumentException if the package has no keyset data.
* @throws NullPointerException if the package is unknown.
*/
- public ArraySet<KeySet> getUpgradeKeySetsByPackageNameLPr(String packageName) {
- ArraySet<KeySet> upgradeKeySets = new ArraySet<KeySet>();
+ public ArraySet<KeySetHandle> getUpgradeKeySetsByPackageNameLPr(String packageName) {
+ ArraySet<KeySetHandle> upgradeKeySets = new ArraySet<KeySetHandle>();
PackageSetting p = mPackages.get(packageName);
if (p == null) {
throw new NullPointerException("Unknown package");
@@ -287,7 +306,7 @@
*
* Throws if the provided set is {@code null}.
*/
- private KeySet addKeySetLPw(Set<PublicKey> keys) {
+ private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) {
if (keys == null) {
throw new NullPointerException("Provided keys cannot be null");
}
@@ -305,7 +324,7 @@
}
// create the KeySet object
- KeySet ks = new KeySet(new Binder());
+ KeySetHandle ks = new KeySetHandle();
// get the first unoccupied slot in mKeySets
long id = getFreeKeySetIDLPw();
// add the KeySet object to it
@@ -318,7 +337,7 @@
if (p.keySetData != null) {
long pProperSigning = p.keySetData.getProperSigningKeySet();
if (pProperSigning != PackageKeySetData.KEYSET_UNASSIGNED) {
- Set<Long> pSigningKeys = mKeySetMapping.get(pProperSigning);
+ ArraySet<Long> pSigningKeys = mKeySetMapping.get(pProperSigning);
if (pSigningKeys.containsAll(addedKeyIds)) {
p.keySetData.addSigningKeySet(id);
}
@@ -353,7 +372,7 @@
*/
private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) {
for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) {
- Set<Long> value = mKeySetMapping.valueAt(keyMapIndex);
+ ArraySet<Long> value = mKeySetMapping.valueAt(keyMapIndex);
if (value.equals(publicKeyIds)) {
return mKeySetMapping.keyAt(keyMapIndex);
}
@@ -582,7 +601,7 @@
serializer.startTag(null, "keysets");
for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) {
long id = mKeySetMapping.keyAt(keySetIndex);
- Set<Long> keys = mKeySetMapping.valueAt(keySetIndex);
+ ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex);
serializer.startTag(null, "keyset");
serializer.attribute(null, "identifier", Long.toString(id));
for (long keyId : keys) {
@@ -662,7 +681,7 @@
final String tagName = parser.getName();
if (tagName.equals("keyset")) {
currentKeySetId = readIdentifierLPw(parser);
- mKeySets.put(currentKeySetId, new KeySet(new Binder()));
+ mKeySets.put(currentKeySetId, new KeySetHandle());
mKeySetMapping.put(currentKeySetId, new ArraySet<Long>());
} else if (tagName.equals("key-id")) {
long id = readIdentifierLPw(parser);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 0eb922d..db915e2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -60,6 +60,7 @@
// TODO: destroy sessions with old timestamps
// TODO: remove outstanding sessions when installer package goes away
+ // TODO: notify listeners in other users when package has been installed there
private final Context mContext;
private final PackageManagerService mPm;
@@ -75,6 +76,10 @@
@GuardedBy("mSessions")
private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>();
+ /** Historical sessions kept around for debugging purposes */
+ @GuardedBy("mSessions")
+ private final SparseArray<PackageInstallerSession> mHistoricalSessions = new SparseArray<>();
+
private RemoteCallbackList<IPackageInstallerObserver> mObservers = new RemoteCallbackList<>();
private static final FilenameFilter sStageFilter = new FilenameFilter() {
@@ -167,6 +172,10 @@
params.installFlags |= INSTALL_REPLACE_EXISTING;
}
+ if (params.mode == InstallSessionParams.MODE_INVALID) {
+ throw new IllegalArgumentException("Params must have valid mode set");
+ }
+
// Sanity check that install could fit
if (params.deltaSize > 0) {
try {
@@ -339,18 +348,29 @@
}
void dump(IndentingPrintWriter pw) {
- pw.println("Active install sessions:");
- pw.increaseIndent();
synchronized (mSessions) {
- final int N = mSessions.size();
+ pw.println("Active install sessions:");
+ pw.increaseIndent();
+ int N = mSessions.size();
for (int i = 0; i < N; i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
session.dump(pw);
pw.println();
}
+ pw.println();
+ pw.decreaseIndent();
+
+ pw.println("Historical install sessions:");
+ pw.increaseIndent();
+ N = mHistoricalSessions.size();
+ for (int i = 0; i < N; i++) {
+ final PackageInstallerSession session = mHistoricalSessions.valueAt(i);
+ session.dump(pw);
+ pw.println();
+ }
+ pw.println();
+ pw.decreaseIndent();
}
- pw.println();
- pw.decreaseIndent();
}
class Callback {
@@ -362,6 +382,7 @@
notifySessionFinished(session.sessionId, success);
synchronized (mSessions) {
mSessions.remove(session.sessionId);
+ mHistoricalSessions.put(session.sessionId, session);
}
writeSessionsAsync();
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index c399fa2..0e6a3f0 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -65,6 +65,7 @@
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String TAG = "PackageInstaller";
+ private static final boolean LOGD = true;
// TODO: enforce INSTALL_ALLOW_TEST
// TODO: enforce INSTALL_ALLOW_DOWNGRADE
@@ -166,7 +167,7 @@
info.installerPackageName = installerPackageName;
info.progress = mProgress;
- info.fullInstall = params.fullInstall;
+ info.mode = params.mode;
info.packageName = params.packageName;
info.icon = params.icon;
info.title = params.title;
@@ -177,7 +178,8 @@
@Override
public void setClientProgress(int progress) {
mClientProgress = progress;
- mProgress = MathUtils.constrain((mClientProgress * 8 * 100) / (params.progressMax * 10), 0, 80);
+ mProgress = MathUtils.constrain(
+ (int) (((float) mClientProgress) / ((float) params.progressMax)) * 80, 0, 80);
mCallback.onSessionProgress(this, mProgress);
}
@@ -288,7 +290,7 @@
// Inherit any packages and native libraries from existing install that
// haven't been overridden.
- if (!params.fullInstall) {
+ if (params.mode == InstallSessionParams.MODE_INHERIT_EXISTING) {
spliceExistingFilesIntoStage();
}
@@ -382,7 +384,7 @@
// currently relying on PMS to do this.
// TODO: teach about compatible upgrade keysets.
- if (params.fullInstall) {
+ if (params.mode == InstallSessionParams.MODE_FULL_INSTALL) {
// Full installs must include a base package
if (!seenSplits.contains(null)) {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
@@ -434,35 +436,25 @@
*/
private void spliceExistingFilesIntoStage() throws PackageManagerException {
final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId);
- final File existingDir = new File(app.getBaseCodePath());
- try {
- linkTreeIgnoringExisting(existingDir, sessionStageDir);
- } catch (ErrnoException e) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- "Failed to splice into stage");
- }
- }
+ int n = 0;
+ final File[] oldFiles = new File(app.getCodePath()).listFiles();
+ if (!ArrayUtils.isEmpty(oldFiles)) {
+ for (File oldFile : oldFiles) {
+ if (!PackageParser.isApkFile(oldFile)) continue;
- /**
- * Recursively hard link all files from source directory tree to target.
- * When a file already exists in the target tree, it leaves that file
- * intact.
- */
- private void linkTreeIgnoringExisting(File sourceDir, File targetDir) throws ErrnoException {
- final File[] sourceContents = sourceDir.listFiles();
- if (ArrayUtils.isEmpty(sourceContents)) return;
-
- for (File sourceFile : sourceContents) {
- final File targetFile = new File(targetDir, sourceFile.getName());
-
- if (sourceFile.isDirectory()) {
- targetFile.mkdir();
- linkTreeIgnoringExisting(sourceFile, targetFile);
- } else {
- Libcore.os.link(sourceFile.getAbsolutePath(), targetFile.getAbsolutePath());
+ final File newFile = new File(sessionStageDir, oldFile.getName());
+ try {
+ Os.link(oldFile.getAbsolutePath(), newFile.getAbsolutePath());
+ n++;
+ } catch (ErrnoException e) {
+ throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+ "Failed to splice into stage", e);
+ }
}
}
+
+ if (LOGD) Slog.d(TAG, "Spliced " + n + " existing APKs into stage");
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 101ef92..727cff0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -26,7 +26,6 @@
import static android.content.pm.PackageManager.INSTALL_EXTERNAL;
import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
-import static android.content.pm.PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
import static android.content.pm.PackageManager.INSTALL_FAILED_DEXOPT;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
@@ -165,6 +164,7 @@
import android.util.AtomicFile;
import android.util.DisplayMetrics;
import android.util.EventLog;
+import android.util.ExceptionUtils;
import android.util.Log;
import android.util.LogPrinter;
import android.util.PrintStreamPrinter;
@@ -1713,7 +1713,7 @@
// NOTE: We ignore potential failures here during a system scan (like
// the rest of the commands above) because there's precious little we
// can do about it. A settings error is reported, though.
- adjustCpuAbisForSharedUserLPw(setting.packages, null,
+ adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
false /* force dexopt */, false /* defer dexopt */);
}
@@ -1751,6 +1751,16 @@
mSettings.readDefaultPreferredAppsLPw(this, 0);
}
+ // If this is first boot after an OTA, and a normal boot, then
+ // we need to clear code cache directories.
+ if (!Build.FINGERPRINT.equals(mSettings.mFingerprint) && !onlyCore) {
+ Slog.i(TAG, "Build fingerprint changed; clearing code caches");
+ for (String pkgName : mSettings.mPackages.keySet()) {
+ deleteCodeCacheDirsLI(pkgName);
+ }
+ mSettings.mFingerprint = Build.FINGERPRINT;
+ }
+
// All the changes are done during package scanning.
mSettings.updateInternalDatabaseVersion();
@@ -4531,24 +4541,29 @@
}
PackageParser.Package p = pkg;
synchronized (mInstallLock) {
- if (p.mDexOptNeeded) {
- performDexOptLI(p, false /* force dex */, false /* defer */,
- true /* include dependencies */);
- }
+ performDexOptLI(p, null /* instruction sets */, false /* force dex */, false /* defer */,
+ true /* include dependencies */);
}
}
}
}
@Override
- public boolean performDexOpt(String packageName) {
- enforceSystemOrRoot("Only the system can request dexopt be performed");
- return performDexOpt(packageName, true);
+ public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
+ return performDexOpt(packageName, instructionSet, true);
}
- public boolean performDexOpt(String packageName, boolean updateUsage) {
+ private static String getPrimaryInstructionSet(ApplicationInfo info) {
+ if (info.primaryCpuAbi == null) {
+ return getPreferredInstructionSet();
+ }
+ return VMRuntime.getInstructionSet(info.primaryCpuAbi);
+ }
+
+ public boolean performDexOpt(String packageName, String instructionSet, boolean updateUsage) {
PackageParser.Package p;
+ final String targetInstructionSet;
synchronized (mPackages) {
p = mPackages.get(packageName);
if (p == null) {
@@ -4558,13 +4573,17 @@
p.mLastPackageUsageTimeInMills = System.currentTimeMillis();
}
mPackageUsage.write(false);
- if (!p.mDexOptNeeded) {
+
+ targetInstructionSet = instructionSet != null ? instructionSet :
+ getPrimaryInstructionSet(p.applicationInfo);
+ if (p.mDexOptPerformed.contains(targetInstructionSet)) {
return false;
}
}
synchronized (mInstallLock) {
- return performDexOptLI(p, false /* force dex */, false /* defer */,
+ final String[] instructionSets = new String[] { targetInstructionSet };
+ return performDexOptLI(p, instructionSets, false /* force dex */, false /* defer */,
true /* include dependencies */) == DEX_OPT_PERFORMED;
}
}
@@ -4574,9 +4593,9 @@
synchronized (mPackages) {
for (PackageParser.Package p : mPackages.values()) {
if (DEBUG_DEXOPT) {
- Log.i(TAG, p.packageName + " mDexOptNeeded=" + p.mDexOptNeeded);
+ Log.i(TAG, p.packageName + " mDexOptPerformed=" + p.mDexOptPerformed.toArray());
}
- if (!p.mDexOptNeeded) {
+ if (!p.mDexOptPerformed.isEmpty()) {
continue;
}
if (pkgs == null) {
@@ -4636,7 +4655,7 @@
return DEX_OPT_SKIPPED;
}
- final Collection<String> paths = pkg.getAllCodePaths();
+ final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
boolean performedDexOpt = false;
// There are three basic cases here:
// 1.) we need to dexopt, either because we are forced or it is needed
@@ -4644,11 +4663,16 @@
// 3.) we are skipping an unneeded dexopt
for (String path : paths) {
for (String instructionSet : instructionSets) {
+ if (!forceDex && pkg.mDexOptPerformed.contains(instructionSet)) {
+ continue;
+ }
+
try {
final boolean isDexOptNeeded = DexFile.isDexOptNeededInternal(path,
pkg.packageName, instructionSet, defer);
if (forceDex || (!defer && isDexOptNeeded)) {
- Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName + " isa=" + instructionSet);
+ Log.i(TAG, "Running dexopt on: " + path + " pkg="
+ + pkg.applicationInfo.packageName + " isa=" + instructionSet);
final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
final int ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
pkg.packageName, instructionSet);
@@ -4657,10 +4681,10 @@
// Don't bother running dexopt again if we failed, it will probably
// just result in an error again. Also, don't bother dexopting for other
// paths & ISAs.
- pkg.mDexOptNeeded = false;
return DEX_OPT_FAILED;
} else {
performedDexOpt = true;
+ pkg.mDexOptPerformed.add(instructionSet);
}
}
@@ -4694,7 +4718,6 @@
// deferred dex-opt. We've either dex-opted one more paths or instruction sets or
// we've skipped all of them because they are up to date. In both cases this
// package doesn't need dexopt any longer.
- pkg.mDexOptNeeded = false;
return performedDexOpt ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
}
@@ -4750,8 +4773,8 @@
return allInstructionSets;
}
- private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
- boolean inclDependencies) {
+ private int performDexOptLI(PackageParser.Package pkg, String[] instructionSets,
+ boolean forceDex, boolean defer, boolean inclDependencies) {
HashSet<String> done;
if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
done = new HashSet<String>();
@@ -4759,7 +4782,7 @@
} else {
done = null;
}
- return performDexOptLI(pkg, null /* target instruction sets */, forceDex, defer, done);
+ return performDexOptLI(pkg, instructionSets, forceDex, defer, done);
}
private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
@@ -4826,6 +4849,18 @@
return res;
}
+ private int deleteCodeCacheDirsLI(String packageName) {
+ int[] users = sUserManager.getUserIds();
+ int res = 0;
+ for (int user : users) {
+ int resInner = mInstaller.deleteCodeCacheFiles(packageName, user);
+ if (resInner < 0) {
+ res = resInner;
+ }
+ }
+ return res;
+ }
+
private void addSharedLibraryLPw(ArraySet<String> usesLibraryFiles, SharedLibraryEntry file,
PackageParser.Package changingLib) {
if (file.path != null) {
@@ -5428,11 +5463,8 @@
}
}
- if (abi32 < 0 && abi32 != PackageManager.NO_NATIVE_LIBRARIES) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- "Error unpackaging 32 bit native libs for multiarch app, errorCode="
- + abi32);
- }
+ maybeThrowExceptionForMultiArchCopy(
+ "Error unpackaging 32 bit native libs for multiarch app.", abi32);
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
if (isAsec) {
@@ -5443,11 +5475,8 @@
}
}
- if (abi64 < 0 && abi64 != PackageManager.NO_NATIVE_LIBRARIES) {
- throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
- "Error unpackaging 64 bit native libs for multiarch app, errorCode="
- + abi32);
- }
+ maybeThrowExceptionForMultiArchCopy(
+ "Error unpackaging 64 bit native libs for multiarch app.", abi64);
if (abi64 >= 0) {
pkg.applicationInfo.primaryCpuAbi = Build.SUPPORTED_64_BIT_ABIS[abi64];
@@ -5489,6 +5518,8 @@
if (copyRet >= 0) {
pkg.applicationInfo.primaryCpuAbi = abiList[copyRet];
+ } else if (copyRet == PackageManager.NO_NATIVE_LIBRARIES && abiOverride != null) {
+ pkg.applicationInfo.primaryCpuAbi = abiOverride;
}
}
} catch (IOException ioe) {
@@ -5544,15 +5575,12 @@
// We also do this *before* we perform dexopt on this package, so that
// we can avoid redundant dexopts, and also to make sure we've got the
// code and package path correct.
- if (!adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
- pkg, forceDex, (scanMode & SCAN_DEFER_DEX) != 0)) {
- throw new PackageManagerException(INSTALL_FAILED_CPU_ABI_INCOMPATIBLE,
- "scanPackageLI");
- }
+ adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
+ pkg, forceDex, (scanMode & SCAN_DEFER_DEX) != 0);
}
if ((scanMode&SCAN_NO_DEX) == 0) {
- if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
+ if (performDexOptLI(pkg, null /* instruction sets */, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
== DEX_OPT_FAILED) {
if ((scanMode & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
removeDataDirsLI(pkg.packageName);
@@ -5631,7 +5659,8 @@
if ((scanMode&SCAN_NO_DEX) == 0) {
for (int i=0; i<clientLibPkgs.size(); i++) {
PackageParser.Package clientPkg = clientLibPkgs.get(i);
- if (performDexOptLI(clientPkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
+ if (performDexOptLI(clientPkg, null /* instruction sets */,
+ forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
== DEX_OPT_FAILED) {
if ((scanMode & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
removeDataDirsLI(pkg.packageName);
@@ -6047,7 +6076,7 @@
* NOTE: We currently only match for the primary CPU abi string. Matching the secondary
* adds unnecessary complexity.
*/
- private boolean adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
+ private void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
PackageParser.Package scannedPackage, boolean forceDexOpt, boolean deferDexOpt) {
String requiredInstructionSet = null;
if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) {
@@ -6061,27 +6090,23 @@
// when scannedPackage is an update of an existing package. Without this check,
// we will never be able to change the ABI of any package belonging to a shared
// user, even if it's compatible with other packages.
- if (scannedPackage == null || ! scannedPackage.packageName.equals(ps.name)) {
+ if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) {
if (ps.primaryCpuAbiString == null) {
continue;
}
final String instructionSet = VMRuntime.getInstructionSet(ps.primaryCpuAbiString);
- if (requiredInstructionSet != null) {
- if (!instructionSet.equals(requiredInstructionSet)) {
- // We have a mismatch between instruction sets (say arm vs arm64).
- // bail out.
- String errorMessage = "Instruction set mismatch, "
- + ((requirer == null) ? "[caller]" : requirer)
- + " requires " + requiredInstructionSet + " whereas " + ps
- + " requires " + instructionSet;
- Slog.e(TAG, errorMessage);
+ if (requiredInstructionSet != null && !instructionSet.equals(requiredInstructionSet)) {
+ // We have a mismatch between instruction sets (say arm vs arm64) warn about
+ // this but there's not much we can do.
+ String errorMessage = "Instruction set mismatch, "
+ + ((requirer == null) ? "[caller]" : requirer)
+ + " requires " + requiredInstructionSet + " whereas " + ps
+ + " requires " + instructionSet;
+ Slog.w(TAG, errorMessage);
+ }
- reportSettingsProblem(Log.WARN, errorMessage);
- // Give up, don't bother making any other changes to the package settings.
- return false;
- }
- } else {
+ if (requiredInstructionSet == null) {
requiredInstructionSet = instructionSet;
requirer = ps;
}
@@ -6115,10 +6140,11 @@
ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + adjustedAbi);
- if (performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true) == DEX_OPT_FAILED) {
+ if (performDexOptLI(ps.pkg, null /* instruction sets */, forceDexOpt,
+ deferDexOpt, true) == DEX_OPT_FAILED) {
ps.primaryCpuAbiString = null;
ps.pkg.applicationInfo.primaryCpuAbi = null;
- return false;
+ return;
} else {
mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
}
@@ -6126,8 +6152,6 @@
}
}
}
-
- return true;
}
private void setUpCustomResolverActivity(PackageParser.Package pkg) {
@@ -6194,13 +6218,18 @@
final ApplicationInfo info = pkg.applicationInfo;
final String codePath = pkg.codePath;
final File codeFile = new File(codePath);
+ // If "/system/lib64/apkname" exists, assume that is the per-package
+ // native library directory to use; otherwise use "/system/lib/apkname".
+ final String apkRoot = calculateApkRoot(info.sourceDir);
final boolean bundledApp = isSystemApp(info) && !isUpdatedSystemApp(info);
final boolean asecApp = isForwardLocked(info) || isExternal(info);
+
info.nativeLibraryRootDir = null;
info.nativeLibraryRootRequiresIsa = false;
info.nativeLibraryDir = null;
+ info.secondaryNativeLibraryDir = null;
if (bundledApp) {
// Monolithic bundled install
@@ -6214,38 +6243,43 @@
// is just the default path.
final String apkName = deriveCodePathName(codePath);
final String libDir = is64Bit ? LIB64_DIR_NAME : LIB_DIR_NAME;
- info.nativeLibraryRootDir = Environment.buildPath(new File(info.apkRoot), libDir,
+ info.nativeLibraryRootDir = Environment.buildPath(new File(apkRoot), libDir,
apkName).getAbsolutePath();
info.nativeLibraryRootRequiresIsa = false;
+ info.nativeLibraryDir = info.nativeLibraryRootDir;
+ if (info.secondaryCpuAbi != null) {
+ final String secondaryLibDir = is64Bit ? LIB_DIR_NAME : LIB64_DIR_NAME;
+ info.secondaryNativeLibraryDir = Environment.buildPath(new File(apkRoot),
+ secondaryLibDir, apkName).getAbsolutePath();
+ }
} else if (isApkFile(codeFile)) {
// Monolithic install
if (asecApp) {
info.nativeLibraryRootDir = new File(codeFile.getParentFile(), LIB_DIR_NAME)
.getAbsolutePath();
- info.nativeLibraryRootRequiresIsa = false;
} else {
final String apkName = deriveCodePathName(codePath);
info.nativeLibraryRootDir = new File(mAppLib32InstallDir, apkName)
.getAbsolutePath();
- info.nativeLibraryRootRequiresIsa = false;
}
+
+ info.nativeLibraryRootRequiresIsa = false;
+ info.nativeLibraryDir = info.nativeLibraryRootDir;
} else {
// Cluster install
info.nativeLibraryRootDir = new File(codeFile, LIB_DIR_NAME).getAbsolutePath();
info.nativeLibraryRootRequiresIsa = true;
- }
- if (info.nativeLibraryRootRequiresIsa) {
if (info.primaryCpuAbi != null) {
info.nativeLibraryDir = new File(info.nativeLibraryRootDir,
VMRuntime.getInstructionSet(info.primaryCpuAbi)).getAbsolutePath();
- } else {
- Slog.w(TAG, "Package " + info.packageName
- + " missing ABI; unable to derive nativeLibraryDir");
}
- } else {
- info.nativeLibraryDir = info.nativeLibraryRootDir;
+
+ if (info.secondaryCpuAbi != null) {
+ info.secondaryNativeLibraryDir = new File(info.nativeLibraryRootDir,
+ VMRuntime.getInstructionSet(info.secondaryCpuAbi)).getAbsolutePath();
+ }
}
}
@@ -6263,7 +6297,6 @@
// If "/system/lib64/apkname" exists, assume that is the per-package
// native library directory to use; otherwise use "/system/lib/apkname".
final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir);
- pkg.applicationInfo.apkRoot = apkRoot;
setBundledAppAbi(pkg, apkRoot, apkName);
// pkgSetting might be null during rescan following uninstall of updates
// to a bundled app, so accommodate that possibility. The settings in
@@ -9264,29 +9297,13 @@
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot,
Build.SUPPORTED_32_BIT_ABIS, true /* use isa specific subdirs */);
- if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
- Slog.w(TAG, "Failure copying 32 bit native libraries [errorCode=" + copyRet + "]");
- return copyRet;
- }
- }
-
- if (DEBUG_ABI_SELECTION && copyRet >= 0) {
- Log.d(TAG, "Installed 32 bit libraries under: " + codeFile + " abi=" +
- Build.SUPPORTED_32_BIT_ABIS[copyRet]);
+ maybeThrowExceptionForMultiArchCopy("Failure copying 32 bit native libraries", copyRet);
}
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
copyRet = copyNativeLibrariesForInternalApp(handle, libraryRoot,
Build.SUPPORTED_64_BIT_ABIS, true /* use isa specific subdirs */);
- if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
- Slog.w(TAG, "Failure copying 64 bit native libraries [errorCode=" + copyRet + "]");
- return copyRet;
- }
- }
-
- if (DEBUG_ABI_SELECTION && copyRet >= 0) {
- Log.d(TAG, "Installed 64 bit libraries under: " + codeFile + " abi=" +
- Build.SUPPORTED_64_BIT_ABIS[copyRet]);
+ maybeThrowExceptionForMultiArchCopy("Failure copying 64 bit native libraries", copyRet);
}
} else {
String[] abiList = (abiOverride != null) ?
@@ -9303,14 +9320,13 @@
Slog.w(TAG, "Failure copying native libraries [errorCode=" + copyRet + "]");
return copyRet;
}
-
- if (DEBUG_ABI_SELECTION && copyRet >= 0) {
- Log.d(TAG, "Installed libraries under: " + codeFile + " abi=" + abiList[copyRet]);
- }
}
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ } catch (PackageManagerException pme) {
+ Slog.e(TAG, "Copying native libraries failed", pme);
+ ret = pme.error;
} finally {
IoUtils.closeQuietly(handle);
}
@@ -9331,14 +9347,18 @@
return false;
} else {
final File beforeCodeFile = codeFile;
- final File afterCodeFile = new File(mAppInstallDir,
- getNextCodePath(oldCodePath, pkg.packageName, null));
+ final File afterCodeFile = getNextCodePath(pkg.packageName);
Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
- if (!beforeCodeFile.renameTo(afterCodeFile)) {
+ try {
+ Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
+ } catch (ErrnoException e) {
+ Slog.d(TAG, "Failed to rename", e);
return false;
}
+
if (!SELinux.restoreconRecursive(afterCodeFile)) {
+ Slog.d(TAG, "Failed to restorecon");
return false;
}
@@ -9455,6 +9475,16 @@
return !asecPath.startsWith(mAsecInternalPath);
}
+ private static void maybeThrowExceptionForMultiArchCopy(String message, int copyRet) throws
+ PackageManagerException {
+ if (copyRet < 0) {
+ if (copyRet != PackageManager.NO_NATIVE_LIBRARIES &&
+ copyRet != PackageManager.INSTALL_FAILED_NO_MATCHING_ABIS) {
+ throw new PackageManagerException(copyRet, message);
+ }
+ }
+ }
+
/**
* Extract the MountService "container ID" from the full code path of an
* .apk.
@@ -9811,6 +9841,16 @@
return prefix + idxStr;
}
+ private File getNextCodePath(String packageName) {
+ int suffix = 1;
+ File result;
+ do {
+ result = new File(mAppInstallDir, packageName + "-" + suffix);
+ suffix++;
+ } while (result.exists());
+ return result;
+ }
+
// Utility method used to ignore ADD/REMOVE events
// by directory observer.
private static boolean ignoreCodePath(String fullPathStr) {
@@ -9865,6 +9905,18 @@
Slog.w(TAG, msg);
}
+ public void setError(String msg, PackageParserException e) {
+ returnCode = e.error;
+ returnMsg = ExceptionUtils.getCompleteMessage(msg, e);
+ Slog.w(TAG, msg, e);
+ }
+
+ public void setError(String msg, PackageManagerException e) {
+ returnCode = e.error;
+ returnMsg = ExceptionUtils.getCompleteMessage(msg, e);
+ Slog.w(TAG, msg, e);
+ }
+
// In some error cases we want to convey more info back to the observer
String origPackage;
String origPermission;
@@ -9918,8 +9970,7 @@
}
} catch (PackageManagerException e) {
- res.setError(e.error,
- "Package couldn't be installed in " + pkg.codePath + ": " + e.getMessage());
+ res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
}
@@ -9974,6 +10025,7 @@
perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
}
}
+
boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
@@ -10011,14 +10063,14 @@
deletedPkg = false;
} else {
// Successfully deleted the old package. Now proceed with re-installation
+ deleteCodeCacheDirsLI(pkgName);
try {
final PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags,
scanMode | SCAN_UPDATE_TIME, System.currentTimeMillis(), user, abiOverride);
updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
updatedSettings = true;
} catch (PackageManagerException e) {
- res.setError(e.error,
- "Package couldn't be installed in " + pkg.codePath + ": " + e.getMessage());
+ res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
}
@@ -10121,8 +10173,10 @@
res.removedInfo.args = null;
}
}
-
+
// Successfully disabled the old package. Now proceed with re-installation
+ deleteCodeCacheDirsLI(packageName);
+
res.returnCode = PackageManager.INSTALL_SUCCEEDED;
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
@@ -10149,8 +10203,7 @@
}
} catch (PackageManagerException e) {
- res.setError(e.error,
- "Package couldn't be installed in " + pkg.codePath + ": " + e.getMessage());
+ res.setError("Package couldn't be installed in " + pkg.codePath, e);
}
if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
@@ -10195,7 +10248,7 @@
* remove the target to make sure there isn't a stale
* file from a previous version of the package.
*/
- newPackage.mDexOptNeeded = true;
+ newPackage.mDexOptPerformed.clear();
mInstaller.rmdex(oldCodePath, instructionSet);
mInstaller.rmdex(newPackage.baseCodePath, instructionSet);
}
@@ -10288,7 +10341,7 @@
try {
pkg = pp.parsePackage(tmpPackageFile, parseFlags);
} catch (PackageParserException e) {
- res.setError(e.error, "Failed parse during installPackageLI: " + e.getMessage());
+ res.setError("Failed parse during installPackageLI", e);
return;
}
@@ -10304,7 +10357,7 @@
pp.collectCertificates(pkg, parseFlags);
pp.collectManifestDigest(pkg);
} catch (PackageParserException e) {
- res.setError(e.error, "Failed collect during installPackageLI: " + e.getMessage());
+ res.setError("Failed collect during installPackageLI", e);
return;
}
@@ -13255,4 +13308,83 @@
}
return mUserNeedsBadging.valueAt(index);
}
+
+ @Override
+ public KeySetHandle getKeySetByAlias(String packageName, String alias) {
+ if (packageName == null || alias == null) {
+ return null;
+ }
+ synchronized(mPackages) {
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ Slog.w(TAG, "KeySet requested for unknown package:" + packageName);
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+ if (pkg.applicationInfo.uid != Binder.getCallingUid()
+ && Process.SYSTEM_UID != Binder.getCallingUid()) {
+ throw new SecurityException("May not access KeySets defined by"
+ + " aliases in other applications.");
+ }
+ KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ return ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias);
+ }
+ }
+
+ @Override
+ public KeySetHandle getSigningKeySet(String packageName) {
+ if (packageName == null) {
+ return null;
+ }
+ synchronized(mPackages) {
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ Slog.w(TAG, "KeySet requested for unknown package:" + packageName);
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+ if (pkg.applicationInfo.uid != Binder.getCallingUid()
+ && Process.SYSTEM_UID != Binder.getCallingUid()) {
+ throw new SecurityException("May not access signing KeySet of other apps.");
+ }
+ KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ return ksms.getSigningKeySetByPackageNameLPr(packageName);
+ }
+ }
+
+ @Override
+ public boolean isPackageSignedByKeySet(String packageName, IBinder ks) {
+ if (packageName == null || ks == null) {
+ return false;
+ }
+ synchronized(mPackages) {
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ Slog.w(TAG, "KeySet requested for unknown package:" + packageName);
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+ if (ks instanceof KeySetHandle) {
+ KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ return ksms.packageIsSignedByLPr(packageName, (KeySetHandle) ks);
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isPackageSignedByKeySetExactly(String packageName, IBinder ks) {
+ if (packageName == null || ks == null) {
+ return false;
+ }
+ synchronized(mPackages) {
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ Slog.w(TAG, "KeySet requested for unknown package:" + packageName);
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+ if (ks instanceof KeySetHandle) {
+ KeySetManagerService ksms = mSettings.mKeySetManagerService;
+ return ksms.packageIsSignedByExactlyLPr(packageName, (KeySetHandle) ks);
+ }
+ return false;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 40561ba..a3fd1df 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -30,6 +30,7 @@
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Environment;
import android.os.FileUtils;
import android.os.PatternMatcher;
@@ -184,6 +185,12 @@
int mInternalDatabaseVersion;
int mExternalDatabaseVersion;
+ /**
+ * Last known value of {@link Build#FINGERPRINT}. Used to determine when an
+ * system update has occurred, meaning we need to clear code caches.
+ */
+ String mFingerprint;
+
Boolean mReadExternalStorageEnforced;
/** Device identity for the purpose of package verification. */
@@ -1664,6 +1671,7 @@
serializer.startTag(null, "last-platform-version");
serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
+ serializer.attribute(null, "fingerprint", mFingerprint);
serializer.endTag(null, "last-platform-version");
serializer.startTag(null, "database-version");
@@ -2089,6 +2097,7 @@
PackageManagerService.reportSettingsProblem(Log.INFO,
"No settings file; creating initial state");
mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion;
+ mFingerprint = Build.FINGERPRINT;
return false;
}
str = new FileInputStream(mSettingsFilename);
@@ -2181,6 +2190,7 @@
}
} catch (NumberFormatException e) {
}
+ mFingerprint = parser.getAttributeValue(null, "fingerprint");
} else if (tagName.equals("database-version")) {
mInternalDatabaseVersion = mExternalDatabaseVersion = 0;
try {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a69dd30..cb4d339 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -58,6 +58,8 @@
import android.os.SystemService;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.os.Parcel;
+import android.os.ServiceManager;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
import android.util.EventLog;
@@ -659,6 +661,7 @@
if (mLowPowerModeEnabled != lowPowerModeEnabled) {
mLowPowerModeEnabled = lowPowerModeEnabled;
powerHintInternal(POWER_HINT_LOW_POWER_MODE, lowPowerModeEnabled ? 1 : 0);
+ setSurfaceFlingerLowPowerMode(lowPowerModeEnabled ? 1 : 0);
mLowPowerModeEnabled = lowPowerModeEnabled;
BackgroundThread.getHandler().post(new Runnable() {
@Override
@@ -695,6 +698,7 @@
WakeLock wakeLock;
int index = findWakeLockIndexLocked(lock);
+ boolean notifyAcquire;
if (index >= 0) {
wakeLock = mWakeLocks.get(index);
if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
@@ -703,6 +707,7 @@
uid, pid, ws, historyTag);
wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
}
+ notifyAcquire = false;
} else {
wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);
try {
@@ -710,13 +715,21 @@
} catch (RemoteException ex) {
throw new IllegalArgumentException("Wake lock is already dead.");
}
- notifyWakeLockAcquiredLocked(wakeLock);
mWakeLocks.add(wakeLock);
+ notifyAcquire = true;
}
applyWakeLockFlagsOnAcquireLocked(wakeLock);
mDirty |= DIRTY_WAKE_LOCKS;
updatePowerStateLocked();
+ if (notifyAcquire) {
+ // This needs to be done last so we are sure we have acquired the
+ // kernel wake lock. Otherwise we have a race where the system may
+ // go to sleep between the time we start the accounting in battery
+ // stats and when we actually get around to telling the kernel to
+ // stay awake.
+ notifyWakeLockAcquiredLocked(wakeLock);
+ }
}
}
@@ -2094,6 +2107,21 @@
nativeSendPowerHint(hintId, data);
}
+ private static void setSurfaceFlingerLowPowerMode(int enabled) {
+ try {
+ final IBinder flinger = ServiceManager.getService("SurfaceFlinger");
+ if (flinger != null) {
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ data.writeInt(enabled);
+ flinger.transact(1016, data, null, 0);
+ data.recycle();
+ }
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to reduce refresh rate", ex);
+ }
+ }
+
/**
* Low-level function turn the device off immediately, without trying
* to be clean. Most people should use {@link ShutdownThread} for a clean shutdown.
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index efe543b..8f237db 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -16,7 +16,12 @@
package com.android.server.tv;
+import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
+import static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED;
+
import android.content.Context;
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiHotplugEvent;
import android.media.AudioDevicePort;
import android.media.AudioManager;
import android.media.AudioPatch;
@@ -25,14 +30,22 @@
import android.media.tv.ITvInputHardware;
import android.media.tv.ITvInputHardwareCallback;
import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvInputInfo;
import android.media.tv.TvStreamConfig;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.view.KeyEvent;
import android.view.Surface;
+import com.android.server.SystemService;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -46,23 +59,42 @@
*
* @hide
*/
-class TvInputHardwareManager implements TvInputHal.Callback {
+class TvInputHardwareManager
+ implements TvInputHal.Callback, HdmiControlManager.HotplugEventListener {
private static final String TAG = TvInputHardwareManager.class.getSimpleName();
private final TvInputHal mHal = new TvInputHal(this);
private final SparseArray<Connection> mConnections = new SparseArray<Connection>();
private final List<TvInputHardwareInfo> mInfoList = new ArrayList<TvInputHardwareInfo>();
private final Context mContext;
+ private final TvInputManagerService.Client mClient;
private final Set<Integer> mActiveHdmiSources = new HashSet<Integer>();
private final AudioManager mAudioManager;
+ private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray();
+ // TODO: Should handle INACTIVE case.
+ private final SparseArray<TvInputInfo> mTvInputInfoMap = new SparseArray<TvInputInfo>();
+
+ // Calls to mClient should happen here.
+ private final HandlerThread mHandlerThread = new HandlerThread(TAG);
+ private final Handler mHandler;
private final Object mLock = new Object();
- public TvInputHardwareManager(Context context) {
+ public TvInputHardwareManager(Context context, TvInputManagerService.Client client) {
mContext = context;
+ mClient = client;
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- // TODO(hdmi): mHdmiManager = mContext.getSystemService(...);
- // TODO(hdmi): mHdmiClient = mHdmiManager.getTvClient();
mHal.init();
+
+ mHandlerThread.start();
+ mHandler = new ClientHandler(mHandlerThread.getLooper());
+ }
+
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ HdmiControlManager hdmiControlManager =
+ (HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE);
+ hdmiControlManager.addHotplugEventListener(this);
+ }
}
@Override
@@ -80,7 +112,7 @@
private void buildInfoListLocked() {
mInfoList.clear();
for (int i = 0; i < mConnections.size(); ++i) {
- mInfoList.add(mConnections.valueAt(i).getInfoLocked());
+ mInfoList.add(mConnections.valueAt(i).getHardwareInfoLocked());
}
}
@@ -92,7 +124,7 @@
Slog.e(TAG, "onDeviceUnavailable: Cannot find a connection with " + deviceId);
return;
}
- connection.resetLocked(null, null, null, null);
+ connection.resetLocked(null, null, null, null, null);
mConnections.remove(deviceId);
buildInfoListLocked();
// TODO: notify if necessary
@@ -136,6 +168,37 @@
return false;
}
+ private int convertConnectedToState(boolean connected) {
+ if (connected) {
+ return INPUT_STATE_CONNECTED;
+ } else {
+ return INPUT_STATE_DISCONNECTED;
+ }
+ }
+
+ public void registerTvInputInfo(TvInputInfo info, int deviceId) {
+ if (info.getType() == TvInputInfo.TYPE_VIRTUAL) {
+ throw new IllegalArgumentException("info (" + info + ") has virtual type.");
+ }
+ synchronized (mLock) {
+ if (mTvInputInfoMap.indexOfKey(deviceId) >= 0) {
+ Slog.w(TAG, "Trying to override previous registration: old = "
+ + mTvInputInfoMap.get(deviceId) + ":" + deviceId + ", new = "
+ + info + ":" + deviceId);
+ }
+ mTvInputInfoMap.put(deviceId, info);
+
+ for (int i = 0; i < mHdmiStateMap.size(); ++i) {
+ String inputId = findInputIdForHdmiPortLocked(mHdmiStateMap.keyAt(i));
+ if (inputId != null && inputId.equals(info.getId())) {
+ mHandler.obtainMessage(ClientHandler.DO_SET_AVAILABLE,
+ convertConnectedToState(mHdmiStateMap.valueAt(i)), 0,
+ inputId).sendToTarget();
+ }
+ }
+ }
+ }
+
/**
* Create a TvInputHardware object with a specific deviceId. One service at a time can access
* the object, and if more than one process attempts to create hardware with the same deviceId,
@@ -143,7 +206,7 @@
* release is notified via ITvInputHardwareCallback.onReleased().
*/
public ITvInputHardware acquireHardware(int deviceId, ITvInputHardwareCallback callback,
- int callingUid, int resolvedUserId) {
+ TvInputInfo info, int callingUid, int resolvedUserId) {
if (callback == null) {
throw new NullPointerException();
}
@@ -154,14 +217,15 @@
return null;
}
if (checkUidChangedLocked(connection, callingUid, resolvedUserId)) {
- TvInputHardwareImpl hardware = new TvInputHardwareImpl(connection.getInfoLocked());
+ TvInputHardwareImpl hardware =
+ new TvInputHardwareImpl(connection.getHardwareInfoLocked());
try {
callback.asBinder().linkToDeath(connection, 0);
} catch (RemoteException e) {
hardware.release();
return null;
}
- connection.resetLocked(hardware, callback, callingUid, resolvedUserId);
+ connection.resetLocked(hardware, callback, info, callingUid, resolvedUserId);
}
return connection.getHardwareLocked();
}
@@ -182,26 +246,55 @@
|| checkUidChangedLocked(connection, callingUid, resolvedUserId)) {
return;
}
- connection.resetLocked(null, null, null, null);
+ connection.resetLocked(null, null, null, null, null);
+ }
+ }
+
+ private String findInputIdForHdmiPortLocked(int port) {
+ for (TvInputHardwareInfo hardwareInfo : mInfoList) {
+ if (hardwareInfo.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI
+ && hardwareInfo.getHdmiPortId() == port) {
+ TvInputInfo info = mTvInputInfoMap.get(hardwareInfo.getDeviceId());
+ return (info == null) ? null : info.getId();
+ }
+ }
+ return null;
+ }
+
+ // HdmiControlManager.HotplugEventListener implementation.
+
+ @Override
+ public void onReceived(HdmiHotplugEvent event) {
+ String inputId = null;
+
+ synchronized (mLock) {
+ mHdmiStateMap.put(event.getPort(), event.isConnected());
+ inputId = findInputIdForHdmiPortLocked(event.getPort());
+ if (inputId == null) {
+ return;
+ }
+ mHandler.obtainMessage(ClientHandler.DO_SET_AVAILABLE,
+ convertConnectedToState(event.isConnected()), 0, inputId).sendToTarget();
}
}
private class Connection implements IBinder.DeathRecipient {
- private final TvInputHardwareInfo mInfo;
+ private final TvInputHardwareInfo mHardwareInfo;
+ private TvInputInfo mInfo;
private TvInputHardwareImpl mHardware = null;
private ITvInputHardwareCallback mCallback;
private TvStreamConfig[] mConfigs = null;
private Integer mCallingUid = null;
private Integer mResolvedUserId = null;
- public Connection(TvInputHardwareInfo info) {
- mInfo = info;
+ public Connection(TvInputHardwareInfo hardwareInfo) {
+ mHardwareInfo = hardwareInfo;
}
// *Locked methods assume TvInputHardwareManager.mLock is held.
- public void resetLocked(TvInputHardwareImpl hardware,
- ITvInputHardwareCallback callback, Integer callingUid, Integer resolvedUserId) {
+ public void resetLocked(TvInputHardwareImpl hardware, ITvInputHardwareCallback callback,
+ TvInputInfo info, Integer callingUid, Integer resolvedUserId) {
if (mHardware != null) {
try {
mCallback.onReleased();
@@ -212,6 +305,7 @@
}
mHardware = hardware;
mCallback = callback;
+ mInfo = info;
mCallingUid = callingUid;
mResolvedUserId = resolvedUserId;
@@ -228,7 +322,11 @@
mConfigs = configs;
}
- public TvInputHardwareInfo getInfoLocked() {
+ public TvInputHardwareInfo getHardwareInfoLocked() {
+ return mHardwareInfo;
+ }
+
+ public TvInputInfo getInfoLocked() {
return mInfo;
}
@@ -255,7 +353,7 @@
@Override
public void binderDied() {
synchronized (mLock) {
- resetLocked(null, null, null, null);
+ resetLocked(null, null, null, null, null);
}
}
}
@@ -403,4 +501,28 @@
return false;
}
}
+
+ private class ClientHandler extends Handler {
+ private static final int DO_SET_AVAILABLE = 1;
+
+ ClientHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public final void handleMessage(Message msg) {
+ switch (msg.what) {
+ case DO_SET_AVAILABLE: {
+ String inputId = (String) msg.obj;
+ int state = msg.arg1;
+ mClient.setState(inputId, state);
+ break;
+ }
+ default: {
+ Slog.w(TAG, "Unhandled message: " + msg);
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index fac78a9..20fdefa 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -16,6 +16,9 @@
package com.android.server.tv;
+import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
+import static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED;
+
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -38,6 +41,7 @@
import android.media.tv.ITvInputHardware;
import android.media.tv.ITvInputHardwareCallback;
import android.media.tv.ITvInputManager;
+import android.media.tv.ITvInputManagerCallback;
import android.media.tv.ITvInputService;
import android.media.tv.ITvInputServiceCallback;
import android.media.tv.ITvInputSession;
@@ -109,7 +113,7 @@
mContentResolver = context.getContentResolver();
mLogHandler = new LogHandler(IoThread.get().getLooper());
- mTvInputHardwareManager = new TvInputHardwareManager(context);
+ mTvInputHardwareManager = new TvInputHardwareManager(context, new Client());
synchronized (mLock) {
mUserStates.put(mCurrentUserId, new UserState());
@@ -129,6 +133,7 @@
buildTvInputListLocked(mCurrentUserId);
}
}
+ mTvInputHardwareManager.onBootPhase(phase);
}
private void registerBroadcastReceivers() {
@@ -144,7 +149,7 @@
public void onPackageRemoved(String packageName, int uid) {
synchronized (mLock) {
UserState userState = getUserStateLocked(mCurrentUserId);
- if (!userState.packageList.contains(packageName)) {
+ if (!userState.packageSet.contains(packageName)) {
// Not a TV input package.
return;
}
@@ -198,8 +203,11 @@
private void buildTvInputListLocked(int userId) {
UserState userState = getUserStateLocked(userId);
- userState.inputMap.clear();
- userState.packageList.clear();
+
+ Map<String, TvInputState> oldInputMap = userState.inputMap;
+ userState.inputMap = new HashMap<String, TvInputState>();
+
+ userState.packageSet.clear();
if (DEBUG) Slog.d(TAG, "buildTvInputList");
PackageManager pm = mContext.getPackageManager();
@@ -216,8 +224,13 @@
try {
TvInputInfo info = TvInputInfo.createTvInputInfo(mContext, ri);
if (DEBUG) Slog.d(TAG, "add " + info.getId());
- userState.inputMap.put(info.getId(), info);
- userState.packageList.add(si.packageName);
+ TvInputState state = oldInputMap.get(info.getId());
+ if (state == null) {
+ state = new TvInputState();
+ }
+ userState.inputMap.put(info.getId(), state);
+ state.mInfo = info;
+ userState.packageSet.add(si.packageName);
// Reconnect the service if existing input is updated.
updateServiceConnectionLocked(info.getId(), userId);
@@ -225,6 +238,7 @@
Slog.e(TAG, "Can't load TV input " + si.name, e);
}
}
+ oldInputMap.clear();
}
private void switchUser(int userId) {
@@ -359,7 +373,7 @@
}
Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(
- userState.inputMap.get(inputId).getComponent());
+ userState.inputMap.get(inputId).mInfo.getComponent());
// Binding service may fail if the service is updating.
// In that case, the connection will be revived in buildTvInputListLocked called by
// onSomePackagesChanged.
@@ -472,6 +486,40 @@
}
@Override
+ public void onVideoAvailable() {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "onVideoAvailable()");
+ }
+ if (sessionState.mSession == null || sessionState.mClient == null) {
+ return;
+ }
+ try {
+ sessionState.mClient.onVideoAvailable(sessionState.mSeq);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in onVideoAvailable");
+ }
+ }
+ }
+
+ @Override
+ public void onVideoUnavailable(int reason) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "onVideoUnavailable(" + reason + ")");
+ }
+ if (sessionState.mSession == null || sessionState.mClient == null) {
+ return;
+ }
+ try {
+ sessionState.mClient.onVideoUnavailable(reason, sessionState.mSeq);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in onVideoUnavailable");
+ }
+ }
+ }
+
+ @Override
public void onSessionEvent(String eventType, Bundle eventArgs) {
synchronized (mLock) {
if (DEBUG) {
@@ -554,7 +602,7 @@
updateServiceConnectionLocked(sessionState.mInputId, userId);
}
- private void unregisterCallbackInternalLocked(IBinder clientToken, String inputId,
+ private void unregisterClientInternalLocked(IBinder clientToken, String inputId,
int userId) {
UserState userState = getUserStateLocked(userId);
ClientState clientState = userState.clientStateMap.get(clientToken);
@@ -589,14 +637,43 @@
}
}
- private void broadcastServiceAvailabilityChangedLocked(ServiceState serviceState) {
- for (IBinder clientToken : serviceState.mClientTokens) {
- try {
- ITvInputClient.Stub.asInterface(clientToken).onAvailabilityChanged(
- serviceState.mTvInputInfo.getId(), serviceState.mAvailable);
- } catch (RemoteException e) {
- Slog.e(TAG, "error in onAvailabilityChanged", e);
+ private void notifyStateChangedLocked(UserState userState, String inputId,
+ int state, ITvInputManagerCallback targetCallback) {
+ if (DEBUG) {
+ Slog.d(TAG, "notifyStateChangedLocked: inputId = " + inputId
+ + "; state = " + state);
+ }
+ if (targetCallback == null) {
+ for (ITvInputManagerCallback callback : userState.callbackSet) {
+ try {
+ callback.onInputStateChanged(inputId, state);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to report state change to callback.");
+ }
}
+ } else {
+ try {
+ targetCallback.onInputStateChanged(inputId, state);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to report state change to callback.");
+ }
+ }
+ }
+
+ private void setStateLocked(String inputId, int state, int userId) {
+ UserState userState = getUserStateLocked(userId);
+ TvInputState inputState = userState.inputMap.get(inputId);
+ ServiceState serviceState = userState.serviceStateMap.get(inputId);
+ int oldState = inputState.mState;
+ inputState.mState = state;
+ boolean isStateEmpty = serviceState.mClientTokens.isEmpty()
+ && serviceState.mSessionTokens.isEmpty();
+ if (serviceState != null && serviceState.mService == null && !isStateEmpty) {
+ // We don't notify state change while reconnecting. It should remain disconnected.
+ return;
+ }
+ if (oldState != state) {
+ notifyStateChangedLocked(userState, inputId, state, null);
}
}
@@ -609,80 +686,29 @@
try {
synchronized (mLock) {
UserState userState = getUserStateLocked(resolvedUserId);
- return new ArrayList<TvInputInfo>(userState.inputMap.values());
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public boolean getAvailability(final ITvInputClient client, final String inputId,
- int userId) {
- final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, "getAvailability");
- final long identity = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
- UserState userState = getUserStateLocked(resolvedUserId);
- ServiceState serviceState = userState.serviceStateMap.get(inputId);
- if (serviceState != null) {
- // We already know the status of this input service. Return the cached
- // status.
- return serviceState.mAvailable;
+ List<TvInputInfo> inputList = new ArrayList<TvInputInfo>();
+ for (TvInputState state : userState.inputMap.values()) {
+ inputList.add(state.mInfo);
}
+ return inputList;
}
} finally {
Binder.restoreCallingIdentity(identity);
}
- // STOPSHIP: Redesign the API around the availability change. For now, the service
- // will be always available.
- return true;
}
@Override
- public void registerCallback(final ITvInputClient client, final String inputId,
- int userId) {
+ public void registerCallback(final ITvInputManagerCallback callback, int userId) {
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "registerCallback");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- // Create a new service callback and add it to the callback map of the current
- // service.
UserState userState = getUserStateLocked(resolvedUserId);
- ServiceState serviceState = userState.serviceStateMap.get(inputId);
- if (serviceState == null) {
- serviceState = new ServiceState(
- userState.inputMap.get(inputId), resolvedUserId);
- userState.serviceStateMap.put(inputId, serviceState);
- }
- IBinder clientToken = client.asBinder();
- if (!serviceState.mClientTokens.contains(clientToken)) {
- serviceState.mClientTokens.add(clientToken);
- }
-
- ClientState clientState = userState.clientStateMap.get(clientToken);
- if (clientState == null) {
- clientState = createClientStateLocked(clientToken, resolvedUserId);
- }
- if (!clientState.mInputIds.contains(inputId)) {
- clientState.mInputIds.add(inputId);
- }
-
- if (serviceState.mService != null) {
- if (serviceState.mCallback != null) {
- // We already handled.
- return;
- }
- serviceState.mCallback = new ServiceCallback(resolvedUserId);
- try {
- serviceState.mService.registerCallback(serviceState.mCallback);
- } catch (RemoteException e) {
- Slog.e(TAG, "error in registerCallback", e);
- }
- } else {
- updateServiceConnectionLocked(inputId, resolvedUserId);
+ userState.callbackSet.add(callback);
+ for (TvInputState state : userState.inputMap.values()) {
+ notifyStateChangedLocked(userState, state.mInfo.getId(),
+ state.mState, callback);
}
}
} finally {
@@ -691,13 +717,14 @@
}
@Override
- public void unregisterCallback(ITvInputClient client, String inputId, int userId) {
+ public void unregisterCallback(ITvInputManagerCallback callback, int userId) {
final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
Binder.getCallingUid(), userId, "unregisterCallback");
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- unregisterCallbackInternalLocked(client.asBinder(), inputId, resolvedUserId);
+ UserState userState = getUserStateLocked(resolvedUserId);
+ userState.callbackSet.remove(callback);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -717,7 +744,7 @@
ServiceState serviceState = userState.serviceStateMap.get(inputId);
if (serviceState == null) {
serviceState = new ServiceState(
- userState.inputMap.get(inputId), resolvedUserId);
+ userState.inputMap.get(inputId).mInfo, resolvedUserId);
userState.serviceStateMap.put(inputId, serviceState);
}
// Send a null token immediately while reconnecting.
@@ -834,7 +861,7 @@
}
// Create a log entry and fill it later.
- String packageName = userState.inputMap.get(sessionState.mInputId)
+ String packageName = userState.inputMap.get(sessionState.mInputId).mInfo
.getServiceInfo().packageName;
ContentValues values = new ContentValues();
values.put(TvContract.WatchedPrograms.COLUMN_PACKAGE_NAME, packageName);
@@ -983,8 +1010,7 @@
@Override
public List<TvInputHardwareInfo> getHardwareList() throws RemoteException {
- if (mContext.checkCallingPermission(
- android.Manifest.permission.TV_INPUT_HARDWARE)
+ if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
!= PackageManager.PERMISSION_GRANTED) {
return null;
}
@@ -998,10 +1024,25 @@
}
@Override
+ public void registerTvInputInfo(TvInputInfo info, int deviceId) {
+ if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
+ != PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mTvInputHardwareManager.registerTvInputInfo(info, deviceId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public ITvInputHardware acquireTvInputHardware(int deviceId,
- ITvInputHardwareCallback callback, int userId) throws RemoteException {
- if (mContext.checkCallingPermission(
- android.Manifest.permission.TV_INPUT_HARDWARE)
+ ITvInputHardwareCallback callback, TvInputInfo info, int userId)
+ throws RemoteException {
+ if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
!= PackageManager.PERMISSION_GRANTED) {
return null;
}
@@ -1012,7 +1053,7 @@
userId, "acquireTvInputHardware");
try {
return mTvInputHardwareManager.acquireHardware(
- deviceId, callback, callingUid, resolvedUserId);
+ deviceId, callback, info, callingUid, resolvedUserId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1021,8 +1062,7 @@
@Override
public void releaseTvInputHardware(int deviceId, ITvInputHardware hardware, int userId)
throws RemoteException {
- if (mContext.checkCallingPermission(
- android.Manifest.permission.TV_INPUT_HARDWARE)
+ if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
@@ -1065,16 +1105,16 @@
pw.println("UserState (" + userId + "):");
pw.increaseIndent();
- pw.println("inputMap: inputId -> TvInputInfo");
+ pw.println("inputMap: inputId -> TvInputState");
pw.increaseIndent();
- for (TvInputInfo info : userState.inputMap.values()) {
- pw.println(info.toString());
+ for (TvInputState state : userState.inputMap.values()) {
+ pw.println(state.toString());
}
pw.decreaseIndent();
- pw.println("packageList:");
+ pw.println("packageSet:");
pw.increaseIndent();
- for (String packageName : userState.packageList) {
+ for (String packageName : userState.packageSet) {
pw.println(packageName);
}
pw.decreaseIndent();
@@ -1135,7 +1175,6 @@
pw.println("mService: " + service.mService);
pw.println("mCallback: " + service.mCallback);
pw.println("mBound: " + service.mBound);
- pw.println("mAvailable: " + service.mAvailable);
pw.println("mReconnecting: " + service.mReconnecting);
pw.decreaseIndent();
@@ -1162,18 +1201,38 @@
}
pw.decreaseIndent();
+ pw.println("callbackSet:");
+ pw.increaseIndent();
+ for (ITvInputManagerCallback callback : userState.callbackSet) {
+ pw.println(callback.toString());
+ }
+ pw.decreaseIndent();
+
pw.decreaseIndent();
}
}
}
}
- private static final class UserState {
- // A mapping from the TV input id to its TvInputInfo.
- private final Map<String, TvInputInfo> inputMap = new HashMap<String,TvInputInfo>();
+ private static final class TvInputState {
+ // A TvInputInfo object which represents the TV input.
+ private TvInputInfo mInfo;
- // A list of all TV input packages.
- private final Set<String> packageList = new HashSet<String>();
+ // The state of TV input. Connected by default.
+ private int mState = INPUT_STATE_CONNECTED;
+
+ @Override
+ public String toString() {
+ return "mInfo: " + mInfo + "; mState: " + mState;
+ }
+ }
+
+ private static final class UserState {
+ // A mapping from the TV input id to its TvInputState.
+ private Map<String, TvInputState> inputMap = new HashMap<String, TvInputState>();
+
+ // A set of all TV input packages.
+ private final Set<String> packageSet = new HashSet<String>();
// A mapping from the token of a client to its state.
private final Map<IBinder, ClientState> clientStateMap =
@@ -1186,6 +1245,10 @@
// A mapping from the token of a TV input session to its state.
private final Map<IBinder, SessionState> sessionStateMap =
new HashMap<IBinder, SessionState>();
+
+ // A set of callbacks.
+ private final Set<ITvInputManagerCallback> callbackSet =
+ new HashSet<ITvInputManagerCallback>();
}
private final class ClientState implements IBinder.DeathRecipient {
@@ -1209,7 +1272,7 @@
synchronized (mLock) {
UserState userState = getUserStateLocked(mUserId);
// DO NOT remove the client state of clientStateMap in this method. It will be
- // removed in releaseSessionLocked() or unregisterCallbackInternalLocked().
+ // removed in releaseSessionLocked() or unregisterClientInternalLocked().
ClientState clientState = userState.clientStateMap.get(mClientToken);
if (clientState != null) {
while (clientState.mSessionTokens.size() > 0) {
@@ -1217,7 +1280,7 @@
clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId);
}
while (clientState.mInputIds.size() > 0) {
- unregisterCallbackInternalLocked(
+ unregisterClientInternalLocked(
mClientToken, clientState.mInputIds.get(0), mUserId);
}
}
@@ -1235,7 +1298,6 @@
private ITvInputService mService;
private ServiceCallback mCallback;
private boolean mBound;
- private boolean mAvailable;
private boolean mReconnecting;
private ServiceState(TvInputInfo inputInfo, int userId) {
@@ -1291,16 +1353,18 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
+ String inputId = mTvInputInfo.getId();
if (DEBUG) {
- Slog.d(TAG, "onServiceConnected(inputId=" + mTvInputInfo.getId() + ")");
+ Slog.d(TAG, "onServiceConnected(inputId=" + inputId + ")");
}
synchronized (mLock) {
- ServiceState serviceState = getServiceStateLocked(mTvInputInfo.getId(), mUserId);
+ UserState userState = getUserStateLocked(mUserId);
+ ServiceState serviceState = userState.serviceStateMap.get(inputId);
serviceState.mService = ITvInputService.Stub.asInterface(service);
// Register a callback, if we need to.
if (!serviceState.mClientTokens.isEmpty() && serviceState.mCallback == null) {
- serviceState.mCallback = new ServiceCallback(mUserId);
+ serviceState.mCallback = new ServiceCallback(mTvInputInfo.getId(), mUserId);
try {
serviceState.mService.registerCallback(serviceState.mCallback);
} catch (RemoteException e) {
@@ -1312,6 +1376,12 @@
for (IBinder sessionToken : serviceState.mSessionTokens) {
createSessionInternalLocked(serviceState.mService, sessionToken, mUserId);
}
+
+ TvInputState inputState = userState.inputMap.get(inputId);
+ if (inputState != null && inputState.mState != INPUT_STATE_DISCONNECTED) {
+ notifyStateChangedLocked(userState, mTvInputInfo.getId(),
+ inputState.mState, null);
+ }
}
}
@@ -1343,10 +1413,8 @@
}
}
- if (serviceState.mAvailable) {
- serviceState.mAvailable = false;
- broadcastServiceAvailabilityChangedLocked(serviceState);
- }
+ notifyStateChangedLocked(userState, mTvInputInfo.getId(),
+ INPUT_STATE_DISCONNECTED, null);
updateServiceConnectionLocked(mTvInputInfo.getId(), mUserId);
}
}
@@ -1354,24 +1422,22 @@
}
private final class ServiceCallback extends ITvInputServiceCallback.Stub {
+ private final String mInputId;
private final int mUserId;
- ServiceCallback(int userId) {
+ ServiceCallback(String inputId, int userId) {
+ mInputId = inputId;
mUserId = userId;
}
@Override
- public void onAvailabilityChanged(String inputId, boolean isAvailable) {
+ public void onInputStateChanged(int state) {
if (DEBUG) {
- Slog.d(TAG, "onAvailabilityChanged(inputId=" + inputId + ", isAvailable="
- + isAvailable + ")");
+ Slog.d(TAG, "onInputStateChanged(inputId=" + mInputId + ", state="
+ + state + ")");
}
synchronized (mLock) {
- ServiceState serviceState = getServiceStateLocked(inputId, mUserId);
- if (serviceState.mAvailable != isAvailable) {
- serviceState.mAvailable = isAvailable;
- broadcastServiceAvailabilityChangedLocked(serviceState);
- }
+ setStateLocked(mInputId, state, mUserId);
}
}
}
@@ -1519,4 +1585,12 @@
mContentResolver.update(uri, values, null, null);
}
}
+
+ final class Client {
+ public void setState(String inputId, int state) {
+ synchronized (mLock) {
+ setStateLocked(inputId, state, mCurrentUserId);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index e007600..0e1340c 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -46,6 +46,8 @@
import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindBackgroundAnimation;
+import static com.android.internal.R.styleable.WindowAnimation_launchTaskBehindSourceAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
import static com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation;
@@ -72,44 +74,42 @@
WindowManagerService.DEBUG_APP_TRANSITIONS;
private static final boolean DEBUG_ANIM = WindowManagerService.DEBUG_ANIM;
- /** Bit mask that is set for all enter transition. */
- public static final int TRANSIT_ENTER_MASK = 0x1000;
-
- /** Bit mask that is set for all exit transitions. */
- public static final int TRANSIT_EXIT_MASK = 0x2000;
/** Not set up for a transition. */
public static final int TRANSIT_UNSET = -1;
/** No animation for transition. */
public static final int TRANSIT_NONE = 0;
/** A window in a new activity is being opened on top of an existing one in the same task. */
- public static final int TRANSIT_ACTIVITY_OPEN = 6 | TRANSIT_ENTER_MASK;
+ public static final int TRANSIT_ACTIVITY_OPEN = 6;
/** The window in the top-most activity is being closed to reveal the
* previous activity in the same task. */
- public static final int TRANSIT_ACTIVITY_CLOSE = 7 | TRANSIT_EXIT_MASK;
+ public static final int TRANSIT_ACTIVITY_CLOSE = 7;
/** A window in a new task is being opened on top of an existing one
* in another activity's task. */
- public static final int TRANSIT_TASK_OPEN = 8 | TRANSIT_ENTER_MASK;
+ public static final int TRANSIT_TASK_OPEN = 8;
/** A window in the top-most activity is being closed to reveal the
* previous activity in a different task. */
- public static final int TRANSIT_TASK_CLOSE = 9 | TRANSIT_EXIT_MASK;
+ public static final int TRANSIT_TASK_CLOSE = 9;
/** A window in an existing task is being displayed on top of an existing one
* in another activity's task. */
- public static final int TRANSIT_TASK_TO_FRONT = 10 | TRANSIT_ENTER_MASK;
+ public static final int TRANSIT_TASK_TO_FRONT = 10;
/** A window in an existing task is being put below all other tasks. */
- public static final int TRANSIT_TASK_TO_BACK = 11 | TRANSIT_EXIT_MASK;
+ public static final int TRANSIT_TASK_TO_BACK = 11;
/** A window in a new activity that doesn't have a wallpaper is being opened on top of one that
* does, effectively closing the wallpaper. */
- public static final int TRANSIT_WALLPAPER_CLOSE = 12 | TRANSIT_EXIT_MASK;
+ public static final int TRANSIT_WALLPAPER_CLOSE = 12;
/** A window in a new activity that does have a wallpaper is being opened on one that didn't,
* effectively opening the wallpaper. */
- public static final int TRANSIT_WALLPAPER_OPEN = 13 | TRANSIT_ENTER_MASK;
+ public static final int TRANSIT_WALLPAPER_OPEN = 13;
/** A window in a new activity is being opened on top of an existing one, and both are on top
* of the wallpaper. */
- public static final int TRANSIT_WALLPAPER_INTRA_OPEN = 14 | TRANSIT_ENTER_MASK;
+ public static final int TRANSIT_WALLPAPER_INTRA_OPEN = 14;
/** The window in the top-most activity is being closed to reveal the previous activity, and
* both are on top of the wallpaper. */
- public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15 | TRANSIT_EXIT_MASK;
+ public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15;
+ /** A window in a new task is being opened behind an existing one in another activity's task.
+ * The new window will show briefly and then be gone. */
+ public static final int TRANSIT_TASK_OPEN_BEHIND = 16;
/** Fraction of animation at which the recents thumbnail becomes completely transparent */
private static final float RECENTS_THUMBNAIL_FADEOUT_FRACTION = 0.25f;
@@ -811,6 +811,10 @@
? WindowAnimation_wallpaperIntraCloseEnterAnimation
: WindowAnimation_wallpaperIntraCloseExitAnimation;
break;
+ case TRANSIT_TASK_OPEN_BEHIND:
+ animAttr = enter
+ ? WindowAnimation_launchTaskBehindSourceAnimation
+ : WindowAnimation_launchTaskBehindBackgroundAnimation;
}
a = animAttr != 0 ? loadAnimationAttr(lp, animAttr) : null;
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.v(TAG,
@@ -896,9 +900,6 @@
case TRANSIT_NONE: {
return "TRANSIT_NONE";
}
- case TRANSIT_EXIT_MASK: {
- return "TRANSIT_EXIT_MASK";
- }
case TRANSIT_ACTIVITY_OPEN: {
return "TRANSIT_ACTIVITY_OPEN";
}
@@ -929,6 +930,9 @@
case TRANSIT_WALLPAPER_INTRA_CLOSE: {
return "TRANSIT_WALLPAPER_INTRA_CLOSE";
}
+ case TRANSIT_TASK_OPEN_BEHIND: {
+ return "TRANSIT_TASK_OPEN_BEHIND";
+ }
default: {
return "<UNKNOWN>";
}
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 63ae98e..874e105 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -16,7 +16,9 @@
package com.android.server.wm;
+import android.graphics.Bitmap;
import android.graphics.Matrix;
+import android.os.RemoteException;
import android.util.Slog;
import android.util.TimeUtils;
import android.view.Display;
@@ -281,9 +283,21 @@
final int N = mAllAppWinAnimators.size();
for (int i=0; i<N; i++) {
- mAllAppWinAnimators.get(i).finishExit();
+ final WindowStateAnimator winAnim = mAllAppWinAnimators.get(i);
+ if (mAppToken.mLaunchTaskBehind) {
+ winAnim.mWin.mExiting = true;
+ }
+ winAnim.finishExit();
}
- mAppToken.updateReportedVisibilityLocked();
+ if (mAppToken.mLaunchTaskBehind) {
+ try {
+ mService.mActivityManager.notifyLaunchTaskBehindComplete(mAppToken.token);
+ } catch (RemoteException e) {
+ }
+ mAppToken.mLaunchTaskBehind = false;
+ } else {
+ mAppToken.updateReportedVisibilityLocked();
+ }
return false;
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 12c15e2..312689b 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -109,6 +109,8 @@
boolean mDeferRemoval;
+ boolean mLaunchTaskBehind;
+
AppWindowToken(WindowManagerService _service, IApplicationToken _token,
boolean _voiceInteraction) {
super(_service, _token.asBinder(),
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index f1d0585d..27fff1d 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -248,7 +248,7 @@
for (int i = windows.size() - 1; i >= 0; i--) {
WindowState win = windows.get(i);
WindowStateAnimator winAnimator = win.mWinAnimator;
- final int flags = winAnimator.mAttrFlags;
+ final int flags = win.mAttrs.flags;
if (winAnimator.mSurfaceControl != null) {
final boolean wasAnimating = winAnimator.mWasAnimating;
@@ -309,8 +309,7 @@
+ " hidden=" + win.mRootToken.hidden
+ " anim=" + win.mWinAnimator.mAnimation);
} else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
- final boolean hideWhenLocked =
- (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0;
+ final boolean hideWhenLocked = (flags & FLAG_SHOW_WHEN_LOCKED) == 0;
final boolean changed;
if (((mForceHiding == KEYGUARD_ANIMATING_IN)
&& (!winAnimator.isAnimating() || hideWhenLocked))
@@ -416,7 +415,7 @@
continue;
}
- final int flags = winAnimator.mAttrFlags;
+ final int flags = win.mAttrs.flags;
// If this window is animating, make a note that we have
// an animating window and take care of a request to run
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 396ec8f..a5959d4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -497,8 +497,8 @@
boolean mStartingIconInTransition = false;
boolean mSkipAppTransitionAnimation = false;
- final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
- final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
+ final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<AppWindowToken>();
+ final ArraySet<AppWindowToken> mClosingApps = new ArraySet<AppWindowToken>();
boolean mIsTouchDevice;
@@ -3234,6 +3234,12 @@
SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN);
}
+ if (atoken.mLaunchTaskBehind) {
+ // Differentiate the two animations. This one which is briefly on the screen
+ // gets the !enter animation, and the other activity which remains on the
+ // screen gets the enter animation. Both appear in the mOpeningApps set.
+ enter = false;
+ }
Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
mCurConfiguration.orientation, containingFrame, contentInsets, isFullScreen,
isVoiceInteraction);
@@ -3449,14 +3455,14 @@
EventLog.writeEvent(EventLogTags.WM_TASK_CREATED, taskId, stackId);
Task task = new Task(atoken, stack, userId);
mTaskIdToTask.put(taskId, task);
- stack.addTask(task, true);
+ stack.addTask(task, !atoken.mLaunchTaskBehind /* toTop */);
return task;
}
@Override
public void addAppToken(int addPos, IApplicationToken token, int taskId, int stackId,
int requestedOrientation, boolean fullscreen, boolean showWhenLocked, int userId,
- int configChanges, boolean voiceInteraction) {
+ int configChanges, boolean voiceInteraction, boolean launchTaskBehind) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"addAppToken()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
@@ -3490,6 +3496,7 @@
atoken.requestedOrientation = requestedOrientation;
atoken.layoutConfigChanges = (configChanges &
(ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_ORIENTATION)) != 0;
+ atoken.mLaunchTaskBehind = launchTaskBehind;
if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
+ " to stack=" + stackId + " task=" + taskId + " at " + addPos);
@@ -3954,16 +3961,16 @@
}
synchronized(mWindowMap) {
- if (DEBUG_APP_TRANSITIONS) {
- RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
- Slog.w(TAG, "Execute app transition: " + mAppTransition, e);
- }
+ if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition,
+ new RuntimeException("here").fillInStackTrace());
if (mAppTransition.isTransitionSet()) {
mAppTransition.setReady();
final long origId = Binder.clearCallingIdentity();
- performLayoutAndPlaceSurfacesLocked();
- Binder.restoreCallingIdentity(origId);
+ try {
+ performLayoutAndPlaceSurfacesLocked();
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
}
}
}
@@ -4370,17 +4377,11 @@
return;
}
- if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
- RuntimeException e = null;
- if (!HIDE_STACK_CRAWLS) {
- e = new RuntimeException();
- e.fillInStackTrace();
- }
- Slog.v(TAG, "setAppVisibility(" + token + ", visible=" + visible
- + "): " + mAppTransition
- + " hidden=" + wtoken.hidden
- + " hiddenRequested=" + wtoken.hiddenRequested, e);
- }
+ if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" +
+ token + ", visible=" + visible + "): " + mAppTransition +
+ " hidden=" + wtoken.hidden + " hiddenRequested=" +
+ wtoken.hiddenRequested, HIDE_STACK_CRAWLS ?
+ null : new RuntimeException("here").fillInStackTrace());
// If we are preparing an app transition, then delay changing
// the visibility of this token until we execute that transition.
@@ -4428,6 +4429,21 @@
wtoken.waitingToHide = true;
}
}
+ if (mAppTransition.getAppTransition() == AppTransition.TRANSIT_TASK_OPEN_BEHIND) {
+ // We're launchingBehind, add the launching activity to mOpeningApps.
+ final WindowState win =
+ findFocusedWindowLocked(getDefaultDisplayContentLocked());
+ if (win != null) {
+ final AppWindowToken focusedToken = win.mAppToken;
+ if (focusedToken != null) {
+ if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "TRANSIT_TASK_OPEN_BEHIND, " +
+ " adding " + focusedToken + " to mOpeningApps");
+ // Force animation to be loaded.
+ focusedToken.hidden = true;
+ mOpeningApps.add(focusedToken);
+ }
+ }
+ }
return;
}
@@ -8558,7 +8574,7 @@
// all of the apps are ready. Otherwise just go because
// we'll unfreeze the display when everyone is ready.
for (i=0; i<NN && goodToGo; i++) {
- AppWindowToken wtoken = mOpeningApps.get(i);
+ AppWindowToken wtoken = mOpeningApps.valueAt(i);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"Check opening app=" + wtoken + ": allDrawn="
+ wtoken.allDrawn + " startingDisplayed="
@@ -8631,12 +8647,12 @@
for (i=0; i<NN; i++) {
final AppWindowToken wtoken;
if (i < NC) {
- wtoken = mClosingApps.get(i);
+ wtoken = mClosingApps.valueAt(i);
if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
closingAppHasWallpaper = true;
}
} else {
- wtoken = mOpeningApps.get(i - NC);
+ wtoken = mOpeningApps.valueAt(i - NC);
if (wtoken == lowerWallpaperAppToken || wtoken == upperWallpaperAppToken) {
openingAppHasWallpaper = true;
}
@@ -8710,7 +8726,7 @@
NN = mOpeningApps.size();
for (i=0; i<NN; i++) {
- AppWindowToken wtoken = mOpeningApps.get(i);
+ AppWindowToken wtoken = mOpeningApps.valueAt(i);
final AppWindowAnimator appAnimator = wtoken.mAppAnimator;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
appAnimator.clearThumbnail();
@@ -8743,7 +8759,7 @@
}
NN = mClosingApps.size();
for (i=0; i<NN; i++) {
- AppWindowToken wtoken = mClosingApps.get(i);
+ AppWindowToken wtoken = mClosingApps.valueAt(i);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now closing app " + wtoken);
wtoken.mAppAnimator.clearThumbnail();
wtoken.inPendingTransaction = false;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 8387b65..49d4ae9 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -172,7 +172,6 @@
/** Was this window last hidden? */
boolean mLastHidden;
- int mAttrFlags;
int mAttrType;
public WindowStateAnimator(final WindowState win) {
@@ -197,7 +196,6 @@
? null : win.mAttachedWindow.mWinAnimator;
mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
mSession = win.mSession;
- mAttrFlags = win.mAttrs.flags;
mAttrType = win.mAttrs.type;
mIsWallpaper = win.mIsWallpaper;
}
@@ -717,10 +715,10 @@
float top = w.mFrame.top + w.mYOffset;
// Adjust for surface insets.
- width += attrs.shadowInsets.left + attrs.shadowInsets.right;
- height += attrs.shadowInsets.top + attrs.shadowInsets.bottom;
- left -= attrs.shadowInsets.left;
- top -= attrs.shadowInsets.top;
+ width += attrs.surfaceInsets.left + attrs.surfaceInsets.right;
+ height += attrs.surfaceInsets.top + attrs.surfaceInsets.bottom;
+ left -= attrs.surfaceInsets.left;
+ top -= attrs.surfaceInsets.top;
if (DEBUG_VISIBILITY) {
Slog.v(TAG, "Creating surface in session "
@@ -1140,19 +1138,12 @@
void applyDecorRect(final Rect decorRect) {
final WindowState w = mWin;
- int width = w.mFrame.width();
- int height = w.mFrame.height();
+ final int width = w.mFrame.width();
+ final int height = w.mFrame.height();
// Compute the offset of the window in relation to the decor rect.
- int left = w.mXOffset + w.mFrame.left;
- int top = w.mYOffset + w.mFrame.top;
-
- // Adjust for surface insets.
- final WindowManager.LayoutParams attrs = w.mAttrs;
- width += attrs.shadowInsets.left + attrs.shadowInsets.right;
- height += attrs.shadowInsets.top + attrs.shadowInsets.bottom;
- left -= attrs.shadowInsets.left;
- top -= attrs.shadowInsets.top;
+ final int left = w.mXOffset + w.mFrame.left;
+ final int top = w.mYOffset + w.mFrame.top;
// Initialize the decor rect to the entire frame.
w.mSystemDecorRect.set(0, 0, width, height);
@@ -1182,7 +1173,6 @@
if (displayContent == null) {
return;
}
- DisplayInfo displayInfo = displayContent.getDisplayInfo();
// Need to recompute a new system decor rect each time.
if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
@@ -1192,6 +1182,7 @@
} else if (!w.isDefaultDisplay()) {
// On a different display there is no system decor. Crop the window
// by the screen boundaries.
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
w.mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top,
displayInfo.logicalWidth - w.mCompatFrame.left,
@@ -1202,44 +1193,52 @@
// windows need to be cropped by the screen, so they don't cover
// the universe background.
if (mAnimator.mUniverseBackground == null) {
- w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
- w.mCompatFrame.height());
+ w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
} else {
applyDecorRect(mService.mScreenRect);
}
} else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND
|| w.mDecorFrame.isEmpty()) {
// The universe background isn't cropped, nor windows without policy decor.
- w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(),
- w.mCompatFrame.height());
+ w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
} else {
// Crop to the system decor specified by policy.
applyDecorRect(w.mDecorFrame);
}
- // By default, the clip rect is the system decor rect
- Rect clipRect = w.mSystemDecorRect;
- if (mHasClipRect) {
+ // By default, the clip rect is the system decor.
+ final Rect clipRect = mTmpClipRect;
+ clipRect.set(w.mSystemDecorRect);
- // If we have an animated clip rect, intersect it with the system decor rect
- // NOTE: We are adding a temporary workaround due to the status bar not always reporting
- // the correct system decor rect. In such cases, we take into account the specified
- // content insets as well.
- int offsetTop = Math.max(w.mSystemDecorRect.top, w.mContentInsets.top);
- mTmpClipRect.set(w.mSystemDecorRect);
- // Don't apply the workaround to apps explicitly requesting fullscreen layout.
+ // Expand the clip rect for surface insets.
+ final WindowManager.LayoutParams attrs = w.mAttrs;
+ clipRect.left -= attrs.surfaceInsets.left;
+ clipRect.top -= attrs.surfaceInsets.top;
+ clipRect.right += attrs.surfaceInsets.right;
+ clipRect.bottom += attrs.surfaceInsets.bottom;
+
+ // If we have an animated clip rect, intersect it with the clip rect.
+ if (mHasClipRect) {
+ // NOTE: We are adding a temporary workaround due to the status bar
+ // not always reporting the correct system decor rect. In such
+ // cases, we take into account the specified content insets as well.
if ((w.mSystemUiVisibility & SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN)
== SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN) {
- mTmpClipRect.intersect(mClipRect);
+ // Don't apply the workaround to apps explicitly requesting
+ // fullscreen layout.
+ clipRect.intersect(mClipRect);
} else {
- mTmpClipRect.offset(0, -offsetTop);
- mTmpClipRect.intersect(mClipRect);
- mTmpClipRect.offset(0, offsetTop);
+ final int offsetTop = Math.max(clipRect.top, w.mContentInsets.top);
+ clipRect.offset(0, -offsetTop);
+ clipRect.intersect(mClipRect);
+ clipRect.offset(0, offsetTop);
}
- clipRect = mTmpClipRect;
-
}
+ // The clip rect was generated assuming (0,0) as the window origin,
+ // so we need to translate to match the actual surface coordinates.
+ clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
+
if (!clipRect.equals(mLastClipRect)) {
mLastClipRect.set(clipRect);
try {
@@ -1285,10 +1284,10 @@
// Adjust for surface insets.
final LayoutParams attrs = w.getAttrs();
- width += attrs.shadowInsets.left + attrs.shadowInsets.right;
- height += attrs.shadowInsets.top + attrs.shadowInsets.bottom;
- left -= attrs.shadowInsets.left;
- top -= attrs.shadowInsets.top;
+ width += attrs.surfaceInsets.left + attrs.surfaceInsets.right;
+ height += attrs.surfaceInsets.top + attrs.surfaceInsets.bottom;
+ left -= attrs.surfaceInsets.left;
+ top -= attrs.surfaceInsets.top;
final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
if (surfaceMoved) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5445dc0..92d3d95 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3741,6 +3741,114 @@
}
@Override
+ public void enableSystemApp(ComponentName who, String packageName) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+
+ // This API can only be called by an active device admin,
+ // so try to retrieve it to check that the caller is one.
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ int userId = UserHandle.getCallingUserId();
+ long id = Binder.clearCallingIdentity();
+
+ try {
+ UserManager um = UserManager.get(mContext);
+ if (!um.getUserInfo(userId).isManagedProfile()) {
+ throw new IllegalStateException(
+ "Only call this method from a managed profile.");
+ }
+
+ UserInfo primaryUser = um.getProfileParent(userId);
+
+ if (DBG) {
+ Slog.v(LOG_TAG, "installing " + packageName + " for "
+ + userId);
+ }
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ if (!isSystemApp(pm, packageName, primaryUser.id)) {
+ throw new IllegalArgumentException("Only system apps can be enabled this way.");
+ }
+
+ // Install the app.
+ pm.installExistingPackageAsUser(packageName, userId);
+
+ } catch (RemoteException re) {
+ // shouldn't happen
+ Slog.wtf(LOG_TAG, "Failed to install " + packageName, re);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
+
+ @Override
+ public int enableSystemAppWithIntent(ComponentName who, Intent intent) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+
+ // This API can only be called by an active device admin,
+ // so try to retrieve it to check that the caller is one.
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ int userId = UserHandle.getCallingUserId();
+ long id = Binder.clearCallingIdentity();
+
+ try {
+ UserManager um = UserManager.get(mContext);
+ if (!um.getUserInfo(userId).isManagedProfile()) {
+ throw new IllegalStateException(
+ "Only call this method from a managed profile.");
+ }
+
+ UserInfo primaryUser = um.getProfileParent(userId);
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ 0, // no flags
+ primaryUser.id);
+
+ if (DBG) Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
+ int numberOfAppsInstalled = 0;
+ if (activitiesToEnable != null) {
+ for (ResolveInfo info : activitiesToEnable) {
+ if (info.activityInfo != null) {
+
+ if (!isSystemApp(pm, info.activityInfo.packageName, primaryUser.id)) {
+ throw new IllegalArgumentException(
+ "Only system apps can be enabled this way.");
+ }
+
+
+ numberOfAppsInstalled++;
+ pm.installExistingPackageAsUser(info.activityInfo.packageName, userId);
+ }
+ }
+ }
+ return numberOfAppsInstalled;
+ } catch (RemoteException e) {
+ // shouldn't happen
+ Slog.wtf(LOG_TAG, "Failed to resolve intent for: " + intent);
+ return 0;
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
+
+ private boolean isSystemApp(IPackageManager pm, String packageName, int userId)
+ throws RemoteException {
+ ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0, userId);
+ return (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0;
+ }
+
+ @Override
public void setAccountManagementDisabled(ComponentName who, String accountType,
boolean disabled) {
if (!mHasFeature) {
diff --git a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
index 1db3c5e..4fe30e6 100644
--- a/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
+++ b/services/restrictions/java/com/android/server/restrictions/RestrictionsManagerService.java
@@ -23,17 +23,13 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.IDevicePolicyManager;
-import android.content.AbstractRestrictionsProvider;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
-import android.content.IPermissionResponseCallback;
-import android.content.IRestrictionsProvider;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IRestrictionsManager;
import android.content.RestrictionsManager;
-import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -127,58 +123,12 @@
enforceCallerMatchesPackage(callingUid, packageName, "Package name does not" +
" match caller ");
// Prepare and broadcast the intent to the provider
- Intent intent = new Intent();
+ Intent intent = new Intent(RestrictionsManager.ACTION_REQUEST_PERMISSION);
intent.setComponent(restrictionsProvider);
- new ProviderServiceConnection(intent, null, userHandle) {
- @Override
- public void run() throws RemoteException {
- if (DEBUG) {
- Log.i(LOG_TAG, "calling requestPermission for " + packageName
- + ", type=" + requestType + ", data=" + requestData);
- }
- mRestrictionsProvider.requestPermission(packageName,
- requestType, requestData);
- }
- }.bind();
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- @Override
- public void getPermissionResponse(final String packageName, final String requestId,
- final IPermissionResponseCallback callback) throws RemoteException {
- int callingUid = Binder.getCallingUid();
- int userHandle = UserHandle.getUserId(callingUid);
- if (mDpm != null) {
- long ident = Binder.clearCallingIdentity();
- try {
- ComponentName restrictionsProvider =
- mDpm.getRestrictionsProvider(userHandle);
- // Check if there is a restrictions provider
- if (restrictionsProvider == null) {
- throw new IllegalStateException(
- "Cannot fetch permission without a restrictions provider registered");
- }
- // Check that the packageName matches the caller.
- enforceCallerMatchesPackage(callingUid, packageName, "Package name does not" +
- " match caller ");
- // Prepare and broadcast the intent to the provider
- Intent intent = new Intent();
- intent.setComponent(restrictionsProvider);
- new ProviderServiceConnection(intent, callback.asBinder(), userHandle) {
- @Override
- public void run() throws RemoteException {
- if (DEBUG) {
- Log.i(LOG_TAG, "calling getPermissionResponse for " + packageName
- + ", id=" + requestId);
- }
- Bundle response = mRestrictionsProvider.getPermissionResponse(
- packageName, requestId);
- callback.onResponse(response);
- }
- }.bind();
+ intent.putExtra(RestrictionsManager.EXTRA_PACKAGE_NAME, packageName);
+ intent.putExtra(RestrictionsManager.EXTRA_REQUEST_TYPE, requestType);
+ intent.putExtra(RestrictionsManager.EXTRA_REQUEST_BUNDLE, requestData);
+ mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -226,81 +176,5 @@
// Shouldn't happen
}
}
-
- abstract class ProviderServiceConnection
- implements IBinder.DeathRecipient, ServiceConnection {
-
- protected IRestrictionsProvider mRestrictionsProvider;
- private Intent mIntent;
- protected int mUserHandle;
- protected IBinder mResponse;
- private boolean mAbort;
-
- public ProviderServiceConnection(Intent intent, IBinder response, int userHandle) {
- mIntent = intent;
- mResponse = response;
- mUserHandle = userHandle;
- if (mResponse != null) {
- try {
- mResponse.linkToDeath(this, 0 /* flags */);
- } catch (RemoteException re) {
- close();
- }
- }
- }
-
- /** Bind to the RestrictionsProvider process */
- public void bind() {
- if (DEBUG) {
- Log.i(LOG_TAG, "binding to service: " + mIntent);
- }
- mContext.bindServiceAsUser(mIntent, this, Context.BIND_AUTO_CREATE,
- new UserHandle(mUserHandle));
- }
-
- private void close() {
- mAbort = true;
- unbind();
- }
-
- private void unbind() {
- if (DEBUG) {
- Log.i(LOG_TAG, "unbinding from service");
- }
- mContext.unbindService(this);
- }
-
- /** Implement this to call the appropriate method on the service */
- public abstract void run() throws RemoteException;
-
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- if (DEBUG) {
- Log.i(LOG_TAG, "connected to " + name);
- }
- mRestrictionsProvider = IRestrictionsProvider.Stub.asInterface(service);
- if (!mAbort) {
- try {
- run();
- } catch (RemoteException re) {
- Log.w("RestrictionsProvider", "Remote exception: " + re);
- }
- }
- close();
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- if (DEBUG) {
- Log.i(LOG_TAG, "disconnected from " + name);
- }
- mRestrictionsProvider = null;
- }
-
- @Override
- public void binderDied() {
- mAbort = true;
- }
- }
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 5233297..c0923ca 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -656,14 +656,13 @@
}
break;
case MSG_USER_SWITCHED: {
- mCurrentUser = msg.arg1;
-
UserManager userManager =
(UserManager) mContext.getSystemService(Context.USER_SERVICE);
if (userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
Slog.v(TAG, "Switched to user with DISALLOW_USB_FILE_TRANSFER restriction;"
+ " disabling USB.");
setUsbConfig("none");
+ mCurrentUser = msg.arg1;
break;
}
@@ -675,6 +674,7 @@
setUsbConfig("none");
setUsbConfig(mCurrentFunctions);
}
+ mCurrentUser = msg.arg1;
break;
}
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
index a1240f4..4a8623d 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DatabaseHelper.java
@@ -20,11 +20,10 @@
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.hardware.soundtrigger.SoundTrigger;
-import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
-import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.Keyphrase;
+import android.hardware.soundtrigger.KeyphraseSoundModel;
import android.util.Slog;
import java.util.ArrayList;
@@ -32,6 +31,8 @@
import java.util.UUID;
/**
+ * Helper to manage the database of the sound models that have been registered on the device.
+ *
* @hide
*/
public class DatabaseHelper extends SQLiteOpenHelper {
@@ -73,7 +74,7 @@
+ SoundModelContract.KEY_TYPE + " INTEGER,"
+ SoundModelContract.KEY_DATA + " BLOB" + ")";
- public DatabaseHelper(Context context, CursorFactory factory) {
+ public DatabaseHelper(Context context) {
super(context, NAME, null, VERSION);
}
@@ -86,16 +87,13 @@
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // TODO(sansid): For now, drop older tables and recreate new ones.
+ // TODO: For now, drop older tables and recreate new ones.
db.execSQL("DROP TABLE IF EXISTS " + KeyphraseContract.TABLE);
db.execSQL("DROP TABLE IF EXISTS " + SoundModelContract.TABLE);
onCreate(db);
}
- /**
- * TODO(sansid): Change to addOrUpdate to handle changes here.
- */
- public void addKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
+ public boolean addOrUpdateKeyphraseSoundModel(KeyphraseSoundModel soundModel) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
// Generate a random ID for the model.
@@ -103,28 +101,35 @@
values.put(SoundModelContract.KEY_DATA, soundModel.data);
values.put(SoundModelContract.KEY_TYPE, SoundTrigger.SoundModel.TYPE_KEYPHRASE);
- if (db.insert(SoundModelContract.TABLE, null, values) != -1) {
+ boolean status = true;
+ if (db.insertWithOnConflict(
+ SoundModelContract.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE) != -1) {
for (Keyphrase keyphrase : soundModel.keyphrases) {
- addKeyphrase(soundModel.uuid, keyphrase);
+ status &= addKeyphrase(soundModel.uuid, keyphrase);
}
+ return status;
} else {
Slog.w(TAG, "Failed to persist sound model to database");
+ return false;
}
}
/**
* TODO(sansid): Change to addOrUpdate to handle changes here.
*/
- private void addKeyphrase(UUID modelId, SoundTrigger.Keyphrase keyphrase) {
+ private boolean addKeyphrase(UUID modelId, Keyphrase keyphrase) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(KeyphraseContract.KEY_ID, keyphrase.id);
- values.put(KeyphraseContract.KEY_RECOGNITION_MODES, keyphrase.recognitionModes);
+ values.put(KeyphraseContract.KEY_RECOGNITION_MODES, keyphrase.recognitionModeFlags);
values.put(KeyphraseContract.KEY_SOUND_MODEL_ID, keyphrase.id);
- values.put(KeyphraseContract.KEY_HINT_TEXT, keyphrase.text);
+ values.put(KeyphraseContract.KEY_HINT_TEXT, keyphrase.hintText);
values.put(KeyphraseContract.KEY_LOCALE, keyphrase.locale);
- if (db.insert(KeyphraseContract.TABLE, null, values) == -1) {
+ if (db.insert(KeyphraseContract.TABLE, null, values) != -1) {
+ return true;
+ } else {
Slog.w(TAG, "Failed to persist keyphrase to database");
+ return false;
}
}
@@ -171,7 +176,7 @@
String locale = c.getString(c.getColumnIndex(KeyphraseContract.KEY_LOCALE));
String hintText = c.getString(c.getColumnIndex(KeyphraseContract.KEY_HINT_TEXT));
- keyphrases.add(new Keyphrase(id, modes, locale, hintText, users));
+ keyphrases.add(new Keyphrase(id, hintText, locale, modes, users));
} while (c.moveToNext());
}
Keyphrase[] keyphraseArr = new Keyphrase[keyphrases.size()];
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 85042f7..7204695 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -62,11 +62,13 @@
final Context mContext;
final ContentResolver mResolver;
+ final DatabaseHelper mDbHelper;
public VoiceInteractionManagerService(Context context) {
super(context);
mContext = context;
mResolver = context.getContentResolver();
+ mDbHelper = new DatabaseHelper(context);
}
@Override
@@ -264,8 +266,7 @@
final long caller = Binder.clearCallingIdentity();
try {
- // TODO: Add the implementation here.
- return null;
+ return mDbHelper.getKephraseSoundModels();
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -282,8 +283,11 @@
}
final long caller = Binder.clearCallingIdentity();
try {
- // TODO: Add the implementation here.
- return VoiceInteractionManagerService.STATUS_ERROR;
+ if (mDbHelper.addOrUpdateKeyphraseSoundModel(model)) {
+ return STATUS_OK;
+ } else {
+ return STATUS_ERROR;
+ }
} finally {
Binder.restoreCallingIdentity(caller);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 1f40c26..54af5d4 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -87,6 +87,10 @@
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mLock) {
mService = IVoiceInteractionService.Stub.asInterface(service);
+ try {
+ mService.ready();
+ } catch (RemoteException e) {
+ }
}
}
diff --git a/telecomm/java/android/telecomm/Call.java b/telecomm/java/android/telecomm/Call.java
new file mode 100644
index 0000000..9f38d0d
--- /dev/null
+++ b/telecomm/java/android/telecomm/Call.java
@@ -0,0 +1,723 @@
+/*
+ * 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.
+ */
+
+package android.telecomm;
+
+import android.net.Uri;
+import android.os.RemoteException;
+import android.telephony.DisconnectCause;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents an ongoing phone call that the in-call app should present to the user.
+ */
+public final class Call {
+ /**
+ * The state of a {@code Call} when newly created.
+ */
+ public static final int STATE_NEW = 0;
+
+ /**
+ * The state of an outgoing {@code Call} when dialing the remote number, but not yet connected.
+ */
+ public static final int STATE_DIALING = 1;
+
+ /**
+ * The state of an incoming {@code Call} when ringing locally, but not yet connected.
+ */
+ public static final int STATE_RINGING = 2;
+
+ /**
+ * The state of a {@code Call} when in a holding state.
+ */
+ public static final int STATE_HOLDING = 3;
+
+ /**
+ * The state of a {@code Call} when actively supporting conversation.
+ */
+ public static final int STATE_ACTIVE = 4;
+
+ /**
+ * The state of a {@code Call} when no further voice or other communication is being
+ * transmitted, the remote side has been or will inevitably be informed that the {@code Call}
+ * is no longer active, and the local data transport has or inevitably will release resources
+ * associated with this {@code Call}.
+ */
+ public static final int STATE_DISCONNECTED = 7;
+
+ public static class Details {
+ private final Uri mHandle;
+ private final int mHandlePresentation;
+ private final String mCallerDisplayName;
+ private final int mCallerDisplayNamePresentation;
+ private final PhoneAccount mAccount;
+ private final int mCapabilities;
+ private final int mDisconnectCauseCode;
+ private final String mDisconnectCauseMsg;
+ private final long mConnectTimeMillis;
+ private final GatewayInfo mGatewayInfo;
+ private final int mVideoState;
+
+ /**
+ * @return The handle (e.g., phone number) to which the {@code Call} is currently
+ * connected.
+ */
+ public Uri getHandle() {
+ return mHandle;
+ }
+
+ /**
+ * @return The presentation requirements for the handle. See
+ * {@link android.telecomm.CallPropertyPresentation} for valid values.
+ */
+ public int getHandlePresentation() {
+ return mHandlePresentation;
+ }
+
+ /**
+ * @return The display name for the caller.
+ */
+ public String getCallerDisplayName() {
+ return mCallerDisplayName;
+ }
+
+ /**
+ * @return The presentation requirements for the caller display name. See
+ * {@link android.telecomm.CallPropertyPresentation} for valid values.
+ */
+ public int getCallerDisplayNamePresentation() {
+ return mCallerDisplayNamePresentation;
+ }
+
+ /**
+ * @return The {@code PhoneAccount} whereby the {@code Call} is currently being routed.
+ */
+ public PhoneAccount getAccount() {
+ return mAccount;
+ }
+
+ /**
+ * @return A bitmask of the capabilities of the {@code Call}, as defined in
+ * {@link CallCapabilities}.
+ */
+ public int getCapabilities() {
+ return mCapabilities;
+ }
+
+ /**
+ * @return For a {@link #STATE_DISCONNECTED} {@code Call}, the disconnect cause expressed
+ * as a code chosen from among those declared in {@link DisconnectCause}.
+ */
+ public int getDisconnectCauseCode() {
+ return mDisconnectCauseCode;
+ }
+
+ /**
+ * @return For a {@link #STATE_DISCONNECTED} {@code Call}, an optional reason for
+ * disconnection expressed as a free text message.
+ */
+ public String getDisconnectCauseMsg() {
+ return mDisconnectCauseMsg;
+ }
+
+ /**
+ * @return The time the {@code Call} has been connected. This information is updated
+ * periodically, but user interfaces should not rely on this to display any "call time
+ * clock".
+ */
+ public long getConnectTimeMillis() {
+ return mConnectTimeMillis;
+ }
+
+ /**
+ * @return Information about any calling gateway the {@code Call} may be using.
+ */
+ public GatewayInfo getGatewayInfo() {
+ return mGatewayInfo;
+ }
+
+ /**
+ * @return Returns the video state of the {@code Call}.
+ */
+ public int getVideoState() {
+ return mVideoState;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Details) {
+ Details d = (Details) o;
+ return
+ Objects.equals(mHandle, d.mHandle) &&
+ Objects.equals(mHandlePresentation, d.mHandlePresentation) &&
+ Objects.equals(mCallerDisplayName, d.mCallerDisplayName) &&
+ Objects.equals(mCallerDisplayNamePresentation,
+ d.mCallerDisplayNamePresentation) &&
+ Objects.equals(mAccount, d.mAccount) &&
+ Objects.equals(mCapabilities, d.mCapabilities) &&
+ Objects.equals(mDisconnectCauseCode, d.mDisconnectCauseCode) &&
+ Objects.equals(mDisconnectCauseMsg, d.mDisconnectCauseMsg) &&
+ Objects.equals(mConnectTimeMillis, d.mConnectTimeMillis) &&
+ Objects.equals(mGatewayInfo, d.mGatewayInfo) &&
+ Objects.equals(mVideoState, d.mVideoState);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return
+ Objects.hashCode(mHandle) +
+ Objects.hashCode(mHandlePresentation) +
+ Objects.hashCode(mCallerDisplayName) +
+ Objects.hashCode(mCallerDisplayNamePresentation) +
+ Objects.hashCode(mAccount) +
+ Objects.hashCode(mCapabilities) +
+ Objects.hashCode(mDisconnectCauseCode) +
+ Objects.hashCode(mDisconnectCauseMsg) +
+ Objects.hashCode(mConnectTimeMillis) +
+ Objects.hashCode(mGatewayInfo) +
+ Objects.hashCode(mVideoState);
+ }
+
+ /** {@hide} */
+ public Details(
+ Uri handle,
+ int handlePresentation,
+ String callerDisplayName,
+ int callerDisplayNamePresentation,
+ PhoneAccount account,
+ int capabilities,
+ int disconnectCauseCode,
+ String disconnectCauseMsg,
+ long connectTimeMillis,
+ GatewayInfo gatewayInfo,
+ int videoState) {
+ mHandle = handle;
+ mHandlePresentation = handlePresentation;
+ mCallerDisplayName = callerDisplayName;
+ mCallerDisplayNamePresentation = callerDisplayNamePresentation;
+ mAccount = account;
+ mCapabilities = capabilities;
+ mDisconnectCauseCode = disconnectCauseCode;
+ mDisconnectCauseMsg = disconnectCauseMsg;
+ mConnectTimeMillis = connectTimeMillis;
+ mGatewayInfo = gatewayInfo;
+ mVideoState = videoState;
+ }
+ }
+
+ public static abstract class Listener {
+ /**
+ * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
+ *
+ * TODO(ihab): Provide previous state also?
+ *
+ * @param call The {@code Call} invoking this method.
+ * @param state The new state of the {@code Call}.
+ */
+ public void onStateChanged(Call call, int state) {}
+
+ /**
+ * Invoked when the parent of this {@code Call} has changed. See {@link #getParent()}.
+ *
+ * @param call The {@code Call} invoking this method.
+ * @param parent The new parent of the {@code Call}.
+ */
+ public void onParentChanged(Call call, Call parent) {}
+
+ /**
+ * Invoked when the children of this {@code Call} have changed. See {@link #getChildren()}.
+ *
+ * @param call The {@code Call} invoking this method.
+ * @param children The new children of the {@code Call}.
+ */
+ public void onChildrenChanged(Call call, List<Call> children) {}
+
+ /**
+ * Invoked when the details of this {@code Call} have changed. See {@link #getDetails()}.
+ *
+ * @param call The {@code Call} invoking this method.
+ * @param details A {@code Details} object describing the {@code Call}.
+ */
+ public void onDetailsChanged(Call call, Details details) {}
+
+ /**
+ * Invoked when the text messages that can be used as responses to the incoming
+ * {@code Call} are loaded from the relevant database.
+ * See {@link #getCannedTextResponses()}.
+ *
+ * @param call The {@code Call} invoking this method.
+ * @param cannedTextResponses The text messages useable as responses.
+ */
+ public void onCannedTextResponsesLoaded(Call call, List<String> cannedTextResponses) {}
+
+ /**
+ * Invoked when the outgoing {@code Call} has finished dialing but is sending DTMF signals
+ * that were embedded into the outgoing number.
+ *
+ * @param call The {@code Call} invoking this method.
+ * @param remainingPostDialSequence The post-dial characters that remain to be sent.
+ */
+ public void onPostDial(Call call, String remainingPostDialSequence) {}
+
+ /**
+ * Invoked when the post-dial sequence in the outgoing {@code Call} has reached a pause
+ * character. This causes the post-dial signals to stop pending user confirmation. An
+ * implementation should present this choice to the user and invoke
+ * {@link #postDialContinue(boolean)} when the user makes the choice.
+ *
+ * @param call The {@code Call} invoking this method.
+ * @param remainingPostDialSequence The post-dial characters that remain to be sent.
+ */
+ public void onPostDialWait(Call call, String remainingPostDialSequence) {}
+
+ /**
+ * Invoked when the {@code RemoteCallVideoProvider} of the {@code Call} has changed.
+ *
+ * @param call The {@code Call} invoking this method.
+ * @param callVideoProvider The {@code RemoteCallVideoProvider} associated with the
+ * {@code Call}.
+ */
+
+ public void onCallVideoProviderChanged(Call call,
+ RemoteCallVideoProvider callVideoProvider) {}
+
+ /**
+ * Invoked when the {@code Call} is destroyed. Clients should refrain from cleaning
+ * up their UI for the {@code Call} in response to state transitions. Specifically,
+ * clients should not assume that a {@link #onStateChanged(Call, int)} with a state of
+ * {@link #STATE_DISCONNECTED} is the final notification the {@code Call} will send. Rather,
+ * clients should wait for this method to be invoked.
+ *
+ * @param call The {@code Call} being destroyed.
+ */
+ public void onCallDestroyed(Call call) {}
+ }
+
+ private final Phone mPhone;
+ private final String mTelecommCallId;
+ private final InCallAdapter mInCallAdapter;
+ private Call mParent = null;
+ private int mState;
+ private final List<Call> mChildren = new ArrayList<>();
+ private final List<Call> mUnmodifiableChildren = Collections.unmodifiableList(mChildren);
+ private List<String> mCannedTextResponses = null;
+ private String mRemainingPostDialSequence;
+ private RemoteCallVideoProvider mCallVideoProvider;
+ private Details mDetails;
+ private final List<Listener> mListeners = new ArrayList<>();
+
+ /**
+ * Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
+ *
+ * @return The remaining post-dial sequence, or {@code null} if there is no post-dial sequence
+ * remaining or this {@code Call} is not in a post-dial state.
+ */
+ public String getRemainingPostDialSequence() {
+ return mRemainingPostDialSequence;
+ }
+
+ /**
+ * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
+ */
+ public void answer() {
+ mInCallAdapter.answerCall(mTelecommCallId);
+ }
+
+ /**
+ * Instructs this {@link #STATE_RINGING} {@code Call} to reject.
+ *
+ * @param rejectWithMessage Whether to reject with a text message.
+ * @param textMessage An optional text message with which to respond.
+ */
+ public void reject(boolean rejectWithMessage, String textMessage) {
+ mInCallAdapter.rejectCall(mTelecommCallId, rejectWithMessage, textMessage);
+ }
+
+ /**
+ * Instructs this {@code Call} to disconnect.
+ */
+ public void disconnect() {
+ mInCallAdapter.disconnectCall(mTelecommCallId);
+ }
+
+ /**
+ * Instructs this {@code Call} to go on hold.
+ */
+ public void hold() {
+ mInCallAdapter.holdCall(mTelecommCallId);
+ }
+
+ /**
+ * Instructs this {@link #STATE_HOLDING} call to release from hold.
+ */
+ public void unhold() {
+ mInCallAdapter.unholdCall(mTelecommCallId);
+ }
+
+ /**
+ * Instructs this {@code Call} to play a dual-tone multi-frequency signaling (DTMF) tone.
+ *
+ * Any other currently playing DTMF tone in the specified call is immediately stopped.
+ *
+ * @param digit A character representing the DTMF digit for which to play the tone. This
+ * value must be one of {@code '0'} through {@code '9'}, {@code '*'} or {@code '#'}.
+ */
+ public void playDtmfTone(char digit) {
+ mInCallAdapter.playDtmfTone(mTelecommCallId, digit);
+ }
+
+ /**
+ * Instructs this {@code Call} to stop any dual-tone multi-frequency signaling (DTMF) tone
+ * currently playing.
+ *
+ * DTMF tones are played by calling {@link #playDtmfTone(char)}. If no DTMF tone is
+ * currently playing, this method will do nothing.
+ */
+ public void stopDtmfTone() {
+ mInCallAdapter.stopDtmfTone(mTelecommCallId);
+ }
+
+ /**
+ * Instructs this {@code Call} to continue playing a post-dial DTMF string.
+ *
+ * A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
+ * that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
+ * While these tones are playing, this {@code Call} will notify listeners via
+ * {@link Listener#onPostDial(Call, String)}.
+ *
+ * If the DTMF string contains a {@link TelecommConstants#DTMF_CHARACTER_PAUSE} symbol, this
+ * {@code Call} will temporarily pause playing the tones for a pre-defined period of time.
+ *
+ * If the DTMF string contains a {@link TelecommConstants#DTMF_CHARACTER_WAIT} symbol, this
+ * {@code Call} will pause playing the tones and notify listeners via
+ * {@link Listener#onPostDialWait(Call, String)}. At this point, the in-call app
+ * should display to the user an indication of this state and an affordance to continue
+ * the postdial sequence. When the user decides to continue the postdial sequence, the in-call
+ * app should invoke the {@link #postDialContinue(boolean)} method.
+ *
+ * @param proceed Whether or not to continue with the post-dial sequence.
+ */
+ public void postDialContinue(boolean proceed) {
+ mInCallAdapter.postDialContinue(mTelecommCallId, proceed);
+ }
+
+ /**
+ * Notifies this {@code Call} that the phone account user interface element was touched.
+ *
+ * TODO(ihab): Figure out if and how we can generalize this
+ */
+ public void phoneAccountClicked() {
+ mInCallAdapter.phoneAccountClicked(mTelecommCallId);
+ }
+
+ /**
+ * Instructs this {@code Call} to enter a conference.
+ */
+ public void conference() {
+ mInCallAdapter.conference(mTelecommCallId);
+ }
+
+ /**
+ * Instructs this {@code Call} to split from any conference call with which it may be
+ * connected.
+ */
+ public void splitFromConference() {
+ mInCallAdapter.splitFromConference(mTelecommCallId);
+ }
+
+ /**
+ * Instructs this {@code Call} to swap itself with an existing background call, if one
+ * such call exists.
+ */
+ public void swapWithBackgroundCall() {
+ mInCallAdapter.swapWithBackgroundCall(mTelecommCallId);
+ }
+
+ /**
+ * 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
+ * child of any conference {@code Call}s.
+ */
+ public Call getParent() {
+ return mParent;
+ }
+
+ /**
+ * Obtains the children of this conference {@code Call}, if any.
+ *
+ * @return The children of this {@code Call} if this {@code Call} is a conference, or an empty
+ * {@code List} otherwise.
+ */
+ public List<Call> getChildren() {
+ return mUnmodifiableChildren;
+ }
+
+ /**
+ * Obtains the state of this {@code Call}.
+ *
+ * @return A state value, chosen from the {@code STATE_*} constants.
+ */
+ public int getState() {
+ return mState;
+ }
+
+ /**
+ * Obtains a list of canned, pre-configured message responses to present to the user as
+ * ways of rejecting this {@code Call} using via a text message.
+ *
+ * @see #reject(boolean, String)
+ *
+ * @return A list of canned text message responses.
+ */
+ public List<String> getCannedTextResponses() {
+ return mCannedTextResponses;
+ }
+
+ /**
+ * Obtains an object that can be used to display video from this {@code Call}.
+ *
+ * @return An {@code ICallVideoProvider}.
+ */
+ public RemoteCallVideoProvider getCallVideoProvider() {
+ return mCallVideoProvider;
+ }
+
+ /**
+ * Obtains an object containing call details.
+ *
+ * @return A {@link Details} object. Depending on the state of the {@code Call}, the
+ * result may be {@code null}.
+ */
+ public Details getDetails() {
+ return mDetails;
+ }
+
+ /**
+ * Adds a listener to this {@code Call}.
+ *
+ * @param listener A {@code Listener}.
+ */
+ public void addListener(Listener listener) {
+ mListeners.add(listener);
+ }
+
+ /**
+ * Removes a listener from this {@code Call}.
+ *
+ * @param listener A {@code Listener}.
+ */
+ public void removeListener(Listener listener) {
+ mListeners.remove(listener);
+ }
+
+ /** {@hide} */
+ Call(Phone phone, String telecommCallId, InCallAdapter inCallAdapter) {
+ mPhone = phone;
+ mTelecommCallId = telecommCallId;
+ mInCallAdapter = inCallAdapter;
+ mState = STATE_NEW;
+ }
+
+ /** {@hide} */
+ final String internalGetCallId() {
+ return mTelecommCallId;
+ }
+
+ /** {@hide} */
+ final void internalUpdate(InCallCall inCallCall) {
+ // First, we update the internal state as far as possible before firing any updates.
+
+ Details details = new Details(
+ inCallCall.getHandle(),
+ inCallCall.getHandlePresentation(),
+ inCallCall.getCallerDisplayName(),
+ inCallCall.getCallerDisplayNamePresentation(),
+ inCallCall.getAccount(),
+ inCallCall.getCapabilities(),
+ inCallCall.getDisconnectCauseCode(),
+ inCallCall.getDisconnectCauseMsg(),
+ inCallCall.getConnectTimeMillis(),
+ inCallCall.getGatewayInfo(),
+ inCallCall.getVideoState());
+ boolean detailsChanged = !Objects.equals(mDetails, details);
+ if (detailsChanged) {
+ mDetails = details;
+ }
+
+ boolean cannedTextResponsesChanged = false;
+ if (mCannedTextResponses == null && inCallCall.getCannedSmsResponses() != null
+ && !inCallCall.getCannedSmsResponses().isEmpty()) {
+ mCannedTextResponses = Collections.unmodifiableList(inCallCall.getCannedSmsResponses());
+ }
+
+ boolean callVideoProviderChanged = false;
+ try {
+ callVideoProviderChanged =
+ !Objects.equals(mCallVideoProvider, inCallCall.getCallVideoProvider());
+ if (callVideoProviderChanged) {
+ mCallVideoProvider = inCallCall.getCallVideoProvider();
+ }
+ } catch (RemoteException e) {
+ }
+
+ int state = stateFromInCallCallState(inCallCall.getState());
+ boolean stateChanged = mState != state;
+ if (stateChanged) {
+ mState = state;
+ }
+
+ if (inCallCall.getParentCallId() != null) {
+ mParent = mPhone.internalGetCallByTelecommId(inCallCall.getParentCallId());
+ }
+
+ mChildren.clear();
+ if (inCallCall.getChildCallIds() != null) {
+ for (int i = 0; i < inCallCall.getChildCallIds().size(); i++) {
+ mChildren.add(mPhone.internalGetCallByTelecommId(
+ inCallCall.getChildCallIds().get(i)));
+ }
+ }
+
+ // Now we fire updates, ensuring that any client who listens to any of these notifications
+ // gets the most up-to-date state.
+
+ if (stateChanged) {
+ fireStateChanged(mState);
+ }
+ if (detailsChanged) {
+ fireDetailsChanged(mDetails);
+ }
+ if (cannedTextResponsesChanged) {
+ fireCannedTextResponsesLoaded(mCannedTextResponses);
+ }
+ if (callVideoProviderChanged) {
+ fireCallVideoProviderChanged(mCallVideoProvider);
+ }
+
+ // If we have transitioned to DISCONNECTED, that means we need to notify clients and
+ // remove ourselves from the Phone. Note that we do this after completing all state updates
+ // so a client can cleanly transition all their UI to the state appropriate for a
+ // DISCONNECTED Call while still relying on the existence of that Call in the Phone's list.
+ if (mState == STATE_DISCONNECTED) {
+ fireCallDestroyed();
+ mPhone.internalRemoveCall(this);
+ }
+ }
+
+ /** {@hide} */
+ final void internalSetPostDial(String remaining) {
+ mRemainingPostDialSequence = remaining;
+ firePostDial(mRemainingPostDialSequence);
+ }
+
+ /** {@hide} */
+ final void internalSetPostDialWait(String remaining) {
+ mRemainingPostDialSequence = remaining;
+ firePostDialWait(mRemainingPostDialSequence);
+ }
+
+ private void fireStateChanged(int newState) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onStateChanged(this, newState);
+ }
+ }
+
+ private void fireParentChanged(Call newParent) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onParentChanged(this, newParent);
+ }
+ }
+
+ private void fireChildrenChanged(List<Call> children) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onChildrenChanged(this, children);
+ }
+ }
+
+ private void fireDetailsChanged(Details details) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onDetailsChanged(this, details);
+ }
+ }
+
+ private void fireCannedTextResponsesLoaded(List<String> cannedTextResponses) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onCannedTextResponsesLoaded(this, cannedTextResponses);
+ }
+ }
+
+ private void fireCallVideoProviderChanged(RemoteCallVideoProvider callVideoProvider) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onCallVideoProviderChanged(this, callVideoProvider);
+ }
+ }
+
+ private void firePostDial(String remainingPostDialSequence) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onPostDial(this, remainingPostDialSequence);
+ }
+ }
+
+ private void firePostDialWait(String remainingPostDialSequence) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onPostDialWait(this, remainingPostDialSequence);
+ }
+ }
+
+ private void fireCallDestroyed() {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onCallDestroyed(this);
+ }
+ }
+
+ private int stateFromInCallCallState(CallState inCallCallState) {
+ switch (inCallCallState) {
+ case NEW:
+ return STATE_NEW;
+ case DIALING:
+ return STATE_DIALING;
+ case RINGING:
+ return STATE_RINGING;
+ case ACTIVE:
+ return STATE_ACTIVE;
+ case ON_HOLD:
+ return STATE_HOLDING;
+ case DISCONNECTED:
+ return STATE_DISCONNECTED;
+ case ABORTED:
+ return STATE_DISCONNECTED;
+ default:
+ Log.wtf(this, "Unrecognized CallState %s", inCallCallState);
+ return STATE_NEW;
+ }
+ }
+}
diff --git a/telecomm/java/android/telecomm/CallPropertyPresentation.java b/telecomm/java/android/telecomm/CallPropertyPresentation.java
index 350980c..319e565 100644
--- a/telecomm/java/android/telecomm/CallPropertyPresentation.java
+++ b/telecomm/java/android/telecomm/CallPropertyPresentation.java
@@ -19,14 +19,14 @@
/** Defines how numbers and names are displayed in caller id. */
public class CallPropertyPresentation {
/** Property is displayed normally. */
- public static final int ALLOWED = 0;
+ public static final int ALLOWED = 1;
/** Property was blocked. */
- public static final int RESTRICTED = 1;
+ public static final int RESTRICTED = 2;
/** Presentation was not specified or is unknown. */
- public static final int UNKNOWN = 2;
+ public static final int UNKNOWN = 3;
/** Property should be displayed as a pay phone. */
- public static final int PAYPHONE = 3;
+ public static final int PAYPHONE = 4;
}
diff --git a/telecomm/java/android/telecomm/CallServiceDescriptor.java b/telecomm/java/android/telecomm/CallServiceDescriptor.java
deleted file mode 100644
index 5ae07d3..0000000
--- a/telecomm/java/android/telecomm/CallServiceDescriptor.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright 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.
- */
-
-package android.telecomm;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-
-import java.util.Locale;
-import java.util.UUID;
-
-/**
- * An immutable object containing information about a given {@link ConnectionService}. Instances are
- * created using the enclosed {@link Builder}.
- */
-public final class CallServiceDescriptor implements Parcelable {
- private static final String TAG = CallServiceDescriptor.class.getSimpleName();
-
- /**
- * A placeholder value indicating an invalid network type.
- * @hide
- */
- private static final int FLAG_INVALID = 0;
-
- /**
- * Indicates that the device must be connected to a Wi-Fi network in order for the backing
- * {@link ConnectionService} to be used.
- */
- public static final int FLAG_WIFI = 0x01;
-
- /**
- * Indicates that the device must be connected to a cellular PSTN network in order for the
- * backing {@link ConnectionService} to be used.
- */
- public static final int FLAG_PSTN = 0x02;
-
- /**
- * Indicates that the device must be connected to a cellular data network in order for the
- * backing {@link ConnectionService} to be used.
- */
- public static final int FLAG_MOBILE = 0x04;
-
- /**
- * Represents all of the defined FLAG_ constants so validity can be easily checked.
- * @hide
- */
- public static final int FLAG_ALL = FLAG_WIFI | FLAG_PSTN | FLAG_MOBILE;
-
- /**
- * A unique ID used to identify a given instance.
- */
- private final String mConnectionServiceId;
-
- /**
- * The {@link ComponentName} of the {@link ConnectionService} implementation which this is
- * describing.
- */
- private final ComponentName mComponentName;
-
- /**
- * The type of connection that the {@link ConnectionService} requires; will be one of the FLAG_*
- * constants defined in this class.
- */
- private final int mNetworkType;
-
- private CallServiceDescriptor(
- String connectionServiceId,
- ComponentName componentName,
- int networkType) {
-
- mConnectionServiceId = connectionServiceId;
- mComponentName = componentName;
- mNetworkType = networkType;
- }
-
- /**
- * @return The ID used to identify this {@link ConnectionService}.
- */
- public String getConnectionServiceId() {
- return mConnectionServiceId;
- }
-
- /**
- * @return The {@link ComponentName} of the {@link ConnectionService}.
- */
- public ComponentName getServiceComponent() {
- return mComponentName;
- }
-
- /**
- * @return The network type required by the {@link ConnectionService} to place a call.
- */
- public int getNetworkType() {
- return mNetworkType;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
- if (!(obj instanceof CallServiceDescriptor)) {
- return false;
- }
- CallServiceDescriptor descriptor = (CallServiceDescriptor) obj;
- return mConnectionServiceId.equals(descriptor.mConnectionServiceId) &&
- mComponentName.equals(descriptor.mComponentName) &&
- mNetworkType == descriptor.mNetworkType;
- }
-
- @Override
- public String toString() {
- return String.format(Locale.US, "[%s, component: %s]",
- CallServiceDescriptor.class.getSimpleName(),
- mComponentName == null ? "null" : mComponentName.flattenToShortString());
- }
-
- /**
- * @param context {@link Context} to use for the construction of the {@link Builder}.
- * @return A new {@link Builder} instance.
- */
- public static Builder newBuilder(Context context) {
- return new Builder(context);
- }
-
- /**
- * Creates {@link CallServiceDescriptor} instances. Builders should be created with the
- * {@link CallServiceDescriptor#newBuilder(Context)} method.
- */
- public static class Builder {
- /** The {@link Context} to use to verify {@link ComponentName} ownership. */
- private Context mContext;
-
- /** The {@link ComponentName} pointing to the backing {@link ConnectionService}. */
- private ComponentName mComponentName;
-
- /** The required network type that the {@link ConnectionService} needs. */
- private int mNetworkType = FLAG_INVALID;
-
- private Builder(Context context) {
- mContext = context;
- }
-
- /**
- * Set which {@link ConnectionService} this {@link CallServiceDescriptor} is describing.
- *
- * @param serviceClass The {@link ConnectionService} class
- * @return This {@link Builder} for method chaining.
- */
- public Builder setConnectionService(Class<? extends ConnectionService> serviceClass) {
- mComponentName = new ComponentName(mContext, serviceClass);
- return this;
- }
-
- /**
- * Which network type the backing {@link ConnectionService} requires. This must be one of
- * the {@link CallServiceDescriptor}.TYPE_* fields.
- *
- * @param networkType Which network type the backing {@link ConnectionService} requires.
- * @return This {@link Builder} for method chaining.
- */
- public Builder setNetworkType(int networkType) {
- mNetworkType = networkType;
- return this;
- }
-
- /**
- * @return A constructed {@link CallServiceDescriptor} object.
- */
- public CallServiceDescriptor build() {
- // STOPSHIP: Verify validity of ComponentName (permissions, intents, etc)
-
- // Make sure that they passed in a valid network flag combination
- if (mNetworkType == FLAG_INVALID || ((mNetworkType & FLAG_ALL) == 0)) {
-
- Log.wtf(TAG, "Invalid network type for " + mComponentName);
- // Revert them back to TYPE_INVALID so it won't be considered.
- mNetworkType = FLAG_INVALID;
- }
-
- // TODO: Should we use a sha1 of the ComponentName? Would prevent duplicates.
- return new CallServiceDescriptor(
- UUID.randomUUID().toString(), mComponentName, mNetworkType);
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mConnectionServiceId);
- dest.writeParcelable(mComponentName, 0);
- dest.writeInt(mNetworkType);
- }
-
- public static final Creator<CallServiceDescriptor> CREATOR =
- new Creator<CallServiceDescriptor>() {
- @Override
- public CallServiceDescriptor createFromParcel(Parcel source) {
- String id = source.readString();
- ComponentName componentName = source.readParcelable(
- CallServiceDescriptor.class.getClassLoader());
- int networkType = source.readInt();
-
- return new CallServiceDescriptor(id, componentName, networkType);
- }
-
- @Override
- public CallServiceDescriptor[] newArray(int size) {
- return new CallServiceDescriptor[size];
- }
- };
-}
diff --git a/telecomm/java/android/telecomm/CallServiceLookupResponse.java b/telecomm/java/android/telecomm/CallServiceLookupResponse.java
deleted file mode 100644
index dd35a24..0000000
--- a/telecomm/java/android/telecomm/CallServiceLookupResponse.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-package android.telecomm;
-
-import android.os.RemoteException;
-
-import com.android.internal.telecomm.ICallServiceLookupResponse;
-
-import java.util.List;
-
-/**
- * Used by {@link CallServiceProvider} to return a list of {@link CallServiceDescriptor}s.
- */
-public final class CallServiceLookupResponse {
- private final ICallServiceLookupResponse mResponse;
-
- /**
- * {@hide}
- */
- public CallServiceLookupResponse(ICallServiceLookupResponse response) {
- mResponse = response;
- }
-
- /**
- * Passes the sorted list of preferred {@link CallServiceDescriptor}s back to Telecomm. Used
- * in the context of attempting to place a pending outgoing call.
- *
- * @param callServiceDescriptors The set of call-service descriptors from
- * {@link CallServiceProvider}.
- */
- public void setCallServiceDescriptors(List<CallServiceDescriptor> callServiceDescriptors) {
- try {
- mResponse.setCallServiceDescriptors(callServiceDescriptors);
- } catch (RemoteException e) {
- }
- }
-}
diff --git a/telecomm/java/android/telecomm/CallServiceProvider.java b/telecomm/java/android/telecomm/CallServiceProvider.java
deleted file mode 100644
index c50334a..0000000
--- a/telecomm/java/android/telecomm/CallServiceProvider.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2013 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.telecomm;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-
-import com.android.internal.telecomm.ICallServiceLookupResponse;
-import com.android.internal.telecomm.ICallServiceProvider;
-
-/**
- * Base implementation of a call service provider which extends {@link Service}. This class
- * should be extended by an app that wants to supply phone calls to be handled and managed by
- * the device's in-call interface. All method-calls from the framework to the call service provider
- * are passed through to the main thread for before executing the overriden methods of
- * CallServiceProvider.
- *
- * TODO(santoscordon): Improve paragraph above once the final design is in place. Needs more
- * about how this can be used.
- */
-public abstract class CallServiceProvider extends Service {
-
- /**
- * Default Handler used to consolidate binder method calls onto a single thread.
- */
- private final class CallServiceProviderMessageHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_LOOKUP_CALL_SERVICES:
- CallServiceLookupResponse response =
- new CallServiceLookupResponse((ICallServiceLookupResponse) msg.obj);
- lookupCallServices(response);
- break;
- }
- }
- }
-
- /**
- * Default ICallServiceProvider implementation provided to CallsManager via {@link #onBind}.
- */
- private final class CallServiceProviderWrapper extends ICallServiceProvider.Stub {
- /** {@inheritDoc} */
- @Override
- public void lookupCallServices(ICallServiceLookupResponse callServiceLookupResponse) {
- Message message = mMessageHandler.obtainMessage(
- MSG_LOOKUP_CALL_SERVICES, callServiceLookupResponse);
- message.sendToTarget();
- }
- }
-
- // Only used internally by this class.
- // Binder method calls on this service can occur on multiple threads. These messages are used
- // in conjunction with {@link #mMessageHandler} to ensure that all callbacks are handled on a
- // single thread. Keeping it on a single thread allows CallService implementations to avoid
- // needing multi-threaded code in their own callback routines.
- private static final int MSG_LOOKUP_CALL_SERVICES = 1;
-
- /**
- * Message handler for consolidating binder callbacks onto a single thread.
- * See {@link CallServiceProviderMessageHandler}.
- */
- private final CallServiceProviderMessageHandler mMessageHandler;
-
- /**
- * Default binder implementation of {@link ICallServiceProvider} interface.
- */
- private final CallServiceProviderWrapper mBinder;
-
- /**
- * Protected constructor called only by subclasses creates the binder interface and
- * single-threaded message handler.
- */
- protected CallServiceProvider() {
- mMessageHandler = new CallServiceProviderMessageHandler();
- mBinder = new CallServiceProviderWrapper();
- }
-
- /** {@inheritDoc} */
- @Override
- public IBinder onBind(Intent intent) {
- return mBinder;
- }
-
- /**
- * Initiates the process to retrieve the list of {@link CallServiceDescriptor}s implemented by
- * this provider.
- *
- * @param response The response object through which the list of call services is sent.
- */
- public abstract void lookupCallServices(CallServiceLookupResponse response);
-}
diff --git a/telecomm/java/android/telecomm/CallState.java b/telecomm/java/android/telecomm/CallState.java
index 152c2023..a464da5 100644
--- a/telecomm/java/android/telecomm/CallState.java
+++ b/telecomm/java/android/telecomm/CallState.java
@@ -48,22 +48,6 @@
RINGING,
/**
- * Indicates that the call is active but in a "post-dial" state where Telecomm is now sending
- * some dual-tone multi-frequency signaling (DTMF) tones appended to the dialed number. Normal
- * transitions are to {@link #POST_DIAL_WAIT} when the post-dial string requires user
- * confirmation to proceed, {@link #ACTIVE} when the post-dial tones are completed, or
- * {@link #DISCONNECTED}.
- */
- POST_DIAL,
-
- /**
- * Indicates that the call was in the {@link #POST_DIAL} state but is now waiting for user
- * confirmation before the remaining digits can be sent. Normal transitions are to
- * {@link #POST_DIAL} when the user asks Telecomm to proceed with the post-dial sequence.
- */
- POST_DIAL_WAIT,
-
- /**
* Indicates that a call is currently connected to another party and a communication channel is
* open between them. The normal transition to this state is by the user answering a
* {@link #DIALING} call or a {@link #RINGING} call being answered by the other party.
diff --git a/telecomm/java/android/telecomm/CallVideoClient.java b/telecomm/java/android/telecomm/CallVideoClient.java
index 76b28fa..fb970dc 100644
--- a/telecomm/java/android/telecomm/CallVideoClient.java
+++ b/telecomm/java/android/telecomm/CallVideoClient.java
@@ -241,6 +241,7 @@
*
* @param callCameraCapabilities The changed camera capabilities.
*/
- public abstract void onHandleCameraCapabilitiesChange(CallCameraCapabilities callCameraCapabilities);
+ public abstract void onHandleCameraCapabilitiesChange(
+ CallCameraCapabilities callCameraCapabilities);
}
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index fb820f0..db834a4 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -44,9 +44,9 @@
public void onDestroyed(Connection c) {}
public void onCallCapabilitiesChanged(Connection c, int callCapabilities) {}
public void onParentConnectionChanged(Connection c, Connection parent) {}
- public void onSetCallVideoProvider(Connection c, CallVideoProvider callVideoProvider) {}
- public void onSetAudioModeIsVoip(Connection c, boolean isVoip) {}
- public void onSetStatusHints(Connection c, StatusHints statusHints) {}
+ public void onCallVideoProviderChanged(Connection c, CallVideoProvider callVideoProvider) {}
+ public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {}
+ public void onStatusHintsChanged(Connection c, StatusHints statusHints) {}
}
public final class State {
@@ -321,7 +321,7 @@
public final void setCallVideoProvider(CallVideoProvider callVideoProvider) {
mCallVideoProvider = callVideoProvider;
for (Listener l : mListeners) {
- l.onSetCallVideoProvider(this, callVideoProvider);
+ l.onCallVideoProviderChanged(this, callVideoProvider);
}
}
@@ -415,7 +415,7 @@
public final void setAudioModeIsVoip(boolean isVoip) {
mAudioModeIsVoip = isVoip;
for (Listener l : mListeners) {
- l.onSetAudioModeIsVoip(this, isVoip);
+ l.onAudioModeIsVoipChanged(this, isVoip);
}
}
@@ -427,7 +427,7 @@
public final void setStatusHints(StatusHints statusHints) {
mStatusHints = statusHints;
for (Listener l : mListeners) {
- l.onSetStatusHints(this, statusHints);
+ l.onStatusHintsChanged(this, statusHints);
}
}
@@ -516,7 +516,6 @@
*/
protected void onPhoneAccountClicked() {}
-
private void addChild(Connection connection) {
Log.d(this, "adding child %s", connection);
mChildConnections.add(connection);
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
index 0db9e29..5888d6a 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.java
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -30,11 +30,11 @@
// TODO: Token to limit recursive invocations
// TODO: Consider upgrading "mHandle" to ordered list of handles, indicating a set of phone
// numbers that would satisfy the client's needs, in order of preference
+ private final PhoneAccount mAccount;
private final String mCallId;
private final Uri mHandle;
private final int mHandlePresentation;
private final Bundle mExtras;
- private final PhoneAccount mAccount;
private final int mVideoState;
/**
@@ -61,6 +61,15 @@
mVideoState = videoState;
}
+ private ConnectionRequest(Parcel in) {
+ mAccount = in.readParcelable(getClass().getClassLoader());
+ mCallId = in.readString();
+ mHandle = in.readParcelable(getClass().getClassLoader());
+ mHandlePresentation = in.readInt();
+ mExtras = in.readParcelable(getClass().getClassLoader());
+ mVideoState = in.readInt();
+ }
+
/**
* The account which should be used to place the call.
*/
@@ -109,26 +118,17 @@
mExtras == null ? "" : mExtras);
}
- public static final Parcelable.Creator<ConnectionRequest> CREATOR =
- new Parcelable.Creator<ConnectionRequest> () {
- @Override
- public ConnectionRequest createFromParcel(Parcel source) {
- PhoneAccount account = (PhoneAccount) source.readParcelable(
- getClass().getClassLoader());
- String callId = source.readString();
- Uri handle = (Uri) source.readParcelable(getClass().getClassLoader());
- int presentation = source.readInt();
- Bundle extras = (Bundle) source.readParcelable(getClass().getClassLoader());
- int videoState = source.readInt();
- return new ConnectionRequest(
- account, callId, handle, presentation, extras, videoState);
- }
+ public static final Creator<ConnectionRequest> CREATOR = new Creator<ConnectionRequest> () {
+ @Override
+ public ConnectionRequest createFromParcel(Parcel source) {
+ return new ConnectionRequest(source);
+ }
- @Override
- public ConnectionRequest[] newArray(int size) {
- return new ConnectionRequest[size];
- }
- };
+ @Override
+ public ConnectionRequest[] newArray(int size) {
+ return new ConnectionRequest[size];
+ }
+ };
/**
* {@inheritDoc}
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 1966081..2a6804b 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -47,22 +47,21 @@
private static final Connection NULL_CONNECTION = new Connection() {};
private static final int MSG_ADD_CALL_SERVICE_ADAPTER = 1;
- private static final int MSG_CALL = 2;
+ private static final int MSG_CREATE_CONNECTION = 2;
private static final int MSG_ABORT = 3;
- private static final int MSG_CREATE_INCOMING_CALL = 4;
- private static final int MSG_ANSWER = 5;
- private static final int MSG_REJECT = 6;
- private static final int MSG_DISCONNECT = 7;
- private static final int MSG_HOLD = 8;
- private static final int MSG_UNHOLD = 9;
- private static final int MSG_ON_AUDIO_STATE_CHANGED = 10;
- private static final int MSG_PLAY_DTMF_TONE = 11;
- private static final int MSG_STOP_DTMF_TONE = 12;
- private static final int MSG_CONFERENCE = 13;
- private static final int MSG_SPLIT_FROM_CONFERENCE = 14;
- private static final int MSG_SWAP_WITH_BACKGROUND_CALL = 15;
- private static final int MSG_ON_POST_DIAL_CONTINUE = 16;
- private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 17;
+ private static final int MSG_ANSWER = 4;
+ private static final int MSG_REJECT = 5;
+ private static final int MSG_DISCONNECT = 6;
+ private static final int MSG_HOLD = 7;
+ private static final int MSG_UNHOLD = 8;
+ private static final int MSG_ON_AUDIO_STATE_CHANGED = 9;
+ private static final int MSG_PLAY_DTMF_TONE = 10;
+ private static final int MSG_STOP_DTMF_TONE = 11;
+ private static final int MSG_CONFERENCE = 12;
+ private static final int MSG_SPLIT_FROM_CONFERENCE = 13;
+ private static final int MSG_SWAP_WITH_BACKGROUND_CALL = 14;
+ private static final int MSG_ON_POST_DIAL_CONTINUE = 15;
+ private static final int MSG_ON_PHONE_ACCOUNT_CLICKED = 16;
private final Map<String, Connection> mConnectionById = new HashMap<>();
private final Map<Connection, String> mIdByConnection = new HashMap<>();
@@ -74,11 +73,11 @@
private final ConnectionServiceAdapter mAdapter = new ConnectionServiceAdapter();
/**
- * A callback for providing the resuilt of creating a connection.
+ * A callback for providing the result of creating a connection.
*/
- public interface OutgoingCallResponse<CONNECTION> {
+ public interface CreateConnectionResponse<CONNECTION> {
/**
- * Tells Telecomm that an attempt to place the specified outgoing call succeeded.
+ * Tells Telecomm that an attempt to create the connection succeeded.
*
* @param request The original request.
* @param connection The connection.
@@ -86,7 +85,8 @@
void onSuccess(ConnectionRequest request, CONNECTION connection);
/**
- * Tells Telecomm that an attempt to place the specified outgoing call failed.
+ * Tells Telecomm that an attempt to create the connection failed. Telecomm will try a
+ * different service until a service cancels the process or completes it successfully.
*
* @param request The original request.
* @param code An integer code indicating the reason for failure.
@@ -95,7 +95,8 @@
void onFailure(ConnectionRequest request, int code, String msg);
/**
- * Tells Telecomm to cancel the call.
+ * Tells Telecomm to cancel creating the connection. Telecomm will stop trying to create
+ * the connection an no more services will be tried.
*
* @param request The original request.
*/
@@ -109,8 +110,9 @@
}
@Override
- public void call(ConnectionRequest request) {
- mHandler.obtainMessage(MSG_CALL, request).sendToTarget();
+ public void createConnection(ConnectionRequest request, boolean isIncoming) {
+ mHandler.obtainMessage(
+ MSG_CREATE_CONNECTION, isIncoming ? 1 : 0, 0, request).sendToTarget();
}
@Override
@@ -119,11 +121,6 @@
}
@Override
- public void createIncomingCall(ConnectionRequest request) {
- mHandler.obtainMessage(MSG_CREATE_INCOMING_CALL, request).sendToTarget();
- }
-
- @Override
public void answer(String callId) {
mHandler.obtainMessage(MSG_ANSWER, callId).sendToTarget();
}
@@ -206,15 +203,12 @@
mAdapter.addAdapter((IConnectionServiceAdapter) msg.obj);
onAdapterAttached();
break;
- case MSG_CALL:
- call((ConnectionRequest) msg.obj);
+ case MSG_CREATE_CONNECTION:
+ createConnection((ConnectionRequest) msg.obj, msg.arg1 == 1);
break;
case MSG_ABORT:
abort((String) msg.obj);
break;
- case MSG_CREATE_INCOMING_CALL:
- createIncomingCall((ConnectionRequest) msg.obj);
- break;
case MSG_ANSWER:
answer((String) msg.obj);
break;
@@ -370,19 +364,19 @@
}
@Override
- public void onSetCallVideoProvider(Connection c, CallVideoProvider callVideoProvider) {
+ public void onCallVideoProviderChanged(Connection c, CallVideoProvider callVideoProvider) {
String id = mIdByConnection.get(c);
mAdapter.setCallVideoProvider(id, callVideoProvider);
}
@Override
- public void onSetAudioModeIsVoip(Connection c, boolean isVoip) {
+ public void onAudioModeIsVoipChanged(Connection c, boolean isVoip) {
String id = mIdByConnection.get(c);
mAdapter.setAudioModeIsVoip(id, isVoip);
}
@Override
- public void onSetStatusHints(Connection c, StatusHints statusHints) {
+ public void onStatusHintsChanged(Connection c, StatusHints statusHints) {
String id = mIdByConnection.get(c);
mAdapter.setStatusHints(id, statusHints);
}
@@ -394,29 +388,39 @@
return mBinder;
}
- private void call(final ConnectionRequest originalRequest) {
+ /**
+ * This can be used by telecomm to either create a new outgoing call or attach to an existing
+ * incoming call. In either case, telecomm will cycle through a set of services and call
+ * createConnection util a connection service cancels the process or completes it successfully.
+ */
+ private void createConnection(ConnectionRequest originalRequest, boolean isIncoming) {
Log.d(this, "call %s", originalRequest);
- onCreateConnections(
- originalRequest,
- new OutgoingCallResponse<Connection>() {
- @Override
- public void onSuccess(ConnectionRequest request, Connection connection) {
- Log.d(this, "adapter handleSuccessfulOutgoingCall %s", request.getCallId());
- mAdapter.handleSuccessfulOutgoingCall(request);
- addConnection(request.getCallId(), connection);
- }
+ CreateConnectionResponse response = new CreateConnectionResponse<Connection>() {
+ @Override
+ public void onSuccess(ConnectionRequest request, Connection connection) {
+ Log.d(this, "adapter handleCreateConnectionSuccessful %s",
+ request.getCallId());
+ mAdapter.handleCreateConnectionSuccessful(request);
+ addConnection(request.getCallId(), connection);
+ }
- @Override
- public void onFailure(ConnectionRequest request, int code, String msg) {
- mAdapter.handleFailedOutgoingCall(request, code, msg);
- }
+ @Override
+ public void onFailure(ConnectionRequest request, int code, String msg) {
+ // Tell telecomm to try a different service.
+ mAdapter.handleCreateConnectionFailed(request, code, msg);
+ }
- @Override
- public void onCancel(ConnectionRequest request) {
- mAdapter.cancelOutgoingCall(request);
- }
- }
- );
+ @Override
+ public void onCancel(ConnectionRequest request) {
+ // Tell telecomm not to attempt any more services.
+ mAdapter.handleCreateConnectionCancelled(request);
+ }
+ };
+ if (isIncoming) {
+ onCreateIncomingConnection(originalRequest, response);
+ } else {
+ onCreateOutgoingConnection(originalRequest, response);
+ }
}
private void abort(String callId) {
@@ -424,33 +428,6 @@
findConnectionForAction(callId, "abort").onAbort();
}
- private void createIncomingCall(ConnectionRequest originalRequest) {
- Log.d(this, "createIncomingCall %s", originalRequest);
- onCreateIncomingConnection(
- originalRequest,
- new Response<ConnectionRequest, Connection>() {
- @Override
- public void onResult(ConnectionRequest request, Connection... result) {
- if (result != null && result.length != 1) {
- for (Connection c : result) {
- c.onAbort();
- }
- } else {
- addConnection(request.getCallId(), result[0]);
- Log.d(this, "adapter notifyIncomingCall %s", request);
- mAdapter.notifyIncomingCall(request);
- }
- }
-
- @Override
- public void onError(ConnectionRequest request, int code, String msg) {
- Log.d(this, "adapter failed createIncomingCall %s %d %s",
- request, code, msg);
- }
- }
- );
- }
-
private void answer(String callId) {
Log.d(this, "answer %s", callId);
findConnectionForAction(callId, "answer").onAnswer();
@@ -570,7 +547,7 @@
IConnectionService.Stub.asInterface(services.get(i)));
}
mAreAccountsInitialized = true;
- Log.d(this, "remote call services found: " + services);
+ Log.d(this, "remote connection services found: " + services);
maybeRespondToAccountLookup();
}
});
@@ -606,10 +583,16 @@
}
}
+ public final void createRemoteIncomingConnection(
+ ConnectionRequest request,
+ CreateConnectionResponse<RemoteConnection> response) {
+ mRemoteConnectionManager.createRemoteConnection(request, response, true);
+ }
+
public final void createRemoteOutgoingConnection(
ConnectionRequest request,
- OutgoingCallResponse<RemoteConnection> response) {
- mRemoteConnectionManager.createOutgoingConnection(request, response);
+ CreateConnectionResponse<RemoteConnection> response) {
+ mRemoteConnectionManager.createRemoteConnection(request, response, false);
}
/**
@@ -620,14 +603,25 @@
}
/**
- * Create a Connection given a request.
+ * Create a Connection given an incoming request. This is used to attach to existing incoming
+ * calls.
*
- * @param request Data encapsulating details of the desired Connection.
+ * @param request Details about the incoming call.
* @param callback A callback for providing the result.
*/
- protected void onCreateConnections(
+ protected void onCreateIncomingConnection(
ConnectionRequest request,
- OutgoingCallResponse<Connection> callback) {}
+ CreateConnectionResponse<Connection> callback) {}
+
+ /**
+ * Create a Connection given an outgoing request. This is used to initiate new outgoing calls.
+ *
+ * @param request Details about the outgoing call.
+ * @param callback A callback for providing the result.
+ */
+ protected void onCreateOutgoingConnection(
+ ConnectionRequest request,
+ CreateConnectionResponse<Connection> callback) {}
/**
* Returns a new or existing conference connection when the the user elects to convert the
@@ -645,21 +639,6 @@
Response<String, Connection> callback) {}
/**
- * Create a Connection to match an incoming connection notification.
- *
- * IMPORTANT: If the incoming connection has a phone number (or other handle) that the user
- * is not supposed to be able to see (e.g. it is PRESENTATION_RESTRICTED), then a compliant
- * ConnectionService implementation MUST NOT reveal this phone number as part of the Intent
- * it sends to notify Telecomm of an incoming connection.
- *
- * @param request Data encapsulating details of the desired Connection.
- * @param callback A callback for providing the result.
- */
- protected void onCreateIncomingConnection(
- ConnectionRequest request,
- Response<ConnectionRequest, Connection> callback) {}
-
- /**
* Notifies that a connection has been added to this connection service and sent to Telecomm.
*
* @param connection The connection which was added.
diff --git a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
index b90dec3..a812fa4 100644
--- a/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecomm/ConnectionServiceAdapter.java
@@ -73,65 +73,28 @@
}
}
- /**
- * Provides Telecomm with the details of an incoming call. An invocation of this method must
- * follow {@link ConnectionService#setIncomingCallId} and use the call ID specified therein.
- * Upon the invocation of this method, Telecomm will bring up the incoming-call interface where
- * the user can elect to answer or reject a call.
- *
- * @param request The connection request.
- */
- void notifyIncomingCall(ConnectionRequest request) {
+ void handleCreateConnectionSuccessful(ConnectionRequest request) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.notifyIncomingCall(request);
+ adapter.handleCreateConnectionSuccessful(request);
} catch (RemoteException e) {
}
}
}
- /**
- * Tells Telecomm that an attempt to place the specified outgoing call succeeded.
- *
- * @param request The originating request for a connection.
- */
- void handleSuccessfulOutgoingCall(ConnectionRequest request) {
+ void handleCreateConnectionFailed(ConnectionRequest request, int errorCode, String errorMsg) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.handleSuccessfulOutgoingCall(request);
+ adapter.handleCreateConnectionFailed(request, errorCode, errorMsg);
} catch (RemoteException e) {
}
}
}
- /**
- * Tells Telecomm that an attempt to place the specified outgoing call failed.
- *
- * @param request The originating request for a connection.
- * @param errorCode The error code associated with the failed call attempt.
- * @param errorMsg The error message associated with the failed call attempt.
- */
- void handleFailedOutgoingCall(
- ConnectionRequest request,
- int errorCode,
- String errorMsg) {
+ void handleCreateConnectionCancelled(ConnectionRequest request) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.handleFailedOutgoingCall(request, errorCode, errorMsg);
- } catch (RemoteException e) {
- }
- }
- }
-
- /**
- * Tells Telecomm to cancel the call.
- *
- * @param request The originating request for a connection.
- */
- void cancelOutgoingCall(ConnectionRequest request) {
- for (IConnectionServiceAdapter adapter : mAdapters) {
- try {
- adapter.cancelOutgoingCall(request);
+ adapter.handleCreateConnectionCancelled(request);
} catch (RemoteException e) {
}
}
diff --git a/telecomm/java/android/telecomm/InCallAdapter.java b/telecomm/java/android/telecomm/InCallAdapter.java
index d8293a5..66cf1df 100644
--- a/telecomm/java/android/telecomm/InCallAdapter.java
+++ b/telecomm/java/android/telecomm/InCallAdapter.java
@@ -24,7 +24,7 @@
* Receives commands from {@link InCallService} implementations which should be executed by
* Telecomm. When Telecomm binds to a {@link InCallService}, an instance of this class is given to
* the in-call service through which it can manipulate live (active, dialing, ringing) calls. When
- * the in-call service is notified of new calls ({@link InCallService#addCall}), it can use the
+ * the in-call service is notified of new calls, it can use the
* given call IDs to execute commands such as {@link #answerCall} for incoming calls or
* {@link #disconnectCall} for active calls the user would like to end. Some commands are only
* appropriate for calls in certain states; please consult each method for such limitations.
@@ -167,16 +167,15 @@
* A post-dial DTMF string is a string of digits entered after a phone number, when dialed,
* that are immediately sent as DTMF tones to the recipient as soon as the connection is made.
* While these tones are playing, Telecomm will notify the {@link InCallService} that the call
- * is in the {@link InCallService#setPostDial(String,String)} state.
+ * is in the post dial state.
*
* If the DTMF string contains a {@link TelecommConstants#DTMF_CHARACTER_PAUSE} symbol, Telecomm
* will temporarily pause playing the tones for a pre-defined period of time.
*
* If the DTMF string contains a {@link TelecommConstants#DTMF_CHARACTER_WAIT} symbol, Telecomm
* will pause playing the tones and notify the {@link InCallService} that the call is in the
- * {@link InCallService#setPostDialWait(String,String)} state. When the user decides to continue
- * the postdial sequence, the {@link InCallService} should invoke the
- * {@link #postDialContinue(String,boolean)} method.
+ * post dial wait state. When the user decides to continue the postdial sequence, the
+ * {@link InCallService} should invoke the {@link #postDialContinue(String,boolean)} method.
*
* @param callId The unique ID of the call for which postdial string playing should continue.
* @param proceed Whether or not to continue with the post-dial sequence.
diff --git a/telecomm/java/android/telecomm/InCallCall.java b/telecomm/java/android/telecomm/InCallCall.java
index 7c35020..db8395c 100644
--- a/telecomm/java/android/telecomm/InCallCall.java
+++ b/telecomm/java/android/telecomm/InCallCall.java
@@ -45,12 +45,12 @@
private final int mCallerDisplayNamePresentation;
private final GatewayInfo mGatewayInfo;
private final PhoneAccount mAccount;
- private final CallServiceDescriptor mCurrentCallServiceDescriptor;
private final ICallVideoProvider mCallVideoProvider;
private RemoteCallVideoProvider mRemoteCallVideoProvider;
private final String mParentCallId;
private final List<String> mChildCallIds;
private final StatusHints mStatusHints;
+ private final int mVideoState;
/** @hide */
public InCallCall(
@@ -67,11 +67,11 @@
int callerDisplayNamePresentation,
GatewayInfo gatewayInfo,
PhoneAccount account,
- CallServiceDescriptor descriptor,
ICallVideoProvider callVideoProvider,
String parentCallId,
List<String> childCallIds,
- StatusHints statusHints) {
+ StatusHints statusHints,
+ int videoState) {
mId = id;
mState = state;
mDisconnectCauseCode = disconnectCauseCode;
@@ -85,11 +85,11 @@
mCallerDisplayNamePresentation = callerDisplayNamePresentation;
mGatewayInfo = gatewayInfo;
mAccount = account;
- mCurrentCallServiceDescriptor = descriptor;
mCallVideoProvider = callVideoProvider;
mParentCallId = parentCallId;
mChildCallIds = childCallIds;
mStatusHints = statusHints;
+ mVideoState = videoState;
}
/** The unique ID of the call. */
@@ -165,11 +165,6 @@
return mAccount;
}
- /** The descriptor for the call service currently routing this call. */
- public CallServiceDescriptor getCurrentCallServiceDescriptor() {
- return mCurrentCallServiceDescriptor;
- }
-
/**
* Returns an object for remotely communicating through the call video provider's binder.
* @return The call video provider.
@@ -212,6 +207,14 @@
return mStatusHints;
}
+ /**
+ * The video state.
+ * @return The video state of the call.
+ */
+ public int getVideoState() {
+ return mVideoState;
+ }
+
/** Responsible for creating InCallCall objects for deserialized Parcels. */
public static final Parcelable.Creator<InCallCall> CREATOR =
new Parcelable.Creator<InCallCall> () {
@@ -232,18 +235,18 @@
int callerDisplayNamePresentation = source.readInt();
GatewayInfo gatewayInfo = source.readParcelable(classLoader);
PhoneAccount account = source.readParcelable(classLoader);
- CallServiceDescriptor descriptor = source.readParcelable(classLoader);
ICallVideoProvider callVideoProvider =
ICallVideoProvider.Stub.asInterface(source.readStrongBinder());
String parentCallId = source.readString();
List<String> childCallIds = new ArrayList<>();
source.readList(childCallIds, classLoader);
StatusHints statusHints = source.readParcelable(classLoader);
+ int videoState = source.readInt();
return new InCallCall(id, state, disconnectCauseCode, disconnectCauseMsg,
cannedSmsResponses, capabilities, connectTimeMillis, handle, handlePresentation,
callerDisplayName, callerDisplayNamePresentation, gatewayInfo,
- account, descriptor, callVideoProvider, parentCallId, childCallIds,
- statusHints);
+ account, callVideoProvider, parentCallId, childCallIds, statusHints,
+ videoState);
}
@Override
@@ -274,12 +277,12 @@
destination.writeInt(mCallerDisplayNamePresentation);
destination.writeParcelable(mGatewayInfo, 0);
destination.writeParcelable(mAccount, 0);
- destination.writeParcelable(mCurrentCallServiceDescriptor, 0);
destination.writeStrongBinder(
mCallVideoProvider != null ? mCallVideoProvider.asBinder() : null);
destination.writeString(mParentCallId);
destination.writeList(mChildCallIds);
destination.writeParcelable(mStatusHints, 0);
+ destination.writeInt(mVideoState);
}
@Override
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index 31291fb..028b6e4 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -16,8 +16,6 @@
package android.telecomm;
-import android.app.Service;
-import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -31,11 +29,10 @@
* This service is implemented by any app that wishes to provide the user-interface for managing
* phone calls. Telecomm binds to this service while there exists a live (active or incoming)
* call, and uses it to notify the in-call app of any live and and recently disconnected calls.
- * TODO(santoscordon): Needs more/better description of lifecycle once the interface is better
- * defined.
+ *
* TODO(santoscordon): What happens if two or more apps on a given device implement this interface?
*/
-public abstract class InCallService extends Service {
+public abstract class InCallService {
private static final int MSG_SET_IN_CALL_ADAPTER = 1;
private static final int MSG_ADD_CALL = 2;
private static final int MSG_UPDATE_CALL = 3;
@@ -50,21 +47,21 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_IN_CALL_ADAPTER:
- mAdapter = new InCallAdapter((IInCallAdapter) msg.obj);
- onAdapterAttached(mAdapter);
+ mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
+ onPhoneCreated(mPhone);
break;
case MSG_ADD_CALL:
- addCall((InCallCall) msg.obj);
+ mPhone.internalAddCall((InCallCall) msg.obj);
break;
case MSG_UPDATE_CALL:
- updateCall((InCallCall) msg.obj);
+ mPhone.internalUpdateCall((InCallCall) msg.obj);
break;
- case MSG_SET_POST_DIAL: {
+ case MSG_SET_POST_DIAL: {
SomeArgs args = (SomeArgs) msg.obj;
try {
String callId = (String) args.arg1;
String remaining = (String) args.arg2;
- setPostDial(callId, remaining);
+ mPhone.internalSetPostDial(callId, remaining);
} finally {
args.recycle();
}
@@ -75,17 +72,17 @@
try {
String callId = (String) args.arg1;
String remaining = (String) args.arg2;
- setPostDialWait(callId, remaining);
+ mPhone.internalSetPostDialWait(callId, remaining);
} finally {
args.recycle();
}
break;
}
case MSG_ON_AUDIO_STATE_CHANGED:
- onAudioStateChanged((CallAudioState) msg.obj);
+ mPhone.internalAudioStateChanged((CallAudioState) msg.obj);
break;
case MSG_BRING_TO_FOREGROUND:
- bringToForeground(msg.arg1 == 1);
+ mPhone.internalBringToForeground(msg.arg1 == 1);
break;
default:
break;
@@ -142,85 +139,41 @@
}
}
- private final InCallServiceBinder mBinder;
+ private Phone mPhone;
- private InCallAdapter mAdapter;
+ protected InCallService() {}
- protected InCallService() {
- mBinder = new InCallServiceBinder();
- }
-
- @Override
- public final IBinder onBind(Intent intent) {
- return mBinder;
+ public final IBinder getBinder() {
+ return new InCallServiceBinder();
}
/**
- * @return The attached {@link InCallAdapter} if attached, or null otherwise.
+ * Obtain the {@code Phone} associated with this {@code InCallService}.
+ *
+ * @return The {@code Phone} object associated with this {@code InCallService}, or {@code null}
+ * if the {@code InCallService} is not in a state where it has an associated {@code Phone}.
*/
- protected final InCallAdapter getAdapter() {
- return mAdapter;
+ public Phone getPhone() {
+ return mPhone;
}
/**
- * Lifecycle callback which is called when this {@link InCallService} has been attached
- * to a {@link InCallAdapter}, indicating {@link #getAdapter()} is now safe to use.
+ * Invoked when the {@code Phone} has been created. This is a signal to the in-call experience
+ * to start displaying in-call information to the user. Each instance of {@code InCallService}
+ * will have only one {@code Phone}, and this method will be called exactly once in the
+ * lifetime of the {@code InCallService}.
*
- * @param adapter The adapter now attached to this in-call service.
+ * @param phone The {@code Phone} object associated with this {@code InCallService}.
*/
- protected void onAdapterAttached(InCallAdapter adapter) {
- }
+ public void onPhoneCreated(Phone phone) { }
/**
- * Indicates to the in-call app that a new call has been created and an appropriate
- * user-interface should be built and shown to notify the user.
+ * Invoked when a {@code Phone} has been destroyed. This is a signal to the in-call experience
+ * to stop displaying in-call information to the user. This method will be called exactly once
+ * in the lifetime of the {@code InCallService}, and it will always be called after a previous
+ * call to {@link #onPhoneCreated(Phone)}.
*
- * @param call Information about the new call.
+ * @param phone The {@code Phone} object associated with this {@code InCallService}.
*/
- protected abstract void addCall(InCallCall call);
-
- /**
- * Call when information about a call has changed.
- *
- * @param call Information about the new call.
- */
- protected abstract void updateCall(InCallCall call);
-
- /**
- * Indicates to the in-call app that the specified call is active but in a "post-dial" state
- * where Telecomm is now sending some dual-tone multi-frequency signaling (DTMF) tones appended
- * to the dialed number. Normal transitions are to {@link #setPostDialWait(String,String)} when
- * the post-dial string requires user confirmation to proceed, and {@link CallState#ACTIVE} when
- * the post-dial tones are completed.
- *
- * @param callId The identifier of the call changing state.
- * @param remaining The remaining postdial string to be dialed.
- */
- protected abstract void setPostDial(String callId, String remaining);
-
- /**
- * Indicates to the in-call app that the specified call was in the
- * {@link #setPostDial(String,String)} state but is now waiting for user confirmation before the
- * remaining digits can be sent. Normal transitions are to {@link #setPostDial(String,String)}
- * when the user asks Telecomm to proceed with the post-dial sequence and the in-call app
- * informs Telecomm of this by invoking {@link InCallAdapter#postDialContinue(String,boolean)}.
- *
- * @param callId The identifier of the call changing state.
- * @param remaining The remaining postdial string to be dialed.
- */
- protected abstract void setPostDialWait(String callId, String remaining);
-
- /**
- * Called when the audio state changes.
- *
- * @param audioState The new {@link CallAudioState}.
- */
- protected abstract void onAudioStateChanged(CallAudioState audioState);
-
- /**
- * Brings the in-call screen to the foreground.
- *
- * @param showDialpad If true, put up the dialpad when the screen is shown.
- */
- protected abstract void bringToForeground(boolean showDialpad);
+ public void onPhoneDestroyed(Phone phone) { }
}
diff --git a/telecomm/java/android/telecomm/Phone.java b/telecomm/java/android/telecomm/Phone.java
new file mode 100644
index 0000000..9c97b45
--- /dev/null
+++ b/telecomm/java/android/telecomm/Phone.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2013 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.telecomm;
+
+import android.util.ArrayMap;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A unified virtual device providing a means of voice (and other) communication on a device.
+ */
+public final class Phone {
+
+ public abstract static class Listener {
+ /**
+ * Called when the audio state changes.
+ *
+ * @param phone The {@code Phone} calling this method.
+ * @param audioState The new {@link CallAudioState}.
+ */
+ public void onAudioStateChanged(Phone phone, CallAudioState audioState) { }
+
+ /**
+ * Called to bring the in-call screen to the foreground. The in-call experience should
+ * respond immediately by coming to the foreground to inform the user of the state of
+ * ongoing {@code Call}s.
+ *
+ * @param phone The {@code Phone} calling this method.
+ * @param showDialpad If true, put up the dialpad when the screen is shown.
+ */
+ public void onBringToForeground(Phone phone, boolean showDialpad) { }
+
+ /**
+ * Called when a {@code Call} has been added to this in-call session. The in-call user
+ * experience should add necessary state listeners to the specified {@code Call} and
+ * immediately start to show the user information about the existence
+ * and nature of this {@code Call}. Subsequent invocations of {@link #getCalls()} will
+ * include this {@code Call}.
+ *
+ * @param phone The {@code Phone} calling this method.
+ * @param call A newly added {@code Call}.
+ */
+ public void onCallAdded(Phone phone, Call call) { }
+
+ /**
+ * Called when a {@code Call} has been removed from this in-call session. The in-call user
+ * experience should remove any state listeners from the specified {@code Call} and
+ * immediately stop displaying any information about this {@code Call}.
+ * Subsequent invocations of {@link #getCalls()} will no longer include this {@code Call}.
+ *
+ * @param phone The {@code Phone} calling this method.
+ * @param call A newly removed {@code Call}.
+ */
+ public void onCallRemoved(Phone phone, Call call) { }
+ }
+
+ // A Map allows us to track each Call by its Telecomm-specified call ID
+ private final Map<String, Call> mCallByTelecommCallId = new ArrayMap<>();
+
+ // A List allows us to keep the Calls in a stable iteration order so that casually developed
+ // user interface components do not incur any spurious jank
+ private final List<Call> mCalls = new ArrayList<>();
+
+ // An unmodifiable view of the above List can be safely shared with subclass implementations
+ private final List<Call> mUnmodifiableCalls = Collections.unmodifiableList(mCalls);
+
+ private final InCallAdapter mInCallAdapter;
+
+ private CallAudioState mAudioState;
+
+ private final List<Listener> mListeners = new ArrayList<>();
+
+ /** {@hide} */
+ Phone(InCallAdapter adapter) {
+ mInCallAdapter = adapter;
+ }
+
+ /** {@hide} */
+ final void internalAddCall(InCallCall inCallCall) {
+ Call call = new Call(this, inCallCall.getId(), mInCallAdapter);
+ mCallByTelecommCallId.put(inCallCall.getId(), call);
+ mCalls.add(call);
+ checkCallTree(inCallCall);
+ call.internalUpdate(inCallCall);
+ fireCallAdded(call);
+ }
+
+ /** {@hide} */
+ final void internalRemoveCall(Call call) {
+ mCallByTelecommCallId.remove(call.internalGetCallId());
+ mCalls.remove(call);
+ fireCallRemoved(call);
+ }
+
+ /** {@hide} */
+ final void internalUpdateCall(InCallCall inCallCall) {
+ Call call = mCallByTelecommCallId.get(inCallCall.getId());
+ if (call != null) {
+ checkCallTree(inCallCall);
+ call.internalUpdate(inCallCall);
+ }
+ }
+
+ /** {@hide} */
+ final void internalSetPostDial(String callId, String remaining) {
+ Call call = mCallByTelecommCallId.get(callId);
+ if (call != null) {
+ call.internalSetPostDial(remaining);
+ }
+ }
+
+ /** {@hide} */
+ final void internalSetPostDialWait(String callId, String remaining) {
+ Call call = mCallByTelecommCallId.get(callId);
+ if (call != null) {
+ call.internalSetPostDialWait(remaining);
+ }
+ }
+
+ /** {@hide} */
+ final void internalAudioStateChanged(CallAudioState callAudioState) {
+ if (!Objects.equals(mAudioState, callAudioState)) {
+ mAudioState = callAudioState;
+ fireAudioStateChanged(callAudioState);
+ }
+ }
+
+ /** {@hide} */
+ final Call internalGetCallByTelecommId(String telecommId) {
+ return mCallByTelecommCallId.get(telecommId);
+ }
+
+ /** {@hide} */
+ final void internalBringToForeground(boolean showDialpad) {
+ fireBringToForeground(showDialpad);
+ }
+
+ /**
+ * Adds a listener to this {@code Phone}.
+ *
+ * @param listener A {@code Listener} object.
+ */
+ public final void addListener(Listener listener) {
+ mListeners.add(listener);
+ }
+
+ /**
+ * Removes a listener from this {@code Phone}.
+ *
+ * @param listener A {@code Listener} object.
+ */
+ public final void removeListener(Listener listener) {
+ mListeners.remove(listener);
+ }
+
+ /**
+ * Obtains the current list of {@code Call}s to be displayed by this in-call experience.
+ *
+ * @return A list of the relevant {@code Call}s.
+ */
+ public final List<Call> getCalls() {
+ return mUnmodifiableCalls;
+ }
+
+ /**
+ * Sets the microphone mute state. When this request is honored, there will be change to
+ * the {@link #getAudioState()}.
+ *
+ * @param state {@code true} if the microphone should be muted; {@code false} otherwise.
+ */
+ public final void setMuted(boolean state) {
+ mInCallAdapter.mute(state);
+ }
+
+ /**
+ * Sets the audio route (speaker, bluetooth, etc...). When this request is honored, there will
+ * be change to the {@link #getAudioState()}.
+ *
+ * @param route The audio route to use.
+ */
+ public final void setAudioRoute(int route) {
+ mInCallAdapter.setAudioRoute(route);
+ }
+
+ /**
+ * Obtains the current phone call audio state of the {@code Phone}.
+ *
+ * @return An object encapsulating the audio state.
+ */
+ public final CallAudioState getAudioState() {
+ return mAudioState;
+ }
+
+ private void fireCallAdded(Call call) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onCallAdded(this, call);
+ }
+ }
+
+ private void fireCallRemoved(Call call) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onCallRemoved(this, call);
+ }
+ }
+
+ private void fireAudioStateChanged(CallAudioState audioState) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onAudioStateChanged(this, audioState);
+ }
+ }
+
+ private void fireBringToForeground(boolean showDialpad) {
+ Listener[] listeners = mListeners.toArray(new Listener[mListeners.size()]);
+ for (int i = 0; i < listeners.length; i++) {
+ listeners[i].onBringToForeground(this, showDialpad);
+ }
+ }
+
+ private void checkCallTree(InCallCall inCallCall) {
+ if (inCallCall.getParentCallId() != null &&
+ !mCallByTelecommCallId.containsKey(inCallCall.getParentCallId())) {
+ Log.wtf(this, "InCallCall %s has nonexistent parent %s",
+ inCallCall.getId(), inCallCall.getParentCallId());
+ }
+ if (inCallCall.getChildCallIds() != null) {
+ for (int i = 0; i < inCallCall.getChildCallIds().size(); i++) {
+ if (!mCallByTelecommCallId.containsKey(inCallCall.getChildCallIds().get(i))) {
+ Log.wtf(this, "InCallCall %s has nonexistent child %s",
+ inCallCall.getId(), inCallCall.getChildCallIds().get(i));
+ }
+ }
+ }
+ }
+}
diff --git a/telecomm/java/android/telecomm/PhoneAccount.java b/telecomm/java/android/telecomm/PhoneAccount.java
index 4e440d8..b246d92 100644
--- a/telecomm/java/android/telecomm/PhoneAccount.java
+++ b/telecomm/java/android/telecomm/PhoneAccount.java
@@ -17,52 +17,64 @@
package android.telecomm;
import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import java.util.MissingResourceException;
import java.util.Objects;
/**
* Represents a distinct account, line of service or call placement method that
* the system can use to place phone calls.
*/
-public final class PhoneAccount implements Parcelable {
+public class PhoneAccount implements Parcelable {
- private static final int NO_DENSITY = -1;
- private static final String LOG_TAG = "Account";
+ /**
+ * Flag indicating that this {@code PhoneAccount} can act as a call manager for traditional
+ * SIM-based telephony calls. The {@link ConnectionService} associated with this phone-account
+ * will be allowed to manage SIM-based phone calls including using its own proprietary
+ * phone-call implementation (like VoIP calling) to make calls instead of the telephony stack.
+ * When a user opts to place a call using the SIM-based telephony stack, the connection-service
+ * associated with this phone-account will be attempted first if the user has explicitly
+ * selected it to be used as the default call-manager.
+ * <p>
+ * See {@link #getCapabilities}
+ */
+ public static final int CAPABILITY_SIM_CALL_MANAGER = 0x1;
- private final ComponentName mComponentName;
- private final String mId;
- private final Uri mHandle;
- private final String mLabel;
- private final String mShortDescription;
- private final boolean mIsEnabled;
- private final boolean mIsSystemDefault;
+ /**
+ * Flag indicating that this {@code PhoneAccount} can make phone calls in place of traditional
+ * SIM-based telephony calls. This account will be treated as a distinct method for placing
+ * calls alongside the traditional SIM-based telephony stack. This flag is distinct from
+ * {@link #CAPABILITY_SIM_CALL_MANAGER} in that it is not allowed to manage calls from or use
+ * the built-in telephony stack to place its calls.
+ * <p>
+ * See {@link #getCapabilities}
+ */
+ public static final int CAPABILITY_CALL_PROVIDER = 0x2;
+
+ /**
+ * Flag indicating that this {@code PhoneAccount} represents a built-in PSTN SIM subscription.
+ * <p>
+ * Only the android framework can set this capability on a phone-account.
+ */
+ public static final int CAPABILITY_SIM_SUBSCRIPTION = 0x4;
+
+ private ComponentName mComponentName;
+ private String mId;
+ private Uri mHandle;
+ private int mCapabilities;
public PhoneAccount(
ComponentName componentName,
String id,
Uri handle,
- String label,
- String shortDescription,
- boolean isEnabled,
- boolean isSystemDefault) {
+ int capabilities) {
mComponentName = componentName;
mId = id;
mHandle = handle;
- mLabel = label;
- mShortDescription = shortDescription;
- mIsSystemDefault = isSystemDefault;
- mIsEnabled = isEnabled;
+ mCapabilities = capabilities;
}
/**
@@ -87,8 +99,8 @@
/**
* The handle (e.g., a phone number) associated with this {@code PhoneAccount}. This represents
- * the destination from which outgoing calls using this {@code PhoneAccount} will appear to come
- * from, if applicable, and the destination to which incoming calls using this
+ * the destination from which outgoing calls using this {@code PhoneAccount} will appear to
+ * come, if applicable, and the destination to which incoming calls using this
* {@code PhoneAccount} may be addressed.
*
* @return A handle expressed as a {@code Uri}, for example, a phone number.
@@ -98,76 +110,45 @@
}
/**
- * A short string label describing this {@code PhoneAccount}.
+ * The capabilities of this {@code PhoneAccount}.
*
- * @param context The invoking {@code Context}, used for retrieving resources.
- *
- * TODO(ihab): If don't need context, remove param
- *
- * @return A label for this {@code PhoneAccount}.
+ * @return A bit field of flags describing this {@code PhoneAccount}'s capabilities.
*/
- public String getLabel(Context context) {
- return mLabel;
+ public int getCapabilities() {
+ return mCapabilities;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(mComponentName) + Objects.hashCode(mId) +
+ Objects.hashCode(mHandle) + mCapabilities;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder().append(mComponentName)
+ .append(", ")
+ .append(mId)
+ .append(", ")
+ .append(Log.pii(mHandle))
+ .append(", ")
+ .append(String.valueOf(mCapabilities))
+ .toString();
}
/**
- * A short paragraph describing this {@code PhoneAccount}.
- *
- * @param context The invoking {@code Context}, used for retrieving resources.
- *
- * TODO(ihab): If don't need context, remove param
- *
- * @return A description for this {@code PhoneAccount}.
+ * TODO: Change this to just be equals() and use Set<> in Telecomm code instead of Lists.
+ * @hide
*/
- public String getShortDescription(Context context) {
- return mShortDescription;
+ public boolean equalsComponentAndId(PhoneAccount other) {
+ return other != null &&
+ Objects.equals(other.getComponentName(), getComponentName()) &&
+ Objects.equals(other.getId(), getId());
}
- // TODO(ihab): Representation of the icons
//
- // Refactor to pass a Bitmap (scale it at runtime), but if they don't pass one, fall
- // back to the android:icon attr in the manifest (<service /> first, <application /> second)
-
- /**
- * An icon to represent this {@code PhoneAccount} in a user interface.
- *
- * @param context The invoking {@code Context}, used for retrieving resources.
- *
- * @return An icon for this {@code PhoneAccount}.
- */
- public Drawable getIcon(Context context) {
- return null; // TODO(ihab): See above
- }
-
- /**
- * An icon to represent this {@code PhoneAccount} in a user interface.
- *
- * @param context The invoking {@code Context}, used for retrieving resources.
- * @param density A display density from {@link DisplayMetrics}.
- *
- * @return An icon for this {@code PhoneAccount}.
- */
- public Drawable getIcon(Context context, int density) {
- return null; // TODO(ihab): See above
- }
-
- /**
- * Whether this {@code PhoneAccount} is enabled for use.
- *
- * @return {@code true} if this {@code PhoneAccount} is enabled.
- */
- public boolean isEnabled() {
- return mIsEnabled;
- }
-
- /**
- * Whether this {@code PhoneAccount} is the system default.
- *
- * @return {@code true} if this {@code PhoneAccount} is the system default.
- */
- public boolean isSystemDefault() {
- return mIsSystemDefault;
- }
+ // Parcelable implementation.
+ //
@Override
public int describeContents() {
@@ -179,18 +160,16 @@
out.writeParcelable(mComponentName, flags);
out.writeString(mId);
out.writeString(mHandle != null ? mHandle.toString() : "");
- out.writeString(mLabel);
- out.writeString(mShortDescription);
- out.writeInt(mIsEnabled ? 1 : 0);
- out.writeInt(mIsSystemDefault ? 1 : 0);
+ out.writeInt(mCapabilities);
}
- public static final Creator<PhoneAccount> CREATOR
- = new Creator<PhoneAccount>() {
+ public static final Creator<PhoneAccount> CREATOR = new Creator<PhoneAccount>() {
+ @Override
public PhoneAccount createFromParcel(Parcel in) {
return new PhoneAccount(in);
}
+ @Override
public PhoneAccount[] newArray(int size) {
return new PhoneAccount[size];
}
@@ -201,22 +180,6 @@
mId = in.readString();
String uriString = in.readString();
mHandle = uriString.length() > 0 ? Uri.parse(uriString) : null;
- mLabel = in.readString();
- mShortDescription = in.readString();
- mIsEnabled = in.readInt() == 1;
- mIsSystemDefault = in.readInt() == 1;
- }
-
- @Override
- public boolean equals(Object other) {
- return
- other instanceof PhoneAccount &&
- Objects.equals(mComponentName, ((PhoneAccount) other).mComponentName) &&
- Objects.equals(mId, ((PhoneAccount) other).mId);
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(mComponentName) + Objects.hashCode(mId);
+ mCapabilities = in.readInt();
}
}
diff --git a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl b/telecomm/java/android/telecomm/PhoneAccountMetadata.aidl
similarity index 77%
rename from telecomm/java/android/telecomm/CallServiceDescriptor.aidl
rename to telecomm/java/android/telecomm/PhoneAccountMetadata.aidl
index f517c73..55b8900 100644
--- a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl
+++ b/telecomm/java/android/telecomm/PhoneAccountMetadata.aidl
@@ -1,11 +1,11 @@
/*
- * Copyright 2014, The Android Open Source Project
+ * 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
+ * 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,
@@ -16,4 +16,7 @@
package android.telecomm;
-parcelable CallServiceDescriptor;
+/**
+ * {@hide}
+ */
+parcelable PhoneAccountMetadata;
diff --git a/telecomm/java/android/telecomm/PhoneAccountMetadata.java b/telecomm/java/android/telecomm/PhoneAccountMetadata.java
new file mode 100644
index 0000000..20a4d47
--- /dev/null
+++ b/telecomm/java/android/telecomm/PhoneAccountMetadata.java
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+package android.telecomm;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.IOException;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.util.MissingResourceException;
+
+/**
+ * Provides user interface description information for a {@code PhoneAccount}.
+ */
+public class PhoneAccountMetadata implements Parcelable {
+ private PhoneAccount mAccount;
+ private int mIconResId;
+ private String mLabel;
+ private String mShortDescription;
+
+ public PhoneAccountMetadata(
+ PhoneAccount account,
+ int iconResId,
+ String label,
+ String shortDescription) {
+ mAccount = account;
+ mIconResId = iconResId;
+ mLabel = label;
+ mShortDescription = shortDescription;
+ }
+
+ /**
+ * The {@code PhoneAccount} to which this metadata pertains.
+ *
+ * @return A {@code PhoneAccount}.
+ */
+ public PhoneAccount getAccount() {
+ return mAccount;
+ }
+
+ /**
+ * A short string label describing a {@code PhoneAccount}.
+ *
+ * @return A label for this {@code PhoneAccount}.
+ */
+ public String getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * A short paragraph describing a {@code PhoneAccount}.
+ *
+ * @return A description for this {@code PhoneAccount}.
+ */
+ public String getShortDescription() {
+ return mShortDescription;
+ }
+
+ /**
+ * An icon to represent this {@code PhoneAccount} in a user interface.
+ *
+ * @return An icon for this {@code PhoneAccount}.
+ */
+ public Drawable getIcon(Context context) {
+ return getIcon(context, mIconResId);
+ }
+
+ private Drawable getIcon(Context context, int resId) {
+ Context packageContext;
+ try {
+ packageContext = context.createPackageContext(
+ mAccount.getComponentName().getPackageName(), 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(this, "Cannot find package %s", mAccount.getComponentName().getPackageName());
+ return null;
+ }
+ try {
+ return packageContext.getResources().getDrawable(resId);
+ } catch (MissingResourceException e) {
+ Log.e(this, e, "Cannot find icon %d in package %s",
+ resId, mAccount.getComponentName().getPackageName());
+ return null;
+ }
+ }
+
+ //
+ // Parcelable implementation
+ //
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(mAccount, 0);
+ out.writeInt(mIconResId);
+ out.writeString(mLabel);
+ out.writeString(mShortDescription);
+ }
+
+ public static final Creator<PhoneAccountMetadata> CREATOR
+ = new Creator<PhoneAccountMetadata>() {
+ @Override
+ public PhoneAccountMetadata createFromParcel(Parcel in) {
+ return new PhoneAccountMetadata(in);
+ }
+
+ @Override
+ public PhoneAccountMetadata[] newArray(int size) {
+ return new PhoneAccountMetadata[size];
+ }
+ };
+
+ private PhoneAccountMetadata(Parcel in) {
+ mAccount = in.readParcelable(getClass().getClassLoader());
+ mIconResId = in.readInt();
+ mLabel = in.readString();
+ mShortDescription = in.readString();
+ }
+}
diff --git a/telecomm/java/android/telecomm/RemoteCallVideoProvider.java b/telecomm/java/android/telecomm/RemoteCallVideoProvider.java
index 856d321..a49076a 100644
--- a/telecomm/java/android/telecomm/RemoteCallVideoProvider.java
+++ b/telecomm/java/android/telecomm/RemoteCallVideoProvider.java
@@ -20,63 +20,92 @@
import android.os.RemoteException;
import android.view.Surface;
-import com.android.internal.telecomm.ICallVideoClient;
import com.android.internal.telecomm.ICallVideoProvider;
-public class RemoteCallVideoProvider implements IBinder.DeathRecipient {
+public class RemoteCallVideoProvider {
private final ICallVideoProvider mCallVideoProvider;
+ private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ mCallVideoProvider.asBinder().unlinkToDeath(this, 0);
+ }
+ };
+
+ /** {@hide} */
RemoteCallVideoProvider(ICallVideoProvider callVideoProvider) throws RemoteException {
mCallVideoProvider = callVideoProvider;
- mCallVideoProvider.asBinder().linkToDeath(this, 0);
+ mCallVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
}
- @Override
- public void binderDied() {
- mCallVideoProvider.asBinder().unlinkToDeath(this, 0);
- }
-
- public void setCallVideoClient(CallVideoClient callVideoClient) throws RemoteException {
- mCallVideoProvider.setCallVideoClient(callVideoClient.getBinder());
+ public void setCallVideoClient(CallVideoClient callVideoClient) {
+ try {
+ mCallVideoProvider.setCallVideoClient(callVideoClient.getBinder());
+ } catch (RemoteException e) {
+ }
}
public void setCamera(String cameraId) throws RemoteException {
mCallVideoProvider.setCamera(cameraId);
}
- public void setPreviewSurface(Surface surface) throws RemoteException {
- mCallVideoProvider.setPreviewSurface(surface);
+ public void setPreviewSurface(Surface surface) {
+ try {
+ mCallVideoProvider.setPreviewSurface(surface);
+ } catch (RemoteException e) {
+ }
}
- public void setDisplaySurface(Surface surface) throws RemoteException {
- mCallVideoProvider.setDisplaySurface(surface);
+ public void setDisplaySurface(Surface surface) {
+ try {
+ mCallVideoProvider.setDisplaySurface(surface);
+ } catch (RemoteException e) {
+ }
}
- public void setDeviceOrientation(int rotation) throws RemoteException {
- mCallVideoProvider.setDeviceOrientation(rotation);
+ public void setDeviceOrientation(int rotation) {
+ try {
+ mCallVideoProvider.setDeviceOrientation(rotation);
+ } catch (RemoteException e) {
+ }
}
public void setZoom(float value) throws RemoteException {
mCallVideoProvider.setZoom(value);
}
- public void sendSessionModifyRequest(VideoCallProfile requestProfile) throws RemoteException {
- mCallVideoProvider.sendSessionModifyRequest(requestProfile);
+ public void sendSessionModifyRequest(VideoCallProfile requestProfile) {
+ try {
+ mCallVideoProvider.sendSessionModifyRequest(requestProfile);
+ } catch (RemoteException e) {
+ }
}
- public void sendSessionModifyResponse(VideoCallProfile responseProfile) throws RemoteException {
- mCallVideoProvider.sendSessionModifyResponse(responseProfile);
+ public void sendSessionModifyResponse(VideoCallProfile responseProfile) {
+ try {
+ mCallVideoProvider.sendSessionModifyResponse(responseProfile);
+ } catch (RemoteException e) {
+ }
}
- public void requestCameraCapabilities() throws RemoteException {
- mCallVideoProvider.requestCameraCapabilities();
+ public void requestCameraCapabilities() {
+ try {
+ mCallVideoProvider.requestCameraCapabilities();
+ } catch (RemoteException e) {
+ }
}
- public void requestCallDataUsage() throws RemoteException {
- mCallVideoProvider.requestCallDataUsage();
+ public void requestCallDataUsage() {
+ try {
+ mCallVideoProvider.requestCallDataUsage();
+ } catch (RemoteException e) {
+ }
}
- public void setPauseImage(String uri) throws RemoteException {
- mCallVideoProvider.setPauseImage(uri);
+ public void setPauseImage(String uri) {
+ try {
+ mCallVideoProvider.setPauseImage(uri);
+ } catch (RemoteException e) {
+ }
}
}
\ No newline at end of file
diff --git a/telecomm/java/android/telecomm/RemoteConnectionManager.java b/telecomm/java/android/telecomm/RemoteConnectionManager.java
index 9cffdcc..0a0b245 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionManager.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionManager.java
@@ -54,9 +54,10 @@
return accounts;
}
- public void createOutgoingConnection(
+ public void createRemoteConnection(
ConnectionRequest request,
- final ConnectionService.OutgoingCallResponse response) {
+ ConnectionService.CreateConnectionResponse response,
+ boolean isIncoming) {
PhoneAccount account = request.getAccount();
if (account == null) {
throw new IllegalArgumentException("account must be specified.");
@@ -67,7 +68,7 @@
throw new UnsupportedOperationException("account not supported: " + componentName);
} else {
RemoteConnectionService remoteService = mRemoteConnectionServices.get(componentName);
- remoteService.createOutgoingConnection(request, response);
+ remoteService.createRemoteConnection(request, response, isIncoming);
}
}
}
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
index a436af2..7fd8f93 100644
--- a/telecomm/java/android/telecomm/RemoteConnectionService.java
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -44,40 +44,34 @@
private String mConnectionId;
private ConnectionRequest mPendingRequest;
- private ConnectionService.OutgoingCallResponse<RemoteConnection> mPendingOutgoingCallResponse;
+ private ConnectionService.CreateConnectionResponse<RemoteConnection> mPendingResponse;
// Remote connection services only support a single connection.
private RemoteConnection mConnection;
private final IConnectionServiceAdapter mAdapter = new IConnectionServiceAdapter.Stub() {
-
@Override
- public void notifyIncomingCall(ConnectionRequest request) {
- Log.w(this, "notifyIncomingCall not implemented in Remote connection");
- }
-
- @Override
- public void handleSuccessfulOutgoingCall(ConnectionRequest request) {
+ public void handleCreateConnectionSuccessful(ConnectionRequest request) {
if (isPendingConnection(request.getCallId())) {
mConnection = new RemoteConnection(mConnectionService, request.getCallId());
- mPendingOutgoingCallResponse.onSuccess(request, mConnection);
+ mPendingResponse.onSuccess(request, mConnection);
clearPendingInformation();
}
}
@Override
- public void handleFailedOutgoingCall(
+ public void handleCreateConnectionFailed(
ConnectionRequest request, int errorCode, String errorMessage) {
if (isPendingConnection(request.getCallId())) {
- mPendingOutgoingCallResponse.onFailure(request, errorCode, errorMessage);
+ mPendingResponse.onFailure(request, errorCode, errorMessage);
mConnectionId = null;
clearPendingInformation();
}
}
@Override
- public void cancelOutgoingCall(ConnectionRequest request) {
+ public void handleCreateConnectionCancelled(ConnectionRequest request) {
if (isPendingConnection(request.getCallId())) {
- mPendingOutgoingCallResponse.onCancel(request);
+ mPendingResponse.onCancel(request);
mConnectionId = null;
clearPendingInformation();
}
@@ -226,12 +220,10 @@
release();
}
- /**
- * Places an outgoing call.
- */
- final void createOutgoingConnection(
+ final void createRemoteConnection(
ConnectionRequest request,
- ConnectionService.OutgoingCallResponse<RemoteConnection> response) {
+ ConnectionService.CreateConnectionResponse<RemoteConnection> response,
+ boolean isIncoming) {
if (mConnectionId == null) {
String id = UUID.randomUUID().toString();
@@ -243,9 +235,9 @@
request.getExtras(),
request.getVideoState());
try {
- mConnectionService.call(newRequest);
+ mConnectionService.createConnection(newRequest, isIncoming);
mConnectionId = id;
- mPendingOutgoingCallResponse = response;
+ mPendingResponse = response;
mPendingRequest = request;
} catch (RemoteException e) {
response.onFailure(request, DisconnectCause.ERROR_UNSPECIFIED, e.toString());
@@ -255,9 +247,6 @@
}
}
- // TODO(santoscordon): Handle incoming connections
- // public final void handleIncomingConnection() {}
-
final List<PhoneAccount> lookupAccounts(Uri handle) {
// TODO(santoscordon): Update this so that is actually calls into the RemoteConnection
// each time.
@@ -266,10 +255,7 @@
mComponentName,
null /* id */,
null /* handle */,
- "" /* label */,
- "" /* shortDescription */,
- true /* isEnabled */,
- false /* isSystemDefault */));
+ 0 /* capabilities */));
return accounts;
}
@@ -282,7 +268,7 @@
}
private boolean isPendingConnection(String id) {
- return TextUtils.equals(mConnectionId, id) && mPendingOutgoingCallResponse != null;
+ return TextUtils.equals(mConnectionId, id) && mPendingResponse != null;
}
private boolean isCurrentConnection(String id) {
@@ -291,7 +277,7 @@
private void clearPendingInformation() {
mPendingRequest = null;
- mPendingOutgoingCallResponse = null;
+ mPendingResponse = null;
}
private void destroyConnection() {
diff --git a/telecomm/java/android/telecomm/TelecommConstants.java b/telecomm/java/android/telecomm/TelecommConstants.java
index b9fb40c..b50c1d7 100644
--- a/telecomm/java/android/telecomm/TelecommConstants.java
+++ b/telecomm/java/android/telecomm/TelecommConstants.java
@@ -16,6 +16,7 @@
package android.telecomm;
+import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
@@ -31,9 +32,9 @@
* to find and bind to the appropriate {@link android.telecomm.ConnectionService} which
* Telecomm will ultimately use to control and get information about the call.</p>
*
- * <p>Input: get*Extra field {@link #EXTRA_CALL_SERVICE_DESCRIPTOR} contains the component name
- * of the {@link android.telecomm.ConnectionService} that Telecomm should bind to. Telecomm
- * will then ask the call service for more information about the call prior to showing any UI.
+ * <p>Input: get*Extra field {@link #EXTRA_PHONE_ACCOUNT} contains the component name of the
+ * {@link android.telecomm.ConnectionService} that Telecomm should bind to. Telecomm will then
+ * ask the connection service for more information about the call prior to showing any UI.
*
* TODO(santoscordon): Needs permissions.
* TODO(santoscordon): Consider moving this into a simple method call on a system service.
@@ -41,16 +42,17 @@
public static final String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL";
/**
- * The service action used to bind to {@link CallServiceProvider} implementations.
- */
- public static final String ACTION_CALL_SERVICE_PROVIDER = CallServiceProvider.class.getName();
-
- /**
* The service action used to bind to {@link ConnectionService} implementations.
*/
public static final String ACTION_CONNECTION_SERVICE = ConnectionService.class.getName();
/**
+ * The {@link Intent} action used to configure a {@link ConnectionService}.
+ */
+ public static final String ACTION_CONNECTION_SERVICE_CONFIGURE =
+ "android.intent.action.CONNECTION_SERVICE_CONFIGURE";
+
+ /**
* Optional extra for {@link Intent#ACTION_CALL} containing a boolean that determines whether
* the speakerphone should be automatically turned on for an outgoing call.
*/
@@ -69,11 +71,15 @@
"android.intent.extra.START_CALL_WITH_VIDEO_STATE";
/**
- * Extra for {@link #ACTION_INCOMING_CALL} containing the {@link CallServiceDescriptor} that
- * describes the call service to use for the incoming call.
+ * The extra used with an {@link android.content.Intent#ACTION_CALL},
+ * {@link #ACTION_INCOMING_CALL}, {@link android.content.Intent#ACTION_DIAL} {@code Intent} to
+ * specify a {@link PhoneAccount} to use when making the call.
+ *
+ * <p class="note">
+ * Retrieve with
+ * {@link android.content.Intent#getParcelableExtra(String)}.
*/
- public static final String EXTRA_CALL_SERVICE_DESCRIPTOR =
- "android.intent.extra.CALL_SERVICE_DESCRIPTOR";
+ public static final String EXTRA_PHONE_ACCOUNT = "android.intent.extra.PHONE_ACCOUNT";
/**
* Optional extra for {@link #ACTION_INCOMING_CALL} containing a {@link Bundle} which contains
@@ -115,4 +121,83 @@
* wait for user confirmation before proceeding.
*/
public static final char DTMF_CHARACTER_WAIT = ';';
+
+ /**
+ * TTY (teletypewriter) mode is off.
+ *
+ * @hide
+ */
+ public static final int TTY_MODE_OFF = 0;
+
+ /**
+ * TTY (teletypewriter) mode is on. The speaker is off and the microphone is muted. The user
+ * will communicate with the remote party by sending and receiving text messages.
+ *
+ * @hide
+ */
+ public static final int TTY_MODE_FULL = 1;
+
+ /**
+ * TTY (teletypewriter) mode is in hearing carryover mode (HCO). The microphone is muted but the
+ * speaker is on. The user will communicate with the remote party by sending text messages and
+ * hearing an audible reply.
+ *
+ * @hide
+ */
+ public static final int TTY_MODE_HCO = 2;
+
+ /**
+ * TTY (teletypewriter) mode is in voice carryover mode (VCO). The speaker is off but the
+ * microphone is still on. User will communicate with the remote party by speaking and receiving
+ * text message replies.
+ *
+ * @hide
+ */
+ public static final int TTY_MODE_VCO = 3;
+
+ /**
+ * Broadcast intent action indicating that the current TTY mode has changed. An intent extra
+ * provides this state as an int.
+ * @see #EXTRA_CURRENT_TTY_MODE
+ *
+ * @hide
+ */
+ public static final String ACTION_CURRENT_TTY_MODE_CHANGED =
+ "android.telecomm.intent.action.CURRENT_TTY_MODE_CHANGED";
+
+ /**
+ * The lookup key for an int that indicates the current TTY mode.
+ * Valid modes are:
+ * - {@link #TTY_MODE_OFF}
+ * - {@link #TTY_MODE_FULL}
+ * - {@link #TTY_MODE_HCO}
+ * - {@link #TTY_MODE_VCO}
+ *
+ * @hide
+ */
+ public static final String EXTRA_CURRENT_TTY_MODE =
+ "android.telecomm.intent.extra.CURRENT_TTY_MODE";
+
+ /**
+ * Broadcast intent action indicating that the TTY preferred operating mode
+ * has changed. An intent extra provides the new mode as an int.
+ * @see #EXTRA_TTY_PREFERRED_MODE
+ *
+ * @hide
+ */
+ public static final String ACTION_TTY_PREFERRED_MODE_CHANGED =
+ "android.telecomm.intent.action.TTY_PREFERRED_MODE_CHANGED";
+
+ /**
+ * The lookup key for an int that indicates preferred TTY mode.
+ * Valid modes are:
+ * - {@link #TTY_MODE_OFF}
+ * - {@link #TTY_MODE_FULL}
+ * - {@link #TTY_MODE_HCO}
+ * - {@link #TTY_MODE_VCO}
+ *
+ * @hide
+ */
+ public static final String EXTRA_TTY_PREFERRED_MODE =
+ "android.telecomm.intent.extra.TTY_PREFERRED";
}
diff --git a/telecomm/java/android/telecomm/TelecommManager.java b/telecomm/java/android/telecomm/TelecommManager.java
index 1bb18f2..8bf80bb 100644
--- a/telecomm/java/android/telecomm/TelecommManager.java
+++ b/telecomm/java/android/telecomm/TelecommManager.java
@@ -23,31 +23,18 @@
import com.android.internal.telecomm.ITelecommService;
+import java.util.List;
+
/**
* Provides access to Telecomm-related functionality.
* TODO(santoscordon): Move this all into PhoneManager.
- * @hide
*/
public class TelecommManager {
+
private static final String TAG = "TelecommManager";
private static final String TELECOMM_SERVICE_NAME = "telecomm";
private final Context mContext;
- private final ITelecommService mService;
-
- /**
- * @hide
- */
- public TelecommManager(Context context, ITelecommService service) {
- Context appContext = context.getApplicationContext();
- if (appContext != null) {
- mContext = appContext;
- } else {
- mContext = context;
- }
-
- mService = service;
- }
/**
* @hide
@@ -59,6 +46,101 @@
/**
* @hide
*/
+ public TelecommManager(Context context) {
+ Context appContext = context.getApplicationContext();
+ if (appContext != null) {
+ mContext = appContext;
+ } else {
+ mContext = context;
+ }
+ }
+
+ /**
+ * Return a list of {@link PhoneAccount}s which can be used to make and receive phone calls.
+ *
+ * @see #EXTRA_PHONE_ACCOUNT
+ * @return A list of {@code PhoneAccount} objects.
+ */
+ public List<PhoneAccount> getEnabledPhoneAccounts() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecommService().getEnabledPhoneAccounts();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#getEnabledPhoneAccounts", e);
+ }
+ return null;
+ }
+
+ /**
+ * Return the metadata for a specified {@link PhoneAccount}. Metadata includes resources which
+ * can be used in a user interface.
+ *
+ * @param account The {@link PhoneAccount}.
+ *
+ * @return The metadata for the account.
+ */
+ public PhoneAccountMetadata getPhoneAccountMetadata(PhoneAccount account) {
+ try {
+ if (isServiceConnected()) {
+ return getTelecommService().getPhoneAccountMetadata(account);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#getPhoneAccountMetadata", e);
+ }
+ return null;
+ }
+
+ /**
+ * Register a {@link PhoneAccount} for use by the system.
+ *
+ * @param account The {@link PhoneAccount}.
+ * @param metadata The metadata for the account.
+ */
+ public void registerPhoneAccount(PhoneAccount account, PhoneAccountMetadata metadata) {
+ try {
+ if (isServiceConnected()) {
+ getTelecommService().registerPhoneAccount(account, metadata);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#registerPhoneAccount", e);
+ }
+ }
+
+ /**
+ * Remove a {@link PhoneAccount} registration from the system.
+ *
+ * @param account An Account.
+ */
+ public void unregisterPhoneAccount(PhoneAccount account) {
+ try {
+ if (isServiceConnected()) {
+ getTelecommService().unregisterPhoneAccount(account);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#unregisterPhoneAccount", e);
+ }
+ }
+
+ /**
+ * Remove all Accounts for a given package from the system.
+ *
+ * @param packageName A package name that may have registered Accounts.
+ */
+ @SystemApi
+ public void clearAccounts(String packageName) {
+ try {
+ if (isServiceConnected()) {
+ getTelecommService().clearAccounts(packageName);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelecommService#clearAccounts", e);
+ }
+ }
+
+ /**
+ * @hide
+ */
@SystemApi
public ComponentName getDefaultPhoneApp() {
try {
@@ -108,7 +190,7 @@
/**
* Ends an ongoing call. TODO(santoscordon): L-release - need to convert all invocations of
- * ITelephony#endCall to use this method (clockwork & gearhead).
+ * ITelecommService#endCall to use this method (clockwork & gearhead).
*
* @hide
*/
@@ -127,7 +209,7 @@
/**
* If there is a ringing incoming call, this method accepts the call on behalf of the user.
* TODO(santoscordon): L-release - need to convert all invocation of
- * ITelephony#answerRingingCall to use this method (clockwork & gearhead).
+ * ITelecommService#answerRingingCall to use this method (clockwork & gearhead).
*
* @hide
*/
@@ -158,6 +240,44 @@
}
}
+ /**
+ * Returns whether TTY is supported on this device.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean isTtySupported() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecommService().isTtySupported();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException attempting to get TTY supported state.", e);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the current TTY mode of the device. For TTY to be on the user must enable it in
+ * settings and have a wired headset plugged in. Valid modes are:
+ * - {@link android.telecomm.TelecommConstants#TTY_MODE_OFF}
+ * - {@link android.telecomm.TelecommConstants#TTY_MODE_FULL}
+ * - {@link android.telecomm.TelecommConstants#TTY_MODE_HCO}
+ * - {@link android.telecomm.TelecommConstants#TTY_MODE_VCO}
+ *
+ * @hide
+ */
+ public int getCurrentTtyMode() {
+ try {
+ if (isServiceConnected()) {
+ return getTelecommService().getCurrentTtyMode();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException attempting to get the current TTY mode.", e);
+ }
+ return TelecommConstants.TTY_MODE_OFF;
+ }
+
private ITelecommService getTelecommService() {
return ITelecommService.Stub.asInterface(ServiceManager.getService(TELECOMM_SERVICE_NAME));
}
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceLookupResponse.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceLookupResponse.aidl
deleted file mode 100644
index 10d73be..0000000
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceLookupResponse.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.internal.telecomm;
-
-import android.os.IBinder;
-import android.telecomm.CallServiceDescriptor;
-import java.util.List;
-
-/**
- * Internal remote interface for call service lookup response.
- *
- * @see android.telecomm.CallServiceLookupResponse
- *
- * @hide
- */
-oneway interface ICallServiceLookupResponse {
- void setCallServiceDescriptors(in List<CallServiceDescriptor> callServiceDescriptors);
-}
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceProvider.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceProvider.aidl
deleted file mode 100644
index 96daeed..0000000
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceProvider.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telecomm;
-
-import android.telecomm.CallServiceDescriptor;
-
-import com.android.internal.telecomm.ICallServiceLookupResponse;
-
-/**
- * Internal remote interface for call service providers.
- *
- * @see android.telecomm.CallServiceProvider
- *
- * @hide
- */
-oneway interface ICallServiceProvider {
- void lookupCallServices(in ICallServiceLookupResponse response);
-}
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
index 16d2edf..9360219 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionService.aidl
@@ -32,12 +32,10 @@
oneway interface IConnectionService {
void addConnectionServiceAdapter(in IConnectionServiceAdapter adapter);
- void call(in ConnectionRequest request);
+ void createConnection(in ConnectionRequest request, boolean isIncoming);
void abort(String callId);
- void createIncomingCall(in ConnectionRequest request);
-
void answer(String callId);
void reject(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
index bc67eab..b36f72c 100644
--- a/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/IConnectionServiceAdapter.aidl
@@ -31,13 +31,12 @@
* {@hide}
*/
oneway interface IConnectionServiceAdapter {
- void notifyIncomingCall(in ConnectionRequest request);
+ void handleCreateConnectionSuccessful(in ConnectionRequest request);
- void handleSuccessfulOutgoingCall(in ConnectionRequest request);
+ void handleCreateConnectionFailed(
+ in ConnectionRequest request, int errorCode, String errorMessage);
- void handleFailedOutgoingCall(in ConnectionRequest request, int errorCode, String errorMessage);
-
- void cancelOutgoingCall(in ConnectionRequest request);
+ void handleCreateConnectionCancelled(in ConnectionRequest request);
void setActive(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
index 30e4bdc..43caa1e 100644
--- a/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ITelecommService.aidl
@@ -18,6 +18,7 @@
import android.content.ComponentName;
import android.telecomm.PhoneAccount;
+import android.telecomm.PhoneAccountMetadata;
/**
* Interface used to interact with Telecomm. Mostly this is used by TelephonyManager for passing
@@ -33,22 +34,32 @@
void showCallScreen(boolean showDialpad);
/**
- * Gets a list of accounts.
+ * @see TelecommManager#getEnabledPhoneAccounts
*/
- List<PhoneAccount> getAccounts();
+ List<PhoneAccount> getEnabledPhoneAccounts();
/**
- * Sets the enabled state of a given account.
+ * @see TelecommManager#getPhoneAccountMetadata
*/
- void setEnabled(in PhoneAccount account, boolean enabled);
+ PhoneAccountMetadata getPhoneAccountMetadata(in PhoneAccount account);
/**
- * Sets a given account as the system default.
+ * @see TelecommManager#registerPhoneAccount
*/
- void setSystemDefault(in PhoneAccount account);
+ void registerPhoneAccount(in PhoneAccount account, in PhoneAccountMetadata metadata);
/**
- * Returns the component name of the default phone application.
+ * @see TelecommManager#unregisterPhoneAccount
+ */
+ void unregisterPhoneAccount(in PhoneAccount account);
+
+ /**
+ * @see TelecommManager#clearAccounts
+ */
+ void clearAccounts(String packageName);
+
+ /**
+ * @see TelecommManager#getDefaultPhoneApp
*/
ComponentName getDefaultPhoneApp();
@@ -90,4 +101,14 @@
* @see PhoneManager#handlePinMmi
*/
boolean handlePinMmi(String dialString);
+
+ /**
+ * @see TelecomManager#isTtySupported
+ */
+ boolean isTtySupported();
+
+ /**
+ * @see TelecomManager#getCurrentTtyMode
+ */
+ int getCurrentTtyMode();
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 91ce73a..5e6cb14 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -298,17 +298,6 @@
public static final String EXTRA_INCOMING_NUMBER = "incoming_number";
/**
- * The lookup key used with an {@link android.content.Intent#ACTION_CALL} or
- * {@link android.content.Intent#ACTION_DIAL} {@code Intent} for a {@link PhoneAccount}
- * object indicating a preference when making a phone connection.
- *
- * <p class="note">
- * Retrieve with
- * {@link android.content.Intent#getParcelableExtra(String)}.
- */
- public static final String EXTRA_ACCOUNT = "account";
-
- /**
* Broadcast intent action indicating that a precise call state
* (cellular) on the device has changed.
*
@@ -1722,11 +1711,10 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param alphaTag alpha-tagging of the dailing nubmer
* @param number The dialing number
- *
- * @hide
*/
public void setLine1NumberForDisplay(String alphaTag, String number) {
setLine1NumberForDisplay(getDefaultSubscription(), alphaTag, number);
@@ -1740,12 +1728,11 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param subId the subscriber that the alphatag and dialing number belongs to.
* @param alphaTag alpha-tagging of the dailing nubmer
* @param number The dialing number
- *
- * @hide
*/
public void setLine1NumberForDisplay(long subId, String alphaTag, String number) {
try {
@@ -2358,11 +2345,10 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param AID Application id. See ETSI 102.221 and 101.220.
* @return The logical channel id which is negative on error.
- *
- * @hide
*/
public int iccOpenLogicalChannel(String AID) {
try {
@@ -2380,12 +2366,11 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param channel is the channel id to be closed as retruned by a successful
* iccOpenLogicalChannel.
* @return true if the channel was closed successfully.
- *
- * @hide
*/
public boolean iccCloseLogicalChannel(int channel) {
try {
@@ -2403,6 +2388,7 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param channel is the channel id to be closed as returned by a successful
* iccOpenLogicalChannel.
@@ -2415,8 +2401,6 @@
* @param data Data to be sent with the APDU.
* @return The APDU response from the ICC card with the status appended at
* the end. If an error occurs, an empty string is returned.
- *
- * @hide
*/
public String iccTransmitApduLogicalChannel(int channel, int cla,
int instruction, int p1, int p2, int p3, String data) {
@@ -2434,6 +2418,7 @@
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param content String containing SAT/USAT response in hexadecimal
* format starting with command tag. See TS 102 223 for
@@ -2441,8 +2426,6 @@
* @return The APDU response from the ICC card, with the last 4 bytes
* being the status word. If the command fails, returns an empty
* string.
- *
- * @hide
*/
public String sendEnvelopeWithStatus(String content) {
try {
@@ -2454,11 +2437,16 @@
}
/**
- * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}.
+ * Read one of the NV items defined in com.android.internal.telephony.RadioNVItems.
* Used for device configuration by some CDMA operators.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param itemID the ID of the item to read.
* @return the NV item as a String, or null on any failure.
+ *
* @hide
*/
public String nvReadItem(int itemID) {
@@ -2472,14 +2460,18 @@
return "";
}
-
/**
- * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}.
+ * Write one of the NV items defined in com.android.internal.telephony.RadioNVItems.
* Used for device configuration by some CDMA operators.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param itemID the ID of the item to read.
* @param itemValue the value to write, as a String.
* @return true on success; false on any failure.
+ *
* @hide
*/
public boolean nvWriteItem(int itemID, String itemValue) {
@@ -2496,9 +2488,14 @@
/**
* Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
* Used for device configuration by some CDMA operators.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param preferredRoamingList byte array containing the new PRL.
* @return true on success; false on any failure.
+ *
* @hide
*/
public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
@@ -2516,9 +2513,14 @@
* Perform the specified type of NV config reset. The radio will be taken offline
* and the device must be rebooted after the operation. Used for device
* configuration by some CDMA operators.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param resetType reset type: 1: reload NV reset, 2: erase NV reset, 3: factory NV reset
* @return true on success; false on any failure.
+ *
* @hide
*/
public boolean nvResetConfig(int resetType) {
@@ -2815,10 +2817,12 @@
/**
* Get the calculated preferred network type.
* Used for debugging incorrect network type.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
* @return the preferred network type, defined in RILConstants.java or -1 if
* none available.
- * @hide
*/
public int getCalculatedPreferredNetworkType() {
try {
@@ -2834,9 +2838,12 @@
/**
* Get the preferred network type.
* Used for device configuration by some CDMA operators.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @return the preferred network type, defined in RILConstants.java.
- * @hide
*/
public int getPreferredNetworkType() {
try {
@@ -2852,10 +2859,13 @@
/**
* Set the preferred network type.
* Used for device configuration by some CDMA operators.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param networkType the preferred network type, defined in RILConstants.java.
* @return true on success; false on any failure.
- * @hide
*/
public boolean setPreferredNetworkType(int networkType) {
try {
@@ -2871,10 +2881,13 @@
/**
* Set the CDMA subscription source.
* Used for device supporting both NV and RUIM for CDMA.
+ * <p>
+ * Requires Permission:
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param subscriptionType the subscription type, 0 for RUIM, 1 for NV.
* @return true on success; false on any failure.
- * @hide
*/
public boolean setCdmaSubscription(int subscriptionType) {
try {
@@ -3207,51 +3220,14 @@
}
/**
- * Return a list of Accounts that can be used to indicate a preference when making
- * a phone call.
- *
- * @see #EXTRA_ACCOUNT
- * @return A list of {@code Accouint} objects.
- */
- public List<PhoneAccount> getAccounts() {
- try {
- return getTelecommService().getAccounts();
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#getAccounts", e);
- }
- return null;
- }
-
- /** @hide */
- @SystemApi
- public void setEnabled(PhoneAccount account, boolean enabled) {
- try {
- getTelecommService().setEnabled(account, enabled);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#setEnabled", e);
- }
- }
-
- /** @hide */
- @SystemApi
- public void setSystemDefault(PhoneAccount account) {
- try {
- getTelecommService().setSystemDefault(account);
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#setSystemDefault", e);
- }
- }
-
- /**
* Set whether Android should display a simplified Mobile Network Settings UI.
* The setting won't be persisted during power cycle.
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param enable true means enabling the simplified UI.
- *
- * @hide
*/
public void enableSimplifiedNetworkSettings(boolean enable) {
enableSimplifiedNetworkSettings(getDefaultSubscription(), enable);
@@ -3263,11 +3239,10 @@
* <p>
* Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
*
* @param subId for which the simplified UI should be enabled or disabled.
* @param enable true means enabling the simplified UI.
- *
- * @hide
*/
public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
try {
@@ -3284,8 +3259,6 @@
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*
* @return true if the simplified UI is enabled.
- *
- * @hide
*/
public boolean getSimplifiedNetworkSettingsEnabled() {
return getSimplifiedNetworkSettingsEnabled(getDefaultSubscription());
@@ -3299,8 +3272,6 @@
*
* @param subId for which the simplified UI should be enabled or disabled.
* @return true if the simplified UI is enabled.
- *
- * @hide
*/
public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
try {
diff --git a/telephony/java/com/android/internal/telephony/IMms.aidl b/telephony/java/com/android/internal/telephony/IMms.aidl
index db93a4f..651205f 100644
--- a/telephony/java/com/android/internal/telephony/IMms.aidl
+++ b/telephony/java/com/android/internal/telephony/IMms.aidl
@@ -215,4 +215,29 @@
*/
void sendStoredMessage(long subId, String callingPkg, in Uri messageUri,
in PendingIntent sentIntent);
+
+ /**
+ * Turns on/off the flag to automatically write sent/received SMS/MMS messages into system
+ *
+ * When this flag is on, all SMS/MMS sent/received are stored by system automatically
+ * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system
+ * automatically
+ *
+ * This flag can only be changed by default SMS apps
+ *
+ * @param callingPkg the name of the calling app package
+ * @param enabled Whether to enable message auto persisting
+ */
+ void setAutoPersisting(String callingPkg, boolean enabled);
+
+ /**
+ * Get the value of the flag to automatically write sent/received SMS/MMS messages into system
+ *
+ * When this flag is on, all SMS/MMS sent/received are stored by system automatically
+ * When this flag is off, only SMS/MMS sent by non-default SMS apps are stored by system
+ * automatically
+ *
+ * @return the current value of the auto persist flag
+ */
+ boolean getAutoPersisting();
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4592717..d41ceda 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -650,7 +650,7 @@
*
* TODO: Add a link to documentation.
*
- * @return carrier privelege status defined in TelephonyManager.
+ * @return carrier privilege status defined in TelephonyManager.
*/
int hasCarrierPrivileges();
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl
deleted file mode 100644
index bcf2d81..0000000
--- a/telephony/java/com/android/internal/telephony/IThirdPartyCallListener.aidl
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import com.android.internal.telephony.IThirdPartyCallProvider;
-
-/**
- * Interface provided to ThirdPartyCallService. The service can use this to notify the listener of
- * changes to the call state.
- */
-oneway interface IThirdPartyCallListener {
- /**
- * Called by the service when a call provider is available to perform the outgoing or incoming
- * call.
- */
- void onCallProviderAttached(IThirdPartyCallProvider callProvider);
-
- /**
- * Notifies the listener that ringing has started for this call.
- */
- void onRingingStarted();
-
- /**
- * Notifies the listener that the call has been successfully established.
- */
- void onCallEstablished();
-
- /**
- * Notifies the listener that the call has ended.
- */
- void onCallEnded(int reason);
-}
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl
deleted file mode 100644
index 9d595b0..0000000
--- a/telephony/java/com/android/internal/telephony/IThirdPartyCallProvider.aidl
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import com.android.internal.telephony.IThirdPartyCallListener;
-import com.android.internal.telephony.IThirdPartyCallSendDtmfCallback;
-
-/**
- * Interface sent to ThirdPartyCallListener.onCallProviderAttached. This is used to control an
- * outgoing or incoming call.
- */
-oneway interface IThirdPartyCallProvider {
- /**
- * Mutes or unmutes the call.
- */
- void mute(boolean shouldMute);
-
- /**
- * Ends the current call. If this is an unanswered incoming call then the call is rejected (for
- * example, a notification is sent to a server that the user declined the call).
- */
- void hangup();
-
- /**
- * Accepts the incoming call.
- */
- void incomingCallAccept();
-
- /**
- * Sends the given DTMF code. The code can be '0'-'9', 'A'-'D', '#', or '*'.
- */
- void sendDtmf(char c, IThirdPartyCallSendDtmfCallback callback);
-}
diff --git a/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl b/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl
deleted file mode 100644
index 597567a..0000000
--- a/telephony/java/com/android/internal/telephony/IThirdPartyCallService.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.telephony;
-
-import com.android.internal.telephony.IThirdPartyCallListener;
-
-/**
- * Interface provided by a service to start outgoing calls and attach to incoming calls.
- */
-oneway interface IThirdPartyCallService {
- /**
- * Call to start a new outgoing call.
- */
- void outgoingCallInitiate(IThirdPartyCallListener listener, String number);
-
- /**
- * Call to attach to an incoming call. This is in response to a call to
- * TelephonyManager.newIncomingThirdPartyCall.
- */
- void incomingCallAttach(IThirdPartyCallListener listener, String callId);
-}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index a54936b..8a2732d 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -175,6 +175,11 @@
}
@Override
+ public File getNoBackupFilesDir() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public File getExternalFilesDir(String type) {
throw new UnsupportedOperationException();
}
@@ -190,6 +195,11 @@
}
@Override
+ public File getCodeCacheDir() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public File getExternalCacheDir() {
throw new UnsupportedOperationException();
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index a14714a..e388480 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -31,6 +31,7 @@
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
+import android.content.pm.KeySet;
import android.content.pm.ManifestDigest;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
@@ -616,6 +617,26 @@
throw new UnsupportedOperationException();
}
+ @Override
+ public KeySet getKeySetByAlias(String packageName, String alias) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public KeySet getSigningKeySet(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isSignedBy(String packageName, KeySet ks) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isSignedByExactly(String packageName, KeySet ks) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* @hide
*/
@@ -729,7 +750,13 @@
}
/** {@hide} */
- public PackageInstaller getPackageInstaller() {
+ public PackageInstaller getInstaller() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@hide} */
+ @Override
+ public boolean isPackageAvailable(String packageName) {
throw new UnsupportedOperationException();
}
diff --git a/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk
index 93b9c9a..4feac68 100644
--- a/tests/OneMedia/Android.mk
+++ b/tests/OneMedia/Android.mk
@@ -10,8 +10,7 @@
LOCAL_CERTIFICATE := platform
LOCAL_STATIC_JAVA_LIBRARIES := \
- android-support-v7-appcompat \
- android-support-v7-mediarouter
+ android-support-media-protocols
LOCAL_PROGUARD_ENABLED := disabled
diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml
index 504d471..9d78ca5 100644
--- a/tests/OneMedia/AndroidManifest.xml
+++ b/tests/OneMedia/AndroidManifest.xml
@@ -27,11 +27,11 @@
android:process="com.android.onemedia.service" />
<service
android:name=".provider.OneMediaRouteProvider"
- android:permission="android.permission.BIND_ROUTE_PROVIDER"
+ android:permission="android.permission.BIND_MEDIA_ROUTE_SERVICE"
android:exported="true"
android:process="com.android.onemedia.provider">
<intent-filter>
- <action android:name="com.android.media.session.MediaRouteProvider" />
+ <action android:name="android.media.routing.MediaRouteService" />
</intent-filter>
</service>
</application>
diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
index ee407ad..894377b 100644
--- a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
+++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
@@ -28,8 +28,6 @@
import android.widget.EditText;
import android.widget.TextView;
-import com.android.onemedia.playback.Renderer;
-
public class OnePlayerActivity extends Activity {
private static final String TAG = "OnePlayerActivity";
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
index 145b389..b47cc3c 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerController.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
@@ -18,13 +18,14 @@
import android.media.MediaMetadata;
import android.media.session.MediaController;
-import android.media.session.RouteInfo;
+import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -44,7 +45,7 @@
protected MediaController.TransportControls mTransportControls;
private final Intent mServiceIntent;
- private Context mContext;
+ private Activity mContext;
private Listener mListener;
private SessionCallback mControllerCb;
private MediaSessionManager mManager;
@@ -52,7 +53,7 @@
private boolean mResumed;
- public PlayerController(Context context, Intent serviceIntent) {
+ public PlayerController(Activity context, Intent serviceIntent) {
mContext = context;
if (serviceIntent == null) {
mServiceIntent = new Intent(mContext, PlayerService.class);
@@ -121,7 +122,7 @@
}
public void showRoutePicker() {
- mController.showRoutePicker();
+ // TODO
}
private void unbindFromService() {
@@ -141,6 +142,7 @@
mBinder = null;
mController = null;
mTransportControls = null;
+ mContext.setMediaController(null);
Log.d(TAG, "Disconnected from PlayerService");
if (mListener != null) {
@@ -152,12 +154,15 @@
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = IPlayerService.Stub.asInterface(service);
Log.d(TAG, "service is " + service + " binder is " + mBinder);
+ MediaSession.Token token;
try {
- mController = MediaController.fromToken(mBinder.getSessionToken());
+ token = mBinder.getSessionToken();
} catch (RemoteException e) {
Log.e(TAG, "Error getting session", e);
return;
}
+ mController = new MediaController(token);
+ mContext.setMediaController(mController);
mController.addCallback(mControllerCb, mHandler);
mTransportControls = mController.getTransportControls();
Log.d(TAG, "Ready to use PlayerService");
@@ -173,11 +178,6 @@
private class SessionCallback extends MediaController.Callback {
@Override
- public void onRouteChanged(RouteInfo route) {
- // TODO
- }
-
- @Override
public void onPlaybackStateChanged(PlaybackState state) {
if (state == null) {
return;
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
index a220107..feecfde 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -17,14 +17,19 @@
import android.content.Context;
import android.content.Intent;
-import android.media.session.Route;
-import android.media.session.RouteInfo;
-import android.media.session.RouteOptions;
-import android.media.session.RoutePlaybackControls;
+import android.media.routing.MediaRouteSelector;
+import android.media.routing.MediaRouter;
+import android.media.routing.MediaRouter.ConnectionRequest;
+import android.media.routing.MediaRouter.DestinationInfo;
+import android.media.routing.MediaRouter.RouteInfo;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.os.Bundle;
+import android.support.media.protocols.MediaPlayerProtocol;
+import android.support.media.protocols.MediaPlayerProtocol.MediaStatus;
+import android.os.RemoteException;
+import android.os.SystemClock;
import android.util.Log;
import android.view.KeyEvent;
@@ -34,11 +39,13 @@
import com.android.onemedia.playback.RequestUtils;
import java.util.ArrayList;
+import java.util.List;
public class PlayerSession {
private static final String TAG = "PlayerSession";
protected MediaSession mSession;
+ protected MediaRouter mRouter;
protected Context mContext;
protected Renderer mRenderer;
protected MediaSession.Callback mCallback;
@@ -46,10 +53,6 @@
protected PlaybackState mPlaybackState;
protected Listener mListener;
- protected ArrayList<RouteOptions> mRouteOptions;
- protected Route mRoute;
- protected RoutePlaybackControls mRouteControls;
- protected RouteListener mRouteListener;
private String mContent;
@@ -58,46 +61,58 @@
mRenderer = new LocalRenderer(context, null);
mCallback = new SessionCb();
mRenderListener = new RenderListener();
- mPlaybackState = new PlaybackState();
- mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
- | PlaybackState.ACTION_PLAY);
+ PlaybackState.Builder psBob = new PlaybackState.Builder();
+ psBob.setActions(PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY);
+ mPlaybackState = psBob.build();
mRenderer.registerListener(mRenderListener);
-
- // TODO need an easier way to build route options
- mRouteOptions = new ArrayList<RouteOptions>();
- RouteOptions.Builder bob = new RouteOptions.Builder();
- bob.addInterface(RoutePlaybackControls.NAME);
- mRouteOptions.add(bob.build());
- mRouteListener = new RouteListener();
}
public void createSession() {
- if (mSession != null) {
- mSession.release();
- }
+ releaseSession();
+
MediaSessionManager man = (MediaSessionManager) mContext
.getSystemService(Context.MEDIA_SESSION_SERVICE);
Log.d(TAG, "Creating session for package " + mContext.getBasePackageName());
- mSession = man.createSession("OneMedia");
+
+ mRouter = new MediaRouter(mContext);
+ mRouter.addSelector(new MediaRouteSelector.Builder()
+ .addRequiredProtocol(MediaPlayerProtocol.class)
+ .build());
+ mRouter.addSelector(new MediaRouteSelector.Builder()
+ .setRequiredFeatures(MediaRouter.ROUTE_FEATURE_LIVE_AUDIO)
+ .setOptionalFeatures(MediaRouter.ROUTE_FEATURE_LIVE_VIDEO)
+ .build());
+ mRouter.setRoutingCallback(new RoutingCallback(), null);
+
+ mSession = new MediaSession(mContext, "OneMedia");
mSession.addCallback(mCallback);
mSession.addTransportControlsCallback(new TransportCallback());
mSession.setPlaybackState(mPlaybackState);
mSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
- mSession.setRouteOptions(mRouteOptions);
+ mSession.setMediaRouter(mRouter);
mSession.setActive(true);
}
public void onDestroy() {
- if (mSession != null) {
- mSession.release();
- }
+ releaseSession();
if (mRenderer != null) {
mRenderer.unregisterListener(mRenderListener);
mRenderer.onDestroy();
}
}
+ private void releaseSession() {
+ if (mSession != null) {
+ mSession.release();
+ mSession = null;
+ }
+ if (mRouter != null) {
+ mRouter.release();
+ mRouter = null;
+ }
+ }
+
public void setListener(Listener listener) {
mListener = listener;
}
@@ -118,7 +133,10 @@
private void updateState(int newState) {
float rate = newState == PlaybackState.STATE_PLAYING ? 1 : 0;
long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
- mPlaybackState.setState(newState, position, rate);
+ PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
+ bob.setState(newState, position, rate, SystemClock.elapsedRealtime());
+ bob.setErrorMessage(null);
+ mPlaybackState = bob.build();
mSession.setPlaybackState(mPlaybackState);
}
@@ -131,10 +149,12 @@
@Override
public void onError(int type, int extra, Bundle extras, Throwable error) {
Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
- mPlaybackState.setState(PlaybackState.STATE_ERROR, -1, 0);
+ PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
+ bob.setState(PlaybackState.STATE_ERROR, -1, 0, 0);
if (error != null) {
- mPlaybackState.setErrorMessage(error.getLocalizedMessage());
+ bob.setErrorMessage(error.getLocalizedMessage());
}
+ mPlaybackState = bob.build();
mSession.setPlaybackState(mPlaybackState);
if (mListener != null) {
mListener.onPlayStateChanged(mPlaybackState);
@@ -143,36 +163,41 @@
@Override
public void onStateChanged(int newState) {
- if (newState != Renderer.STATE_ERROR) {
- mPlaybackState.setErrorMessage(null);
- }
long position = -1;
if (mRenderer != null) {
position = mRenderer.getSeekPosition();
}
+ int pbState;
+ float rate = 0;
+ String errorMsg = null;
switch (newState) {
case Renderer.STATE_ENDED:
case Renderer.STATE_STOPPED:
- mPlaybackState.setState(PlaybackState.STATE_STOPPED, position, 0);
+ pbState = PlaybackState.STATE_STOPPED;
break;
case Renderer.STATE_INIT:
case Renderer.STATE_PREPARING:
- mPlaybackState.setState(PlaybackState.STATE_BUFFERING, position, 0);
+ pbState = PlaybackState.STATE_BUFFERING;
break;
case Renderer.STATE_ERROR:
- mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
+ pbState = PlaybackState.STATE_ERROR;
break;
case Renderer.STATE_PAUSED:
- mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0);
+ pbState = PlaybackState.STATE_PAUSED;
break;
case Renderer.STATE_PLAYING:
- mPlaybackState.setState(PlaybackState.STATE_PLAYING, position, 1);
+ pbState = PlaybackState.STATE_PLAYING;
+ rate = 1;
break;
default:
- mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
- mPlaybackState.setErrorMessage("unkown state");
+ pbState = PlaybackState.STATE_ERROR;
+ errorMsg = "unknown state";
break;
}
+ PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
+ bob.setState(pbState, position, rate, SystemClock.elapsedRealtime());
+ bob.setErrorMessage(errorMsg);
+ mPlaybackState = bob.build();
mSession.setPlaybackState(mPlaybackState);
if (mListener != null) {
mListener.onPlayStateChanged(mPlaybackState);
@@ -187,7 +212,10 @@
public void onFocusLost() {
Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
- mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0);
+ PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
+ bob.setState(PlaybackState.STATE_PAUSED, position, 0, SystemClock.elapsedRealtime());
+ bob.setErrorMessage(null);
+ mPlaybackState = bob.build();
mSession.setPlaybackState(mPlaybackState);
if (mListener != null) {
mListener.onPlayStateChanged(mPlaybackState);
@@ -218,40 +246,6 @@
}
}
}
-
- @Override
- public void onRequestRouteChange(RouteInfo route) {
- if (mRenderer != null) {
- mRenderer.onStop();
- }
- if (route == null) {
- // Use local route
- mRoute = null;
- mRenderer = new LocalRenderer(mContext, null);
- mRenderer.registerListener(mRenderListener);
- updateState(PlaybackState.STATE_NONE);
- } else {
- // Use remote route
- mSession.connect(route, mRouteOptions.get(0));
- mRenderer = null;
- updateState(PlaybackState.STATE_CONNECTING);
- }
- }
-
- @Override
- public void onRouteConnected(Route route) {
- mRoute = route;
- mRouteControls = RoutePlaybackControls.from(route);
- mRouteControls.addListener(mRouteListener);
- Log.d(TAG, "Connected to route, registering listener");
- mRenderer = new OneMRPRenderer(mRouteControls);
- updateState(PlaybackState.STATE_NONE);
- }
-
- @Override
- public void onRouteDisconnected(Route route, int reason) {
-
- }
}
private class TransportCallback extends MediaSession.TransportControlsCallback {
@@ -266,12 +260,62 @@
}
}
- private class RouteListener extends RoutePlaybackControls.Listener {
+ private class RoutingCallback extends MediaRouter.RoutingCallback {
@Override
- public void onPlaybackStateChange(int state) {
- Log.d(TAG, "Updating state to " + state);
- updateState(state);
+ public void onConnectionStateChanged(int state) {
+ if (state == MediaRouter.CONNECTION_STATE_CONNECTING) {
+ if (mRenderer != null) {
+ mRenderer.onStop();
+ }
+ mRenderer = null;
+ updateState(PlaybackState.STATE_CONNECTING);
+ return;
+ }
+
+ MediaRouter.ConnectionInfo connection = mRouter.getConnection();
+ if (connection != null) {
+ MediaPlayerProtocol protocol =
+ connection.getProtocolObject(MediaPlayerProtocol.class);
+ if (protocol != null) {
+ Log.d(TAG, "Connected to route using media player protocol");
+
+ protocol.setCallback(new PlayerCallback(), null);
+ mRenderer = new OneMRPRenderer(protocol);
+ updateState(PlaybackState.STATE_NONE);
+ return;
+ }
+ }
+
+ // Use local route
+ mRenderer = new LocalRenderer(mContext, null);
+ mRenderer.registerListener(mRenderListener);
+ updateState(PlaybackState.STATE_NONE);
}
}
+ private class PlayerCallback extends MediaPlayerProtocol.Callback {
+ @Override
+ public void onStatusUpdated(MediaStatus status, Bundle extras) {
+ if (status != null) {
+ Log.d(TAG, "Received status update: " + status.toBundle());
+ switch (status.getPlayerState()) {
+ case MediaStatus.PLAYER_STATE_BUFFERING:
+ updateState(PlaybackState.STATE_BUFFERING);
+ break;
+ case MediaStatus.PLAYER_STATE_IDLE:
+ updateState(PlaybackState.STATE_STOPPED);
+ break;
+ case MediaStatus.PLAYER_STATE_PAUSED:
+ updateState(PlaybackState.STATE_PAUSED);
+ break;
+ case MediaStatus.PLAYER_STATE_PLAYING:
+ updateState(PlaybackState.STATE_PLAYING);
+ break;
+ case MediaStatus.PLAYER_STATE_UNKNOWN:
+ updateState(PlaybackState.STATE_NONE);
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java b/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java
index 05516d2..c133325 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java
@@ -15,10 +15,10 @@
*/
package com.android.onemedia.playback;
+import android.media.MediaMetadata;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-import android.support.v7.media.MediaItemMetadata;
/**
* TODO: Insert description here. (generated by epastern)
@@ -35,11 +35,11 @@
}
public String getTitle() {
- return mBundle.getString(MediaItemMetadata.KEY_TITLE);
+ return mBundle.getString(MediaMetadata.METADATA_KEY_TITLE);
}
public String getArtist() {
- return mBundle.getString(MediaItemMetadata.KEY_ALBUM_ARTIST);
+ return mBundle.getString(MediaMetadata.METADATA_KEY_ALBUM_ARTIST);
}
/* (non-Javadoc)
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
index 9b0a2b2..55eb92c 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
@@ -1,39 +1,42 @@
package com.android.onemedia.playback;
-import android.media.session.RoutePlaybackControls;
import android.os.Bundle;
+import android.support.media.protocols.MediaPlayerProtocol;
+import android.support.media.protocols.MediaPlayerProtocol.MediaInfo;
/**
* Renderer for communicating with the OneMRP route
*/
public class OneMRPRenderer extends Renderer {
- private final RoutePlaybackControls mControls;
+ private final MediaPlayerProtocol mProtocol;
- public OneMRPRenderer(RoutePlaybackControls controls) {
+ public OneMRPRenderer(MediaPlayerProtocol protocol) {
super(null, null);
- mControls = controls;
+ mProtocol = protocol;
}
@Override
public void setContent(Bundle request) {
- mControls.playNow(request.getString(RequestUtils.EXTRA_KEY_SOURCE));
+ MediaInfo mediaInfo = new MediaInfo(request.getString(RequestUtils.EXTRA_KEY_SOURCE),
+ MediaInfo.STREAM_TYPE_BUFFERED, "audio/mp3");
+ mProtocol.load(mediaInfo, true, 0, null);
}
@Override
public boolean onStop() {
- mControls.pause();
+ mProtocol.stop(null);
return true;
}
@Override
public boolean onPlay() {
- mControls.resume();
+ mProtocol.play(null);
return true;
}
@Override
public boolean onPause() {
- mControls.pause();
+ mProtocol.pause(null);
return true;
}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java b/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java
index dd0d982..3778c5f 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java
@@ -16,7 +16,6 @@
package com.android.onemedia.playback;
import android.os.Bundle;
-import android.support.v7.media.MediaItemMetadata;
import java.util.HashMap;
import java.util.Map;
diff --git a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
index f2d691c..5845e48 100644
--- a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
+++ b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
@@ -15,19 +15,23 @@
*/
package com.android.onemedia.provider;
-import android.media.routeprovider.RouteConnection;
-import android.media.routeprovider.RouteInterfaceHandler;
-import android.media.routeprovider.RoutePlaybackControlsHandler;
-import android.media.routeprovider.RouteProviderService;
-import android.media.routeprovider.RouteRequest;
-import android.media.session.RouteInfo;
-import android.media.session.RoutePlaybackControls;
-import android.media.session.RouteInterface;
+import android.media.routing.MediaRouteSelector;
+import android.media.routing.MediaRouteService;
+import android.media.routing.MediaRouter.ConnectionInfo;
+import android.media.routing.MediaRouter.ConnectionRequest;
+import android.media.routing.MediaRouter.DestinationInfo;
+import android.media.routing.MediaRouter.DiscoveryRequest;
+import android.media.routing.MediaRouter.RouteInfo;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Process;
+import android.support.media.protocols.MediaPlayerProtocol;
+import android.support.media.protocols.MediaPlayerProtocol.MediaInfo;
+import android.support.media.protocols.MediaPlayerProtocol.MediaStatus;
import android.os.Looper;
import android.os.ResultReceiver;
+import android.os.SystemClock;
import android.util.Log;
import com.android.onemedia.playback.LocalRenderer;
@@ -35,111 +39,135 @@
import com.android.onemedia.playback.RequestUtils;
import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
/**
* Test of MediaRouteProvider. Show a dummy provider with a simple interface for
* playing music.
*/
-public class OneMediaRouteProvider extends RouteProviderService {
+public class OneMediaRouteProvider extends MediaRouteService {
private static final String TAG = "OneMRP";
private static final boolean DEBUG = true;
+ private static final String TEST_DESTINATION_ID = "testDestination";
+ private static final String TEST_ROUTE_ID = "testRoute";
+
private Renderer mRenderer;
private RenderListener mRenderListener;
private PlaybackState mPlaybackState;
- private RouteConnection mConnection;
- private RoutePlaybackControlsHandler mControls;
- private String mRouteId;
private Handler mHandler;
+ private OneStub mStub;
+
@Override
public void onCreate() {
mHandler = new Handler();
- mRouteId = UUID.randomUUID().toString();
mRenderer = new LocalRenderer(this, null);
mRenderListener = new RenderListener();
- mPlaybackState = new PlaybackState();
- mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
- | PlaybackState.ACTION_PLAY);
+ PlaybackState.Builder bob = new PlaybackState.Builder();
+ bob.setActions(PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_PLAY);
+ mPlaybackState = bob.build();
mRenderer.registerListener(mRenderListener);
-
- if (DEBUG) {
- Log.d(TAG, "onCreate, routeId is " + mRouteId);
- }
}
@Override
- public List<RouteInfo> getMatchingRoutes(List<RouteRequest> requests) {
- RouteInfo.Builder bob = new RouteInfo.Builder();
- bob.setName("OneMedia").setId(mRouteId);
- // TODO add a helper library for generating route info with the correct
- // options
- Log.d(TAG, "Requests:");
- for (RouteRequest request : requests) {
- List<String> ifaces = request.getConnectionOptions().getInterfaceNames();
- Log.d(TAG, " request ifaces:" + ifaces.toString());
- if (ifaces != null && ifaces.size() == 1
- && RoutePlaybackControls.NAME.equals(ifaces.get(0))) {
- bob.addRouteOptions(request.getConnectionOptions());
- }
+ public ClientSession onCreateClientSession(ClientInfo client) {
+ if (client.getUid() != Process.myUid()) {
+ // for testing purposes, only allow connections from this application
+ // since this provider is not fully featured
+ return null;
}
- ArrayList<RouteInfo> result = new ArrayList<RouteInfo>();
- if (bob.getOptionsSize() > 0) {
- RouteInfo info = bob.build();
- result.add(info);
- }
- if (DEBUG) {
- Log.d(TAG, "getRoutes returning " + result.toString());
- }
- return result;
+ return new OneSession(client);
}
- @Override
- public RouteConnection connect(RouteInfo route, RouteRequest request) {
- if (mConnection != null) {
- disconnect(mConnection);
- }
- RouteConnection connection = new RouteConnection(this, route);
- mControls = RoutePlaybackControlsHandler.addTo(connection);
- mControls.addListener(new PlayHandler(mRouteId), mHandler);
- if (DEBUG) {
- Log.d(TAG, "Connected to route");
- }
- return connection;
- }
+ private final class OneSession extends ClientSession {
+ private final ClientInfo mClient;
- private class PlayHandler extends RoutePlaybackControlsHandler.Listener {
- private final String mRouteId;
-
- public PlayHandler(String routeId) {
- mRouteId = routeId;
+ public OneSession(ClientInfo client) {
+ mClient = client;
}
@Override
- public void playNow(String content, ResultReceiver cb) {
+ public boolean onStartDiscovery(DiscoveryRequest req, DiscoveryCallback callback) {
+ for (MediaRouteSelector selector : req.getSelectors()) {
+ if (isMatch(selector)) {
+ DestinationInfo destination = new DestinationInfo.Builder(
+ TEST_DESTINATION_ID, getServiceMetadata(), "OneMedia")
+ .setDescription("Test route from OneMedia app.")
+ .build();
+ ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
+ routes.add(new RouteInfo.Builder(
+ TEST_ROUTE_ID, destination, selector).build());
+ callback.onDestinationFound(destination, routes);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void onStopDiscovery() {
+ }
+
+ @Override
+ public boolean onConnect(ConnectionRequest req, ConnectionCallback callback) {
+ if (req.getRoute().getId().equals(TEST_ROUTE_ID)) {
+ mStub = new OneStub();
+ ConnectionInfo connection = new ConnectionInfo.Builder(req.getRoute())
+ .setProtocolStub(MediaPlayerProtocol.class, mStub)
+ .build();
+ callback.onConnected(connection);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onDisconnect() {
+ mStub = null;
+ }
+
+ private boolean isMatch(MediaRouteSelector selector) {
+ if (!selector.containsProtocol(MediaPlayerProtocol.class)) {
+ return false;
+ }
+ for (String protocol : selector.getRequiredProtocols()) {
+ if (!protocol.equals(MediaPlayerProtocol.class.getName())) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ private final class OneStub extends MediaPlayerProtocol.Stub {
+ MediaInfo mMediaInfo;
+
+ public OneStub() {
+ super(mHandler);
+ }
+
+ @Override
+ public void onLoad(MediaInfo mediaInfo, boolean autoplay, long playPosition,
+ Bundle extras) {
if (DEBUG) {
- Log.d(TAG, "Attempting to play " + content);
+ Log.d(TAG, "Attempting to play " + mediaInfo.getContentId());
}
// look up the route and send a play command to it
+ mMediaInfo = mediaInfo;
Bundle bundle = new Bundle();
- bundle.putString(RequestUtils.EXTRA_KEY_SOURCE, content);
+ bundle.putString(RequestUtils.EXTRA_KEY_SOURCE, mediaInfo.getContentId());
mRenderer.setContent(bundle);
- RouteInterfaceHandler.sendResult(cb, RouteInterface.RESULT_SUCCESS, null);
}
@Override
- public boolean resume() {
+ public void onPlay(Bundle extras) {
mRenderer.onPlay();
- return true;
}
@Override
- public boolean pause() {
+ public void onPause(Bundle extras) {
mRenderer.onPause();
- return true;
}
}
@@ -148,45 +176,48 @@
@Override
public void onError(int type, int extra, Bundle extras, Throwable error) {
Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
- if (mControls != null) {
- mControls.sendPlaybackChangeEvent(PlaybackState.STATE_ERROR);
- }
+ sendStatusUpdate(PlaybackState.STATE_ERROR);
}
@Override
public void onStateChanged(int newState) {
- if (newState != Renderer.STATE_ERROR) {
- mPlaybackState.setErrorMessage(null);
- }
long position = -1;
if (mRenderer != null) {
position = mRenderer.getSeekPosition();
}
+ int pbState;
+ float rate = 0;
+ String errorMsg = null;
switch (newState) {
case Renderer.STATE_ENDED:
case Renderer.STATE_STOPPED:
- mPlaybackState.setState(PlaybackState.STATE_STOPPED, position, 0);
+ pbState = PlaybackState.STATE_STOPPED;
break;
case Renderer.STATE_INIT:
case Renderer.STATE_PREPARING:
- mPlaybackState.setState(PlaybackState.STATE_BUFFERING, position, 0);
+ pbState = PlaybackState.STATE_BUFFERING;
break;
case Renderer.STATE_ERROR:
- mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
+ pbState = PlaybackState.STATE_ERROR;
break;
case Renderer.STATE_PAUSED:
- mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0);
+ pbState = PlaybackState.STATE_PAUSED;
break;
case Renderer.STATE_PLAYING:
- mPlaybackState.setState(PlaybackState.STATE_PLAYING, position, 1);
+ pbState = PlaybackState.STATE_PLAYING;
+ rate = 1;
break;
default:
- mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0);
- mPlaybackState.setErrorMessage("unkown state");
+ pbState = PlaybackState.STATE_ERROR;
+ errorMsg = "unknown state";
break;
}
+ PlaybackState.Builder bob = new PlaybackState.Builder(mPlaybackState);
+ bob.setState(pbState, position, rate, SystemClock.elapsedRealtime());
+ bob.setErrorMessage(errorMsg);
+ mPlaybackState = bob.build();
- mControls.sendPlaybackChangeEvent(mPlaybackState.getState());
+ sendStatusUpdate(mPlaybackState.getState());
}
@Override
@@ -195,13 +226,45 @@
@Override
public void onFocusLost() {
- Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
- mPlaybackState.setState(PlaybackState.STATE_PAUSED, mRenderer.getSeekPosition(), 0);
+ Log.d(TAG, "Focus lost, pausing");
+ // Don't update state here, we'll get a separate call to
+ // onStateChanged when it pauses
mRenderer.onPause();
}
@Override
public void onNextStarted() {
}
+
+ private void sendStatusUpdate(int state) {
+ if (mStub != null) {
+ MediaStatus status = new MediaStatus(1, mStub.mMediaInfo);
+ switch (state) {
+ case PlaybackState.STATE_BUFFERING:
+ case PlaybackState.STATE_FAST_FORWARDING:
+ case PlaybackState.STATE_REWINDING:
+ case PlaybackState.STATE_SKIPPING_TO_NEXT:
+ case PlaybackState.STATE_SKIPPING_TO_PREVIOUS:
+ status.setPlayerState(MediaStatus.PLAYER_STATE_BUFFERING);
+ break;
+ case PlaybackState.STATE_CONNECTING:
+ case PlaybackState.STATE_STOPPED:
+ status.setPlayerState(MediaStatus.PLAYER_STATE_IDLE);
+ break;
+ case PlaybackState.STATE_PAUSED:
+ status.setPlayerState(MediaStatus.PLAYER_STATE_PAUSED);
+ break;
+ case PlaybackState.STATE_PLAYING:
+ status.setPlayerState(MediaStatus.PLAYER_STATE_PLAYING);
+ break;
+ case PlaybackState.STATE_NONE:
+ case PlaybackState.STATE_ERROR:
+ default:
+ status.setPlayerState(MediaStatus.PLAYER_STATE_UNKNOWN);
+ break;
+ }
+ mStub.sendStatusUpdatedEvent(status, null);
+ }
+ }
}
}
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
similarity index 98%
rename from tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable.xml
rename to tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
index 30fb1b8..18d7755 100644
--- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable.xml
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
@@ -19,7 +19,7 @@
android:drawable="@drawable/vector_drawable12" />
<item android:id="@+id/off"
android:drawable="@drawable/vector_drawable12" />
- <transition android:fromId="@+id/off" android:toId="@+id/on">
+ <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
<animated-vector android:drawable="@drawable/vector_drawable12">
<target
android:name="pie1"
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml
new file mode 100644
index 0000000..6a67b02
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml
@@ -0,0 +1,26 @@
+<!--
+ 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/on" android:state_checked="true"
+ android:drawable="@drawable/vector_drawable_grouping_1" />
+ <item android:id="@+id/off"
+ android:drawable="@drawable/vector_drawable_grouping_1" />
+ <transition android:fromId="@+id/off" android:toId="@+id/on"
+ android:drawable="@drawable/animation_vector_drawable_grouping_1"
+ android:reversible="true">
+ </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
new file mode 100644
index 0000000..65cf25b
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
@@ -0,0 +1,26 @@
+<!--
+ 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/on" android:state_checked="true"
+ android:drawable="@drawable/vector_drawable_favorite" />
+ <item android:id="@+id/off"
+ android:drawable="@drawable/vector_drawable_favorite" />
+ <transition android:fromId="@+id/off" android:toId="@+id/on"
+ android:drawable="@drawable/animation_vector_drawable_favorite"
+ android:reversible="true">
+ </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
index 0ae0136..566cc4b 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
@@ -27,7 +27,9 @@
private static final String LOGCAT = "AnimatedStateVectorDrawableTest";
protected int[] icon = {
- R.drawable.state_animation_vector_drawable
+ R.drawable.state_animation_vector_drawable01,
+ R.drawable.state_animation_vector_drawable02,
+ R.drawable.state_animation_vector_drawable03,
};
@Override
@@ -37,7 +39,7 @@
ScrollView scrollView = new ScrollView(this);
GridLayout container = new GridLayout(this);
scrollView.addView(container);
- container.setColumnCount(1);
+ container.setColumnCount(5);
for (int i = 0; i < icon.length; i++) {
CheckBox button = new CheckBox(this);
diff --git a/tests/VoiceEnrollment/res/xml/enrollment_application.xml b/tests/VoiceEnrollment/res/xml/enrollment_application.xml
index 710a0ac..70a6e0c 100644
--- a/tests/VoiceEnrollment/res/xml/enrollment_application.xml
+++ b/tests/VoiceEnrollment/res/xml/enrollment_application.xml
@@ -20,4 +20,5 @@
<voice-enrollment-application xmlns:android="http://schemas.android.com/apk/res/android"
android:searchKeyphraseId="101"
android:searchKeyphrase="Hello There"
- android:searchKeyphraseSupportedLocales="en-US,en-GB,fr-FR,de-DE" />
+ android:searchKeyphraseSupportedLocales="en-US,en-GB,fr-FR,de-DE"
+ android:searchKeyphraseRecognitionFlags="voiceTrigger" />
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index db43be3..ab2e8ac 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -27,8 +27,8 @@
static final String TAG = "MainInteractionService";
@Override
- public void onCreate() {
- super.onCreate();
+ public void onReady() {
+ super.onReady();
Log.i(TAG, "Creating " + this);
Log.i(TAG, "Keyphrase enrollment error? " + getKeyphraseEnrollmentInfo().getParseError());
Log.i(TAG, "Keyphrase enrollment meta-data: "
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index a6c09f3..62c92a1 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -93,7 +93,7 @@
}
try {
- mWm.addAppToken(0, null, 0, 0, 0, false, false, 0, 0, false);
+ mWm.addAppToken(0, null, 0, 0, 0, false, false, 0, 0, false, false);
fail("IWindowManager.addAppToken did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 12f5b92..28de933 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -77,6 +77,14 @@
int32_t layoutBoundsRight;
int32_t layoutBoundsBottom;
+ // Round rect outline description
+ int32_t outlineInsetsLeft;
+ int32_t outlineInsetsTop;
+ int32_t outlineInsetsRight;
+ int32_t outlineInsetsBottom;
+ float outlineRadius;
+ bool outlineFilled;
+
png_uint_32 allocHeight;
png_bytepp allocRows;
};
@@ -397,6 +405,98 @@
return NO_ERROR;
}
+static void find_max_opacity(png_byte** rows,
+ int startX, int startY, int endX, int endY, int dX, int dY,
+ int* out_inset)
+{
+ bool opaque_within_inset = true;
+ unsigned char max_opacity = 0;
+ int inset = 0;
+ *out_inset = 0;
+ for (int x = startX, y = startY; x != endX && y != endY; x += dX, y += dY, inset++) {
+ png_byte* color = rows[y] + x * 4;
+ unsigned char opacity = color[3];
+ if (opacity > max_opacity) {
+ max_opacity = opacity;
+ *out_inset = inset;
+ }
+ if (opacity == 0xff) return;
+ }
+}
+
+static bool is_opaque_over_row(png_byte* row, int startX, int endX)
+{
+ for (int x = startX; x < endX; x++) {
+ png_byte* color = row + x * 4;
+ if (color[3] != 0xff) return false;
+ }
+ return true;
+}
+
+static bool is_opaque_over_col(png_byte** rows, int offsetX, int startY, int endY)
+{
+ for (int y = startY; y < endY; y++) {
+ png_byte* color = rows[y] + offsetX * 4;
+ if (color[3] != 0xff) return false;
+ }
+ return true;
+}
+
+static void get_outline(image_info* image)
+{
+ int midX = image->width / 2;
+ int midY = image->height / 2;
+ int endX = image->width - 2;
+ int endY = image->height - 2;
+
+ // find left and right extent of nine patch content on center row
+ if (image->width > 4) {
+ find_max_opacity(image->rows, 1, midY, midX, -1, 1, 0, &image->outlineInsetsLeft);
+ find_max_opacity(image->rows, endX, midY, midX, -1, -1, 0, &image->outlineInsetsRight);
+ } else {
+ image->outlineInsetsLeft = 0;
+ image->outlineInsetsRight = 0;
+ }
+
+ // find top and bottom extent of nine patch content on center column
+ if (image->height > 4) {
+ find_max_opacity(image->rows, midX, 1, -1, midY, 0, 1, &image->outlineInsetsTop);
+ find_max_opacity(image->rows, midX, endY, -1, midY, 0, -1, &image->outlineInsetsBottom);
+ } else {
+ image->outlineInsetsTop = 0;
+ image->outlineInsetsBottom = 0;
+ }
+
+ int innerStartX = 1 + image->outlineInsetsLeft;
+ int innerStartY = 1 + image->outlineInsetsTop;
+ int innerEndX = endX - image->outlineInsetsRight;
+ int innerEndY = endY - image->outlineInsetsBottom;
+ int innerMidX = (innerEndX + innerStartX) / 2;
+ int innerMidY = (innerEndY + innerStartY) / 2;
+
+ // assuming the image is a round rect, compute the radius by marching
+ // diagonally from the top left corner towards the center
+ image->outlineFilled = is_opaque_over_row(image->rows[innerMidY], innerStartX, innerEndX)
+ && is_opaque_over_col(image->rows, innerMidX, innerStartY, innerStartY);
+
+ int diagonalInset = 0;
+ find_max_opacity(image->rows, innerStartX, innerStartY, innerMidX, innerMidY, 1, 1,
+ &diagonalInset);
+
+ // Determine source radius based upon inset
+ // radius = 1 / (sqrt(2) - 1) * inset
+ image->outlineRadius = 2.4142f * diagonalInset;
+
+ NOISY(printf("outline insets %d %d %d %d, rad %f, filled %d\n",
+ image->outlineFilled,
+ image->outlineInsetsLeft,
+ image->outlineInsetsTop,
+ image->outlineInsetsRight,
+ image->outlineInsetsBottom,
+ image->outlineRadius,
+ image->outlineFilled));
+}
+
static uint32_t get_color(
png_bytepp rows, int left, int top, int right, int bottom)
@@ -571,6 +671,9 @@
image->layoutBoundsRight, image->layoutBoundsBottom));
}
+ // use opacity of pixels to estimate the round rect outline
+ get_outline(image);
+
// If padding is not yet specified, take values from size.
if (image->info9Patch.paddingLeft < 0) {
image->info9Patch.paddingLeft = xDivs[0];
@@ -966,9 +1069,10 @@
int bit_depth, interlace_type, compression_type;
int i;
- png_unknown_chunk unknowns[2];
+ png_unknown_chunk unknowns[3];
unknowns[0].data = NULL;
unknowns[1].data = NULL;
+ unknowns[2].data = NULL;
png_bytepp outRows = (png_bytepp) malloc((int) imageInfo.height * sizeof(png_bytep));
if (outRows == (png_bytepp) 0) {
@@ -1038,12 +1142,17 @@
}
if (imageInfo.is9Patch) {
- int chunk_count = 1 + (imageInfo.haveLayoutBounds ? 1 : 0);
- int p_index = imageInfo.haveLayoutBounds ? 1 : 0;
- int b_index = 0;
+ int chunk_count = 2 + (imageInfo.haveLayoutBounds ? 1 : 0);
+ int p_index = imageInfo.haveLayoutBounds ? 2 : 1;
+ int b_index = 1;
+ int o_index = 0;
+
+ // Chunks ordered thusly because older platforms depend on the base 9 patch data being last
png_byte *chunk_names = imageInfo.haveLayoutBounds
- ? (png_byte*)"npLb\0npTc\0"
- : (png_byte*)"npTc";
+ ? (png_byte*)"npOl\0npLb\0npTc\0"
+ : (png_byte*)"npOl\0npTc";
+
+ // base 9 patch data
NOISY(printf("Adding 9-patch info...\n"));
strcpy((char*)unknowns[p_index].name, "npTc");
unknowns[p_index].data = (png_byte*)imageInfo.serialize9patch();
@@ -1051,6 +1160,18 @@
// TODO: remove the check below when everything works
checkNinePatchSerialization(&imageInfo.info9Patch, unknowns[p_index].data);
+ // automatically generated 9 patch outline data
+ int chunk_size = sizeof(png_uint_32) * 6;
+ strcpy((char*)unknowns[o_index].name, "npOl");
+ unknowns[o_index].data = (png_byte*) calloc(chunk_size, 1);
+ png_byte outputData[chunk_size];
+ memcpy(&outputData, &imageInfo.outlineInsetsLeft, 4 * sizeof(png_uint_32));
+ ((float*) outputData)[4] = imageInfo.outlineRadius;
+ ((png_uint_32*) outputData)[5] = imageInfo.outlineFilled ? 1 : 0;
+ memcpy(unknowns[o_index].data, &outputData, chunk_size);
+ unknowns[o_index].size = chunk_size;
+
+ // optional optical inset / layout bounds data
if (imageInfo.haveLayoutBounds) {
int chunk_size = sizeof(png_uint_32) * 4;
strcpy((char*)unknowns[b_index].name, "npLb");
@@ -1099,6 +1220,7 @@
free(outRows);
free(unknowns[0].data);
free(unknowns[1].data);
+ free(unknowns[2].data);
png_get_IHDR(write_ptr, write_info, &width, &height,
&bit_depth, &color_type, &interlace_type,
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 963c796..4f1d15e 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -931,6 +931,13 @@
// Build an empty <application> tag (required).
sp<XMLNode> app = XMLNode::newElement(filename, String16(), String16("application"));
+
+ // Add the 'hasCode' attribute which is never true for resource splits.
+ if (!addTagAttribute(app, RESOURCES_ANDROID_NAMESPACE, "hasCode",
+ "false", true, true)) {
+ return UNKNOWN_ERROR;
+ }
+
manifest->addChild(app);
root->addChild(manifest);
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 1942831..ead3b13 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -61,7 +61,7 @@
$(hide) mkdir -p $(dir $@)
$(hide) rm -f $@
$(hide) ls -l $(built_framework_classes)
- $(hide) java -jar $(built_layoutlib_create_jar) \
+ $(hide) java -ea -jar $(built_layoutlib_create_jar) \
$@ \
$(built_core_classes) \
$(built_framework_classes) \
diff --git a/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java b/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java
new file mode 100644
index 0000000..a3ec2cc
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java
@@ -0,0 +1,761 @@
+/*
+ * 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.
+ */
+
+package android.graphics;
+
+import java.awt.Composite;
+import java.awt.CompositeContext;
+import java.awt.RenderingHints;
+import java.awt.image.ColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+/*
+ * (non-Javadoc)
+ * The class is adapted from a demo tool for Blending Modes written by
+ * Romain Guy (romainguy@android.com). The tool is available at
+ * http://www.curious-creature.org/2006/09/20/new-blendings-modes-for-java2d/
+ */
+public final class BlendComposite implements Composite {
+ public enum BlendingMode {
+ NORMAL,
+ AVERAGE,
+ MULTIPLY,
+ SCREEN,
+ DARKEN,
+ LIGHTEN,
+ OVERLAY,
+ HARD_LIGHT,
+ SOFT_LIGHT,
+ DIFFERENCE,
+ NEGATION,
+ EXCLUSION,
+ COLOR_DODGE,
+ INVERSE_COLOR_DODGE,
+ SOFT_DODGE,
+ COLOR_BURN,
+ INVERSE_COLOR_BURN,
+ SOFT_BURN,
+ REFLECT,
+ GLOW,
+ FREEZE,
+ HEAT,
+ ADD,
+ SUBTRACT,
+ STAMP,
+ RED,
+ GREEN,
+ BLUE,
+ HUE,
+ SATURATION,
+ COLOR,
+ LUMINOSITY
+ }
+
+ public static final BlendComposite Normal = new BlendComposite(BlendingMode.NORMAL);
+ public static final BlendComposite Average = new BlendComposite(BlendingMode.AVERAGE);
+ public static final BlendComposite Multiply = new BlendComposite(BlendingMode.MULTIPLY);
+ public static final BlendComposite Screen = new BlendComposite(BlendingMode.SCREEN);
+ public static final BlendComposite Darken = new BlendComposite(BlendingMode.DARKEN);
+ public static final BlendComposite Lighten = new BlendComposite(BlendingMode.LIGHTEN);
+ public static final BlendComposite Overlay = new BlendComposite(BlendingMode.OVERLAY);
+ public static final BlendComposite HardLight = new BlendComposite(BlendingMode.HARD_LIGHT);
+ public static final BlendComposite SoftLight = new BlendComposite(BlendingMode.SOFT_LIGHT);
+ public static final BlendComposite Difference = new BlendComposite(BlendingMode.DIFFERENCE);
+ public static final BlendComposite Negation = new BlendComposite(BlendingMode.NEGATION);
+ public static final BlendComposite Exclusion = new BlendComposite(BlendingMode.EXCLUSION);
+ public static final BlendComposite ColorDodge = new BlendComposite(BlendingMode.COLOR_DODGE);
+ public static final BlendComposite InverseColorDodge = new BlendComposite(BlendingMode.INVERSE_COLOR_DODGE);
+ public static final BlendComposite SoftDodge = new BlendComposite(BlendingMode.SOFT_DODGE);
+ public static final BlendComposite ColorBurn = new BlendComposite(BlendingMode.COLOR_BURN);
+ public static final BlendComposite InverseColorBurn = new BlendComposite(BlendingMode.INVERSE_COLOR_BURN);
+ public static final BlendComposite SoftBurn = new BlendComposite(BlendingMode.SOFT_BURN);
+ public static final BlendComposite Reflect = new BlendComposite(BlendingMode.REFLECT);
+ public static final BlendComposite Glow = new BlendComposite(BlendingMode.GLOW);
+ public static final BlendComposite Freeze = new BlendComposite(BlendingMode.FREEZE);
+ public static final BlendComposite Heat = new BlendComposite(BlendingMode.HEAT);
+ public static final BlendComposite Add = new BlendComposite(BlendingMode.ADD);
+ public static final BlendComposite Subtract = new BlendComposite(BlendingMode.SUBTRACT);
+ public static final BlendComposite Stamp = new BlendComposite(BlendingMode.STAMP);
+ public static final BlendComposite Red = new BlendComposite(BlendingMode.RED);
+ public static final BlendComposite Green = new BlendComposite(BlendingMode.GREEN);
+ public static final BlendComposite Blue = new BlendComposite(BlendingMode.BLUE);
+ public static final BlendComposite Hue = new BlendComposite(BlendingMode.HUE);
+ public static final BlendComposite Saturation = new BlendComposite(BlendingMode.SATURATION);
+ public static final BlendComposite Color = new BlendComposite(BlendingMode.COLOR);
+ public static final BlendComposite Luminosity = new BlendComposite(BlendingMode.LUMINOSITY);
+
+ private float alpha;
+ private BlendingMode mode;
+
+ private BlendComposite(BlendingMode mode) {
+ this(mode, 1.0f);
+ }
+
+ private BlendComposite(BlendingMode mode, float alpha) {
+ this.mode = mode;
+ setAlpha(alpha);
+ }
+
+ public static BlendComposite getInstance(BlendingMode mode) {
+ return new BlendComposite(mode);
+ }
+
+ public static BlendComposite getInstance(BlendingMode mode, float alpha) {
+ return new BlendComposite(mode, alpha);
+ }
+
+ public BlendComposite derive(BlendingMode mode) {
+ return this.mode == mode ? this : new BlendComposite(mode, getAlpha());
+ }
+
+ public BlendComposite derive(float alpha) {
+ return this.alpha == alpha ? this : new BlendComposite(getMode(), alpha);
+ }
+
+ public float getAlpha() {
+ return alpha;
+ }
+
+ public BlendingMode getMode() {
+ return mode;
+ }
+
+ private void setAlpha(float alpha) {
+ if (alpha < 0.0f || alpha > 1.0f) {
+ throw new IllegalArgumentException(
+ "alpha must be comprised between 0.0f and 1.0f");
+ }
+
+ this.alpha = alpha;
+ }
+
+ @Override
+ public int hashCode() {
+ return Float.floatToIntBits(alpha) * 31 + mode.ordinal();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof BlendComposite)) {
+ return false;
+ }
+
+ BlendComposite bc = (BlendComposite) obj;
+
+ if (mode != bc.mode) {
+ return false;
+ }
+
+ return alpha == bc.alpha;
+ }
+
+ public CompositeContext createContext(ColorModel srcColorModel,
+ ColorModel dstColorModel,
+ RenderingHints hints) {
+ return new BlendingContext(this);
+ }
+
+ private static final class BlendingContext implements CompositeContext {
+ private final Blender blender;
+ private final BlendComposite composite;
+
+ private BlendingContext(BlendComposite composite) {
+ this.composite = composite;
+ this.blender = Blender.getBlenderFor(composite);
+ }
+
+ public void dispose() {
+ }
+
+ public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
+ if (src.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
+ dstIn.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
+ dstOut.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
+ throw new IllegalStateException(
+ "Source and destination must store pixels as INT.");
+ }
+
+ int width = Math.min(src.getWidth(), dstIn.getWidth());
+ int height = Math.min(src.getHeight(), dstIn.getHeight());
+
+ float alpha = composite.getAlpha();
+
+ int[] srcPixel = new int[4];
+ int[] dstPixel = new int[4];
+ int[] result = new int[4];
+ int[] srcPixels = new int[width];
+ int[] dstPixels = new int[width];
+
+ for (int y = 0; y < height; y++) {
+ dstIn.getDataElements(0, y, width, 1, dstPixels);
+ if (alpha != 0) {
+ src.getDataElements(0, y, width, 1, srcPixels);
+ for (int x = 0; x < width; x++) {
+ // pixels are stored as INT_ARGB
+ // our arrays are [R, G, B, A]
+ int pixel = srcPixels[x];
+ srcPixel[0] = (pixel >> 16) & 0xFF;
+ srcPixel[1] = (pixel >> 8) & 0xFF;
+ srcPixel[2] = (pixel ) & 0xFF;
+ srcPixel[3] = (pixel >> 24) & 0xFF;
+
+ pixel = dstPixels[x];
+ dstPixel[0] = (pixel >> 16) & 0xFF;
+ dstPixel[1] = (pixel >> 8) & 0xFF;
+ dstPixel[2] = (pixel ) & 0xFF;
+ dstPixel[3] = (pixel >> 24) & 0xFF;
+
+ result = blender.blend(srcPixel, dstPixel, result);
+
+ // mixes the result with the opacity
+ if (alpha == 1) {
+ dstPixels[x] = (result[3] & 0xFF) << 24 |
+ (result[0] & 0xFF) << 16 |
+ (result[1] & 0xFF) << 8 |
+ result[2] & 0xFF;
+ } else {
+ dstPixels[x] =
+ ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 |
+ ((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 |
+ ((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) << 8 |
+ (int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF;
+ }
+
+ }
+ }
+ dstOut.setDataElements(0, y, width, 1, dstPixels);
+ }
+ }
+ }
+
+ private static abstract class Blender {
+ public abstract int[] blend(int[] src, int[] dst, int[] result);
+
+ private static void RGBtoHSL(int r, int g, int b, float[] hsl) {
+ float var_R = (r / 255f);
+ float var_G = (g / 255f);
+ float var_B = (b / 255f);
+
+ float var_Min;
+ float var_Max;
+ float del_Max;
+
+ if (var_R > var_G) {
+ var_Min = var_G;
+ var_Max = var_R;
+ } else {
+ var_Min = var_R;
+ var_Max = var_G;
+ }
+ if (var_B > var_Max) {
+ var_Max = var_B;
+ }
+ if (var_B < var_Min) {
+ var_Min = var_B;
+ }
+
+ del_Max = var_Max - var_Min;
+
+ float H, S, L;
+ L = (var_Max + var_Min) / 2f;
+
+ if (del_Max - 0.01f <= 0.0f) {
+ H = 0;
+ S = 0;
+ } else {
+ if (L < 0.5f) {
+ S = del_Max / (var_Max + var_Min);
+ } else {
+ S = del_Max / (2 - var_Max - var_Min);
+ }
+
+ float del_R = (((var_Max - var_R) / 6f) + (del_Max / 2f)) / del_Max;
+ float del_G = (((var_Max - var_G) / 6f) + (del_Max / 2f)) / del_Max;
+ float del_B = (((var_Max - var_B) / 6f) + (del_Max / 2f)) / del_Max;
+
+ if (var_R == var_Max) {
+ H = del_B - del_G;
+ } else if (var_G == var_Max) {
+ H = (1 / 3f) + del_R - del_B;
+ } else {
+ H = (2 / 3f) + del_G - del_R;
+ }
+ if (H < 0) {
+ H += 1;
+ }
+ if (H > 1) {
+ H -= 1;
+ }
+ }
+
+ hsl[0] = H;
+ hsl[1] = S;
+ hsl[2] = L;
+ }
+
+ private static void HSLtoRGB(float h, float s, float l, int[] rgb) {
+ int R, G, B;
+
+ if (s - 0.01f <= 0.0f) {
+ R = (int) (l * 255.0f);
+ G = (int) (l * 255.0f);
+ B = (int) (l * 255.0f);
+ } else {
+ float var_1, var_2;
+ if (l < 0.5f) {
+ var_2 = l * (1 + s);
+ } else {
+ var_2 = (l + s) - (s * l);
+ }
+ var_1 = 2 * l - var_2;
+
+ R = (int) (255.0f * hue2RGB(var_1, var_2, h + (1.0f / 3.0f)));
+ G = (int) (255.0f * hue2RGB(var_1, var_2, h));
+ B = (int) (255.0f * hue2RGB(var_1, var_2, h - (1.0f / 3.0f)));
+ }
+
+ rgb[0] = R;
+ rgb[1] = G;
+ rgb[2] = B;
+ }
+
+ private static float hue2RGB(float v1, float v2, float vH) {
+ if (vH < 0.0f) {
+ vH += 1.0f;
+ }
+ if (vH > 1.0f) {
+ vH -= 1.0f;
+ }
+ if ((6.0f * vH) < 1.0f) {
+ return (v1 + (v2 - v1) * 6.0f * vH);
+ }
+ if ((2.0f * vH) < 1.0f) {
+ return (v2);
+ }
+ if ((3.0f * vH) < 2.0f) {
+ return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f);
+ }
+ return (v1);
+ }
+
+ public static Blender getBlenderFor(BlendComposite composite) {
+ switch (composite.getMode()) {
+ case NORMAL:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ System.arraycopy(src, 0, result, 0, 4);
+ return result;
+ }
+ };
+ case ADD:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 4; i++) {
+ result[i] = Math.min(255, src[i] + dst[i]);
+ }
+ return result;
+ }
+ };
+ case AVERAGE:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = (src[i] + dst[i]) >> 1;
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case BLUE:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ System.arraycopy(dst, 0, result, 0, 3);
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case COLOR:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ float[] srcHSL = new float[3];
+ RGBtoHSL(src[0], src[1], src[2], srcHSL);
+ float[] dstHSL = new float[3];
+ RGBtoHSL(dst[0], dst[1], dst[2], dstHSL);
+
+ HSLtoRGB(srcHSL[0], srcHSL[1], dstHSL[2], result);
+ result[3] = Math.min(255, src[3] + dst[3]);
+
+ return result;
+ }
+ };
+ case COLOR_BURN:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = src[i] == 0 ? 0 :
+ Math.max(0, 255 - (((255 - dst[i]) << 8) / src[i]));
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case COLOR_DODGE:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = src[i] == 255 ? 255 :
+ Math.min((dst[i] << 8) / (255 - src[i]), 255);
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case DARKEN:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = Math.min(src[i], dst[i]);
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case DIFFERENCE:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = dst[i] + src[i] - (dst[i] * src[i] >> 7);
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case EXCLUSION:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = dst[i] + src[i] - (dst[i] * src[i] >> 7);
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case FREEZE:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = src[i] == 0 ? 0 :
+ Math.max(0, 255 - (255 - dst[i]) * (255 - dst[i]) / src[i]);
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case GLOW:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = dst[i] == 255 ? 255 :
+ Math.min(255, src[i] * src[i] / (255 - dst[i]));
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case GREEN:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ dst[0],
+ dst[1],
+ src[2],
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case HARD_LIGHT:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ src[0] < 128 ? dst[0] * src[0] >> 7 :
+ 255 - ((255 - src[0]) * (255 - dst[0]) >> 7),
+ src[1] < 128 ? dst[1] * src[1] >> 7 :
+ 255 - ((255 - src[1]) * (255 - dst[1]) >> 7),
+ src[2] < 128 ? dst[2] * src[2] >> 7 :
+ 255 - ((255 - src[2]) * (255 - dst[2]) >> 7),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case HEAT:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ dst[0] == 0 ? 0 : Math.max(0, 255 - (255 - src[0]) * (255 - src[0]) / dst[0]),
+ dst[1] == 0 ? 0 : Math.max(0, 255 - (255 - src[1]) * (255 - src[1]) / dst[1]),
+ dst[2] == 0 ? 0 : Math.max(0, 255 - (255 - src[2]) * (255 - src[2]) / dst[2]),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case HUE:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ float[] srcHSL = new float[3];
+ RGBtoHSL(src[0], src[1], src[2], srcHSL);
+ float[] dstHSL = new float[3];
+ RGBtoHSL(dst[0], dst[1], dst[2], dstHSL);
+
+ HSLtoRGB(srcHSL[0], dstHSL[1], dstHSL[2], result);
+ result[3] = Math.min(255, src[3] + dst[3]);
+
+ return result;
+ }
+ };
+ case INVERSE_COLOR_BURN:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ dst[0] == 0 ? 0 :
+ Math.max(0, 255 - (((255 - src[0]) << 8) / dst[0])),
+ dst[1] == 0 ? 0 :
+ Math.max(0, 255 - (((255 - src[1]) << 8) / dst[1])),
+ dst[2] == 0 ? 0 :
+ Math.max(0, 255 - (((255 - src[2]) << 8) / dst[2])),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case INVERSE_COLOR_DODGE:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ dst[0] == 255 ? 255 :
+ Math.min((src[0] << 8) / (255 - dst[0]), 255),
+ dst[1] == 255 ? 255 :
+ Math.min((src[1] << 8) / (255 - dst[1]), 255),
+ dst[2] == 255 ? 255 :
+ Math.min((src[2] << 8) / (255 - dst[2]), 255),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case LIGHTEN:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = Math.max(src[i], dst[i]);
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case LUMINOSITY:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ float[] srcHSL = new float[3];
+ RGBtoHSL(src[0], src[1], src[2], srcHSL);
+ float[] dstHSL = new float[3];
+ RGBtoHSL(dst[0], dst[1], dst[2], dstHSL);
+
+ HSLtoRGB(dstHSL[0], dstHSL[1], srcHSL[2], result);
+ result[3] = Math.min(255, src[3] + dst[3]);
+
+ return result;
+ }
+ };
+ case MULTIPLY:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = (src[i] * dst[i]) >> 8;
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case NEGATION:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ 255 - Math.abs(255 - dst[0] - src[0]),
+ 255 - Math.abs(255 - dst[1] - src[1]),
+ 255 - Math.abs(255 - dst[2] - src[2]),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case OVERLAY:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ for (int i = 0; i < 3; i++) {
+ result[i] = dst[i] < 128 ? dst[i] * src[i] >> 7 :
+ 255 - ((255 - dst[i]) * (255 - src[i]) >> 7);
+ }
+ result[3] = Math.min(255, src[3] + dst[3]);
+ return result;
+ }
+ };
+ case RED:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ src[0],
+ dst[1],
+ dst[2],
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case REFLECT:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ src[0] == 255 ? 255 : Math.min(255, dst[0] * dst[0] / (255 - src[0])),
+ src[1] == 255 ? 255 : Math.min(255, dst[1] * dst[1] / (255 - src[1])),
+ src[2] == 255 ? 255 : Math.min(255, dst[2] * dst[2] / (255 - src[2])),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case SATURATION:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ float[] srcHSL = new float[3];
+ RGBtoHSL(src[0], src[1], src[2], srcHSL);
+ float[] dstHSL = new float[3];
+ RGBtoHSL(dst[0], dst[1], dst[2], dstHSL);
+
+ HSLtoRGB(dstHSL[0], srcHSL[1], dstHSL[2], result);
+ result[3] = Math.min(255, src[3] + dst[3]);
+
+ return result;
+ }
+ };
+ case SCREEN:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ 255 - ((255 - src[0]) * (255 - dst[0]) >> 8),
+ 255 - ((255 - src[1]) * (255 - dst[1]) >> 8),
+ 255 - ((255 - src[2]) * (255 - dst[2]) >> 8),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case SOFT_BURN:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ dst[0] + src[0] < 256 ?
+ (dst[0] == 255 ? 255 :
+ Math.min(255, (src[0] << 7) / (255 - dst[0]))) :
+ Math.max(0, 255 - (((255 - dst[0]) << 7) / src[0])),
+ dst[1] + src[1] < 256 ?
+ (dst[1] == 255 ? 255 :
+ Math.min(255, (src[1] << 7) / (255 - dst[1]))) :
+ Math.max(0, 255 - (((255 - dst[1]) << 7) / src[1])),
+ dst[2] + src[2] < 256 ?
+ (dst[2] == 255 ? 255 :
+ Math.min(255, (src[2] << 7) / (255 - dst[2]))) :
+ Math.max(0, 255 - (((255 - dst[2]) << 7) / src[2])),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case SOFT_DODGE:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ dst[0] + src[0] < 256 ?
+ (src[0] == 255 ? 255 :
+ Math.min(255, (dst[0] << 7) / (255 - src[0]))) :
+ Math.max(0, 255 - (((255 - src[0]) << 7) / dst[0])),
+ dst[1] + src[1] < 256 ?
+ (src[1] == 255 ? 255 :
+ Math.min(255, (dst[1] << 7) / (255 - src[1]))) :
+ Math.max(0, 255 - (((255 - src[1]) << 7) / dst[1])),
+ dst[2] + src[2] < 256 ?
+ (src[2] == 255 ? 255 :
+ Math.min(255, (dst[2] << 7) / (255 - src[2]))) :
+ Math.max(0, 255 - (((255 - src[2]) << 7) / dst[2])),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case SOFT_LIGHT:
+ break;
+ case STAMP:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ Math.max(0, Math.min(255, dst[0] + 2 * src[0] - 256)),
+ Math.max(0, Math.min(255, dst[1] + 2 * src[1] - 256)),
+ Math.max(0, Math.min(255, dst[2] + 2 * src[2] - 256)),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ case SUBTRACT:
+ return new Blender() {
+ @Override
+ public int[] blend(int[] src, int[] dst, int[] result) {
+ return new int[] {
+ Math.max(0, src[0] + dst[0] - 256),
+ Math.max(0, src[1] + dst[1] - 256),
+ Math.max(0, src[2] + dst[2] - 256),
+ Math.min(255, src[3] + dst[3])
+ };
+ }
+ };
+ }
+ throw new IllegalArgumentException("Blender not implement for " +
+ composite.getMode().name());
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 7c8ef70..2ff0fc1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -20,6 +20,7 @@
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.GcSnapshot;
+import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.Bitmap.Config;
@@ -534,7 +535,8 @@
// set the color
graphics.setColor(new Color(color, true /*alpha*/));
- Composite composite = PorterDuffXfermode_Delegate.getComposite(mode, 0xFF);
+ Composite composite = PorterDuffUtility.getComposite(
+ PorterDuffUtility.getPorterDuffMode(mode), 0xFF);
if (composite != null) {
graphics.setComposite(composite);
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
index ee90595..4ac376c 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
@@ -21,11 +21,10 @@
import android.graphics.PorterDuff.Mode;
-import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
-import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getAlphaCompositeRule;
+import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getComposite;
import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;
/**
@@ -57,7 +56,7 @@
@Override
public boolean isSupported() {
- return getAlphaCompositeRule(mMode) != -1;
+ return true;
}
@Override
@@ -68,7 +67,7 @@
@Override
public void applyFilter(Graphics2D g, int width, int height) {
BufferedImage image = createFilterImage(width, height);
- g.setComposite(getComposite());
+ g.setComposite(getComposite(mMode, 0xFF));
g.drawImage(image, 0, 0, null);
}
@@ -101,49 +100,36 @@
return image;
}
- private AlphaComposite getComposite() {
- return AlphaComposite.getInstance(getAlphaCompositeRule(mMode));
- }
-
// For filtering the colors, the src image should contain the "color" only for pixel values
// which are not transparent in the target image. But, we are using a simple rectangular image
- // completely filled with color. Hence some AlphaComposite rules do not apply as intended.
- // However, in such cases, they can usually be mapped to some other mode, which produces an
+ // completely filled with color. Hence some Composite rules do not apply as intended. However,
+ // in such cases, they can usually be mapped to some other mode, which produces an
// equivalent result.
private Mode getCompatibleMode(Mode mode) {
Mode m = mode;
+ // Modes that are directly supported:
+ // CLEAR, DST, SRC_IN, DST_IN, DST_OUT, SRC_ATOP, DARKEN, LIGHTEN, MULTIPLY, SCREEN,
+ // ADD, OVERLAY
switch (mode) {
- // Modes that are directly supported.
- case CLEAR:
- case DST:
- case SRC_IN:
- case DST_IN:
- case DST_OUT:
- case SRC_ATOP:
- break;
- // Modes that can be mapped to one of the supported modes.
- case SRC:
- m = Mode.SRC_IN;
- break;
- case SRC_OVER:
- m = Mode.SRC_ATOP;
- break;
- case DST_OVER:
- m = Mode.DST;
- break;
- case SRC_OUT:
- m = Mode.CLEAR;
- break;
- case DST_ATOP:
- m = Mode.DST_IN;
- break;
- case XOR:
- m = Mode.DST_OUT;
- break;
- // This mode is not supported, but used by Action Bar Overflow Popup Menus. We map this
- // to the closest supported mode, to prevent showing excessive warnings to the user.
- case MULTIPLY:
- m = Mode.SRC_IN;
+ // Modes that can be mapped to one of the supported modes.
+ case SRC:
+ m = Mode.SRC_IN;
+ break;
+ case SRC_OVER:
+ m = Mode.SRC_ATOP;
+ break;
+ case DST_OVER:
+ m = Mode.DST;
+ break;
+ case SRC_OUT:
+ m = Mode.CLEAR;
+ break;
+ case DST_ATOP:
+ m = Mode.DST_IN;
+ break;
+ case XOR:
+ m = Mode.DST_OUT;
+ break;
}
return m;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
index f6c36b6..8825f84 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
@@ -16,17 +16,14 @@
package android.graphics;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.PorterDuff.Mode;
-import java.awt.AlphaComposite;
import java.awt.Composite;
-import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getAlphaCompositeRule;
import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;
/**
@@ -58,7 +55,7 @@
@Override
public Composite getComposite(int alpha) {
- return getComposite(mMode, alpha);
+ return PorterDuffUtility.getComposite(mMode, alpha);
}
@Override
@@ -72,9 +69,6 @@
return null;
}
- public static Composite getComposite(int mode, int alpha) {
- return getComposite(getPorterDuffMode(mode), alpha);
- }
// ---- native methods ----
@@ -90,17 +84,4 @@
mMode = getPorterDuffMode(mode);
}
- private static Composite getComposite(Mode mode, int alpha255) {
- float alpha1 = alpha255 != 0xFF ? alpha255 / 255.f : 1.f;
- int rule = getAlphaCompositeRule(mode);
- if (rule >= 0) {
- return AlphaComposite.getInstance(rule, alpha1);
- }
-
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
- String.format("Unsupported PorterDuff Mode: %1$s", mode.name()),
- null, null /*data*/);
-
- return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
- }
}
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 2f40003..6927b26 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -72,7 +72,7 @@
@Override
public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4,
- boolean arg5, boolean arg6, int arg7, int arg8, boolean arg9)
+ boolean arg5, boolean arg6, int arg7, int arg8, boolean arg9, boolean arg10)
throws RemoteException {
// TODO Auto-generated method stub
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
similarity index 60%
rename from tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
index 112250d..607e628 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
@@ -14,24 +14,23 @@
* limitations under the License.
*/
-package android.content.res;
+package com.android.layoutlib.bridge.android;
import java.util.Locale;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import com.ibm.icu.util.ULocale;
/**
- * Delegate used to provide new implementation of a select few methods of {@link Resources}
+ * This class provides an alternate implementation for {@code java.util.Locale#toLanguageTag}
+ * which is only available after Java 6.
*
- * Through the layoutlib_create tool, the original methods of Resources have been replaced
- * by calls to methods of the same name in this delegate class.
- *
+ * The create tool re-writes references to the above mentioned method to this one. Hence it's
+ * imperative that this class is not deleted unless the create tool is modified.
*/
-public class Resources_Delegate {
+@SuppressWarnings("UnusedDeclaration")
+public class AndroidLocale {
- @LayoutlibDelegate
- /*package*/ static String localeToLanguageTag(Resources res, Locale locale) {
+ public static String toLanguageTag(Locale locale) {
return ULocale.forLocale(locale).toLanguageTag();
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index efd55bf..70a7be8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1045,6 +1045,12 @@
}
@Override
+ public File getCodeCacheDir() {
+ // pass
+ return null;
+ }
+
+ @Override
public File getExternalCacheDir() {
// pass
return null;
@@ -1083,6 +1089,12 @@
}
@Override
+ public File getNoBackupFilesDir() {
+ // pass
+ return null;
+ }
+
+ @Override
public File getExternalFilesDir(String type) {
// pass
return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
index bc53e93..9588035 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
@@ -19,11 +19,14 @@
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
+import android.graphics.BlendComposite;
+import android.graphics.BlendComposite.BlendingMode;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter_Delegate;
import android.graphics.PorterDuffXfermode_Delegate;
import java.awt.AlphaComposite;
+import java.awt.Composite;
/**
* Provides various utility methods for {@link PorterDuffColorFilter_Delegate} and {@link
@@ -51,46 +54,54 @@
}
/**
- * A utility method to convert the porterDuffMode to an int to be used as a rule for {@link
- * AlphaComposite}. If {@code AlphaComposite} doesn't support the mode, -1 is returned.
+ * A utility method to get the {@link Composite} that represents the filter for the given
+ * PorterDuff mode and the alpha. Defaults to {@link Mode#SRC_OVER} for invalid modes.
*/
- public static int getAlphaCompositeRule(Mode porterDuffMode) {
- switch (porterDuffMode) {
+ public static Composite getComposite(Mode mode, int alpha255) {
+ float alpha1 = alpha255 != 0xFF ? alpha255 / 255.f : 1.f;
+ switch (mode) {
case CLEAR:
- return AlphaComposite.CLEAR;
- case DARKEN:
- break;
- case DST:
- return AlphaComposite.DST;
- case DST_ATOP:
- return AlphaComposite.DST_ATOP;
- case DST_IN:
- return AlphaComposite.DST_IN;
- case DST_OUT:
- return AlphaComposite.DST_OUT;
- case DST_OVER:
- return AlphaComposite.DST_OVER;
- case LIGHTEN:
- break;
- case MULTIPLY:
- break;
- case SCREEN:
- break;
+ return AlphaComposite.getInstance(AlphaComposite.CLEAR, alpha1);
case SRC:
- return AlphaComposite.SRC;
- case SRC_ATOP:
- return AlphaComposite.SRC_ATOP;
- case SRC_IN:
- return AlphaComposite.SRC_IN;
- case SRC_OUT:
- return AlphaComposite.SRC_OUT;
+ return AlphaComposite.getInstance(AlphaComposite.SRC, alpha1);
+ case DST:
+ return AlphaComposite.getInstance(AlphaComposite.DST, alpha1);
case SRC_OVER:
- return AlphaComposite.SRC_OVER;
+ return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
+ case DST_OVER:
+ return AlphaComposite.getInstance(AlphaComposite.DST_OVER, alpha1);
+ case SRC_IN:
+ return AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha1);
+ case DST_IN:
+ return AlphaComposite.getInstance(AlphaComposite.DST_IN, alpha1);
+ case SRC_OUT:
+ return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, alpha1);
+ case DST_OUT:
+ return AlphaComposite.getInstance(AlphaComposite.DST_OUT, alpha1);
+ case SRC_ATOP:
+ return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha1);
+ case DST_ATOP:
+ return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, alpha1);
case XOR:
- return AlphaComposite.XOR;
- }
- // This is an unsupported mode.
- return -1;
+ return AlphaComposite.getInstance(AlphaComposite.XOR, alpha1);
+ case DARKEN:
+ return BlendComposite.getInstance(BlendingMode.DARKEN, alpha1);
+ case LIGHTEN:
+ return BlendComposite.getInstance(BlendingMode.LIGHTEN, alpha1);
+ case MULTIPLY:
+ return BlendComposite.getInstance(BlendingMode.MULTIPLY, alpha1);
+ case SCREEN:
+ return BlendComposite.getInstance(BlendingMode.SCREEN, alpha1);
+ case ADD:
+ return BlendComposite.getInstance(BlendingMode.ADD, alpha1);
+ case OVERLAY:
+ return BlendComposite.getInstance(BlendingMode.OVERLAY, alpha1);
+ default:
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
+ String.format("Unsupported PorterDuff Mode: %1$s", mode.name()),
+ null, null /*data*/);
+ return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
+ }
}
}
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 8de64db..727b194 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -39,7 +39,8 @@
The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the configuration
is done in the main() method and the CreateInfo structure is expected to change with the Android
-platform as new classes are added, changed or removed.
+platform as new classes are added, changed or removed. Some configuration that may be platform
+dependent is also present elsewhere in code.
The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the platform, that
provides all the necessary missing implementation for rendering graphics in Eclipse.
@@ -95,7 +96,7 @@
- specific classes to refactor.
Each of these are specific strategies we use to be able to modify the Android code to fit within the
-Eclipse renderer. These strategies are explained beow.
+Eclipse renderer. These strategies are explained below.
The core method of the generator is transform(): it takes an input ASM ClassReader and modifies it
to produce a byte array suitable for the final JAR file.
@@ -130,9 +131,11 @@
valid StackMapTable. As a side benefit of this, we can continue to support Java 6 because Java 7 on
Mac has horrible font rendering support.
-ReplaceMethodCallsAdapter replaces calls to certain methods. Currently, it only rewrites calls to
-specialized versions of java.lang.System.arraycopy(), which are not part of the Desktop VM to call
-the more general method java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V.
+ReplaceMethodCallsAdapter replaces calls to certain methods. This is different from the
+DelegateMethodAdapter since it doesn't preserve the original copy of the method and more importantly
+changes the calls to a method in each class instead of changing the implementation of the method.
+This is useful for methods in the Java namespace where we cannot add delegates. The configuration
+for this is not done through the CreateInfo class, but done in the ReplaceMethodAdapter.
The ClassAdapters are chained together to achieve the desired output. (Look at section 2.2.7
Transformation chains in the asm user guide, link in the References.) The order of execution of
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
index 767e597..e043d4d 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
@@ -724,9 +724,8 @@
considerDesc(desc);
- // Check if method is a specialized version of java.lang.System.arrayCopy()
- if (owner.equals("java/lang/System") && name.equals("arraycopy")
- && !desc.equals("(Ljava/lang/Object;ILjava/lang/Object;II)V")) {
+ // Check if method needs to replaced by a call to a different method.
+ if (ReplaceMethodCallsAdapter.isReplacementNeeded(owner, name, desc)) {
mReplaceMethodCallClasses.add(mOwnerClass);
}
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 552fb6c..8fb8928 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -126,7 +126,6 @@
"android.content.res.Resources$Theme#obtainStyledAttributes",
"android.content.res.Resources$Theme#resolveAttribute",
"android.content.res.Resources$Theme#resolveAttributes",
- "android.content.res.Resources#localeToLanguageTag",
"android.content.res.AssetManager#newTheme",
"android.content.res.AssetManager#deleteTheme",
"android.content.res.AssetManager#applyThemeStyle",
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
index ae17417..0b5fb46 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
@@ -20,12 +20,15 @@
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
- * Replaces calls to certain methods that do not exist in the Desktop VM.
+ * Replaces calls to certain methods that do not exist in the Desktop VM. Useful for methods in the
+ * "java" package.
*/
public class ReplaceMethodCallsAdapter extends ClassVisitor {
@@ -37,6 +40,60 @@
"([CI[CII)V", "([BI[BII)V", "([SI[SII)V", "([II[III)V",
"([JI[JII)V", "([FI[FII)V", "([DI[DII)V", "([ZI[ZII)V"));
+ private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<MethodReplacer>(2);
+
+ // Static initialization block to initialize METHOD_REPLACERS.
+ static {
+ // Case 1: java.lang.System.arraycopy()
+ METHOD_REPLACERS.add(new MethodReplacer() {
+ @Override
+ public boolean isNeeded(String owner, String name, String desc) {
+ return owner.equals("java/lang/System") && name.equals("arraycopy") &&
+ ARRAYCOPY_DESCRIPTORS.contains(desc);
+ }
+
+ @Override
+ public void replace(int opcode, String owner, String name, String desc,
+ int[] opcodeOut, String[] output) {
+ assert isNeeded(owner, name, desc) && output.length == 3
+ && opcodeOut.length == 1;
+ opcodeOut[0] = opcode;
+ output[0] = owner;
+ output[1] = name;
+ output[2] = "(Ljava/lang/Object;ILjava/lang/Object;II)V";
+ }
+ });
+
+ // Case 2: java.util.Locale.toLanguageTag()
+ METHOD_REPLACERS.add(new MethodReplacer() {
+ @Override
+ public boolean isNeeded(String owner, String name, String desc) {
+ return owner.equals("java/util/Locale") && name.equals("toLanguageTag") &&
+ "()Ljava/lang/String;".equals(desc);
+ }
+
+ @Override
+ public void replace(int opcode, String owner, String name, String desc,
+ int[] opcodeOut, String[] output) {
+ assert isNeeded(owner, name, desc) && output.length == 3
+ && opcodeOut.length == 1;
+ opcodeOut[0] = Opcodes.INVOKESTATIC;
+ output[0] = "com.android.layoutlib.bridge.android.AndroidLocale";
+ output[1] = name;
+ output[2] = "(Ljava/util/Locale;)Ljava/lang/String;";
+ }
+ });
+ }
+
+ public static boolean isReplacementNeeded(String owner, String name, String desc) {
+ for (MethodReplacer replacer : METHOD_REPLACERS) {
+ if (replacer.isNeeded(owner, name, desc)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public ReplaceMethodCallsAdapter(ClassVisitor cv) {
super(Opcodes.ASM4, cv);
}
@@ -56,13 +113,34 @@
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
// Check if method is a specialized version of java.lang.System.arrayCopy
- if (owner.equals("java/lang/System") && name.equals("arraycopy")) {
-
- if (ARRAYCOPY_DESCRIPTORS.contains(desc)) {
- desc = "(Ljava/lang/Object;ILjava/lang/Object;II)V";
+ for (MethodReplacer replacer : METHOD_REPLACERS) {
+ if (replacer.isNeeded(owner, name, desc)) {
+ String[] output = new String[3];
+ int[] opcodeOut = new int[1];
+ replacer.replace(opcode, owner, name, desc, opcodeOut, output);
+ opcode = opcodeOut[0];
+ owner = output[0];
+ name = output[1];
+ desc = output[2];
+ break;
}
}
super.visitMethodInsn(opcode, owner, name, desc);
}
}
+
+ private interface MethodReplacer {
+ public boolean isNeeded(String owner, String name, String desc);
+
+ /**
+ * This method must update the values of the output arrays with the new values of method
+ * attributes - opcode, owner, name and desc.
+ * @param opcodeOut An array that will contain the new value of the opcode. The size of
+ * the array must be 1.
+ * @param output An array that will contain the new values of the owner, name and desc in
+ * that order. The size of the array must be 3.
+ */
+ public void replace(int opcode, String owner, String name, String desc, int[] opcodeOut,
+ String[] output);
+ }
}
diff --git a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl b/wifi/java/android/net/wifi/IRttManager.aidl
similarity index 68%
copy from telecomm/java/android/telecomm/CallServiceDescriptor.aidl
copy to wifi/java/android/net/wifi/IRttManager.aidl
index f517c73..d929f55 100644
--- a/telecomm/java/android/telecomm/CallServiceDescriptor.aidl
+++ b/wifi/java/android/net/wifi/IRttManager.aidl
@@ -1,11 +1,11 @@
/*
- * Copyright 2014, The Android Open Source Project
+ * Copyright (C) 2008 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
+ * 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,
@@ -14,6 +14,14 @@
* limitations under the License.
*/
-package android.telecomm;
+package android.net.wifi;
-parcelable CallServiceDescriptor;
+import android.os.Messenger;
+
+/**
+ * {@hide}
+ */
+interface IRttManager
+{
+ Messenger getMessenger();
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 22ba924..292f1e8 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -41,6 +41,8 @@
List<WifiConfiguration> getConfiguredNetworks();
+ List<WifiConfiguration> getPrivilegedConfiguredNetworks();
+
int addOrUpdateNetwork(in WifiConfiguration config);
boolean removeNetwork(int netId);
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
new file mode 100644
index 0000000..50fd260
--- /dev/null
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -0,0 +1,334 @@
+package android.net.wifi;
+
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.util.AsyncChannel;
+
+import java.util.concurrent.CountDownLatch;
+
+/** @hide */
+@SystemApi
+public class RttManager {
+
+ private static final boolean DBG = true;
+ private static final String TAG = "RttManager";
+
+ public static final int RTT_TYPE_UNSPECIFIED = 0;
+ public static final int RTT_TYPE_ONE_SIDED = 1;
+ public static final int RTT_TYPE_11_V = 2;
+ public static final int RTT_TYPE_11_MC = 4;
+
+ public static final int RTT_PEER_TYPE_UNSPECIFIED = 0;
+ public static final int RTT_PEER_TYPE_AP = 1;
+ public static final int RTT_PEER_TYPE_STA = 2; /* requires NAN */
+
+ public static final int RTT_CHANNEL_WIDTH_20 = 0;
+ public static final int RTT_CHANNEL_WIDTH_40 = 1;
+ public static final int RTT_CHANNEL_WIDTH_80 = 2;
+ public static final int RTT_CHANNEL_WIDTH_160 = 3;
+ public static final int RTT_CHANNEL_WIDTH_80P80 = 4;
+ public static final int RTT_CHANNEL_WIDTH_5 = 5;
+ public static final int RTT_CHANNEL_WIDTH_10 = 6;
+ public static final int RTT_CHANNEL_WIDTH_UNSPECIFIED = -1;
+
+ public static final int RTT_STATUS_SUCCESS = 0;
+ public static final int RTT_STATUS_FAILURE = 1;
+ public static final int RTT_STATUS_FAIL_NO_RSP = 2;
+ public static final int RTT_STATUS_FAIL_REJECTED = 3;
+ public static final int RTT_STATUS_FAIL_NOT_SCHEDULED_YET = 4;
+ public static final int RTT_STATUS_FAIL_TM_TIMEOUT = 5;
+ public static final int RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL = 6;
+ public static final int RTT_STATUS_FAIL_NO_CAPABILITY = 7;
+ public static final int RTT_STATUS_ABORTED = 8;
+
+ public static final int REASON_UNSPECIFIED = -1;
+ public static final int REASON_INVALID_LISTENER = -2;
+ public static final int REASON_INVALID_REQUEST = -3;
+
+ public class Capabilities {
+ int supportedType;
+ int supportedPeerType;
+ }
+
+ public Capabilities getCapabilities() {
+ return new Capabilities();
+ }
+
+ /** specifies parameters for RTT request */
+ public static class RttParams {
+
+ /** type of device being ranged; one of RTT_PEER_TYPE_AP or RTT_PEER_TYPE_STA */
+ public int deviceType;
+
+ /** type of RTT being sought; one of RTT_TYPE_ONE_SIDED
+ * RTT_TYPE_11_V or RTT_TYPE_11_MC or RTT_TYPE_UNSPECIFIED */
+ public int requestType;
+
+ /** mac address of the device being ranged */
+ public String bssid;
+
+ /** channel frequency that the device is on; optional */
+ public int frequency;
+
+ /** optional channel width. wider channels result in better accuracy,
+ * but they take longer time, and even get aborted may times; use
+ * RTT_CHANNEL_WIDTH_UNSPECIFIED if not specifying */
+ public int channelWidth;
+
+ /** number of samples to be taken */
+ public int num_samples;
+
+ /** number of retries if a sample fails */
+ public int num_retries;
+ }
+
+ /** specifies RTT results */
+ public static class RttResult {
+ /** mac address of the device being ranged */
+ public String bssid;
+
+ /** status of the request */
+ public int status;
+
+ /** timestamp of completion, in microsecond since boot */
+ public long ts;
+
+ /** average RSSI observed */
+ public int rssi;
+
+ /** RSSI spread (i.e. max - min) */
+ public int rssi_spread;
+
+ /** average transmit rate */
+ public int tx_rate;
+
+ /** average round trip time in nano second */
+ public long rtt_ns;
+
+ /** standard deviation observed in round trip time */
+ public long rtt_sd_ns;
+
+ /** spread (i.e. max - min) round trip time */
+ public long rtt_spread_ns;
+
+ /** average distance in centimeter, computed based on rtt_ns */
+ public long distance_cm;
+
+ /** standard deviation observed in distance */
+ public long distance_sd_cm;
+
+ /** spread (i.e. max - min) distance */
+ public long distance_spread_cm;
+ }
+
+ public static interface RttListener {
+ public void onSuccess(RttResult results[]);
+ public void onFailure(int reason, String description);
+ public void onAborted();
+ }
+
+ public void startRanging(RttParams params[], RttListener listener) {
+ validateChannel();
+ sAsyncChannel.sendMessage(CMD_OP_START_RANGING, 0, removeListener(listener), params);
+ }
+
+ public void stopRanging(RttListener listener) {
+ validateChannel();
+ sAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
+ }
+
+ /* private methods */
+ public static final int CMD_OP_START_RANGING = 0;
+ public static final int CMD_OP_STOP_RANGING = 1;
+ public static final int CMD_OP_FAILED = 2;
+ public static final int CMD_OP_SUCCEEDED = 3;
+ public static final int CMD_OP_ABORTED = 4;
+
+ private Context mContext;
+ private IRttManager mService;
+
+ private static final int INVALID_KEY = 0;
+ private static int sListenerKey = 1;
+
+ private static final SparseArray sListenerMap = new SparseArray();
+ private static final Object sListenerMapLock = new Object();
+
+ private static AsyncChannel sAsyncChannel;
+ private static CountDownLatch sConnected;
+
+ private static final Object sThreadRefLock = new Object();
+ private static int sThreadRefCount;
+ private static HandlerThread sHandlerThread;
+
+ /**
+ * Create a new WifiScanner instance.
+ * Applications will almost always want to use
+ * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
+ * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
+ * @param context the application context
+ * @param service the Binder interface
+ * @hide
+ */
+
+ public RttManager(Context context, IRttManager service) {
+ mContext = context;
+ mService = service;
+ init();
+ }
+
+ private void init() {
+ synchronized (sThreadRefLock) {
+ if (++sThreadRefCount == 1) {
+ Messenger messenger = null;
+ try {
+ messenger = mService.getMessenger();
+ } catch (RemoteException e) {
+ /* do nothing */
+ } catch (SecurityException e) {
+ /* do nothing */
+ }
+
+ if (messenger == null) {
+ sAsyncChannel = null;
+ return;
+ }
+
+ sHandlerThread = new HandlerThread("WifiScanner");
+ sAsyncChannel = new AsyncChannel();
+ sConnected = new CountDownLatch(1);
+
+ sHandlerThread.start();
+ Handler handler = new ServiceHandler(sHandlerThread.getLooper());
+ sAsyncChannel.connect(mContext, handler, messenger);
+ try {
+ sConnected.await();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "interrupted wait at init");
+ }
+ }
+ }
+ }
+
+ private void validateChannel() {
+ if (sAsyncChannel == null) throw new IllegalStateException(
+ "No permission to access and change wifi or a bad initialization");
+ }
+
+ private static int putListener(Object listener) {
+ if (listener == null) return INVALID_KEY;
+ int key;
+ synchronized (sListenerMapLock) {
+ do {
+ key = sListenerKey++;
+ } while (key == INVALID_KEY);
+ sListenerMap.put(key, listener);
+ }
+ return key;
+ }
+
+ private static Object getListener(int key) {
+ if (key == INVALID_KEY) return null;
+ synchronized (sListenerMapLock) {
+ Object listener = sListenerMap.get(key);
+ return listener;
+ }
+ }
+
+ private static int getListenerKey(Object listener) {
+ if (listener == null) return INVALID_KEY;
+ synchronized (sListenerMapLock) {
+ int index = sListenerMap.indexOfValue(listener);
+ if (index == -1) {
+ return INVALID_KEY;
+ } else {
+ return sListenerMap.keyAt(index);
+ }
+ }
+ }
+
+ private static Object removeListener(int key) {
+ if (key == INVALID_KEY) return null;
+ synchronized (sListenerMapLock) {
+ Object listener = sListenerMap.get(key);
+ sListenerMap.remove(key);
+ return listener;
+ }
+ }
+
+ private static int removeListener(Object listener) {
+ int key = getListenerKey(listener);
+ if (key == INVALID_KEY) return key;
+ synchronized (sListenerMapLock) {
+ sListenerMap.remove(key);
+ return key;
+ }
+ }
+
+ private static class ServiceHandler extends Handler {
+ ServiceHandler(Looper looper) {
+ super(looper);
+ }
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+ if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+ sAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+ } else {
+ Log.e(TAG, "Failed to set up channel connection");
+ // This will cause all further async API calls on the WifiManager
+ // to fail and throw an exception
+ sAsyncChannel = null;
+ }
+ sConnected.countDown();
+ return;
+ case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
+ return;
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+ Log.e(TAG, "Channel connection lost");
+ // This will cause all further async API calls on the WifiManager
+ // to fail and throw an exception
+ sAsyncChannel = null;
+ getLooper().quit();
+ return;
+ }
+
+ Object listener = getListener(msg.arg2);
+ if (listener == null) {
+ if (DBG) Log.d(TAG, "invalid listener key = " + msg.arg2);
+ return;
+ } else {
+ if (DBG) Log.d(TAG, "listener key = " + msg.arg2);
+ }
+
+ switch (msg.what) {
+ /* ActionListeners grouped together */
+ case CMD_OP_SUCCEEDED :
+ ((RttListener) listener).onSuccess((RttResult[])msg.obj);
+ break;
+ case CMD_OP_FAILED :
+ ((RttListener) listener).onFailure(msg.arg1, (String)msg.obj);
+ removeListener(msg.arg2);
+ break;
+ case CMD_OP_ABORTED :
+ ((RttListener) listener).onAborted();
+ removeListener(msg.arg2);
+ break;
+ default:
+ if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
+ return;
+ }
+ }
+ }
+
+}
+
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index cf4cb89..8945e52 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.content.Context;
import android.net.DhcpInfo;
import android.net.wifi.ScanSettings;
@@ -82,7 +83,29 @@
* Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED
* @hide
*/
- public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled";
+ public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled";
+
+ /**
+ * Broadcast intent action indicating that the credential of a Wi-Fi network
+ * has been changed. One extra provides the ssid of the network. Another
+ * extra provides the event type, whether the credential is saved or forgot.
+ * @hide
+ */
+ @SystemApi
+ public static final String WIFI_CREDENTIAL_CHANGED_ACTION =
+ "android.net.wifi.WIFI_CREDENTIAL_CHANGED";
+ /** @hide */
+ @SystemApi
+ public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
+ /** @hide */
+ @SystemApi
+ public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid";
+ /** @hide */
+ @SystemApi
+ public static final int WIFI_CREDENTIAL_SAVED = 0;
+ /** @hide */
+ @SystemApi
+ public static final int WIFI_CREDENTIAL_FORGOT = 1;
/**
* Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
@@ -606,6 +629,16 @@
}
}
+ /** @hide */
+ @SystemApi
+ public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
+ try {
+ return mService.getPrivilegedConfiguredNetworks();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
/**
* Add a new network description to the set of configured networks.
* The {@code networkId} field of the supplied configuration object
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index f3294bb..4cdbc44 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -771,7 +771,13 @@
}
Object listener = getListener(msg.arg2);
- if (DBG) Log.d(TAG, "listener key = " + msg.arg2);
+
+ if (listener == null) {
+ if (DBG) Log.d(TAG, "invalid listener key = " + msg.arg2);
+ return;
+ } else {
+ if (DBG) Log.d(TAG, "listener key = " + msg.arg2);
+ }
switch (msg.what) {
/* ActionListeners grouped together */