Merge "Don't enqueue allowBackup=false apps for full backup attempts"
diff --git a/Android.mk b/Android.mk
index f3f1acb..e42a2f8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -238,6 +238,8 @@
core/java/android/service/wallpaper/IWallpaperConnection.aidl \
core/java/android/service/wallpaper/IWallpaperEngine.aidl \
core/java/android/service/wallpaper/IWallpaperService.aidl \
+ core/java/android/service/chooser/IChooserTargetService.aidl \
+ core/java/android/service/chooser/IChooserTargetResult.aidl \
core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl\
core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl\
core/java/android/view/accessibility/IAccessibilityManager.aidl \
@@ -333,8 +335,8 @@
media/java/android/media/IRingtonePlayer.aidl \
media/java/android/media/IVolumeController.aidl \
media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl \
+ media/java/android/media/midi/IMidiDeviceListener.aidl \
media/java/android/media/midi/IMidiDeviceServer.aidl \
- media/java/android/media/midi/IMidiListener.aidl \
media/java/android/media/midi/IMidiManager.aidl \
media/java/android/media/projection/IMediaProjection.aidl \
media/java/android/media/projection/IMediaProjectionCallback.aidl \
@@ -545,6 +547,7 @@
frameworks/base/core/java/android/view/textservice/SuggestionsInfo.aidl \
frameworks/base/core/java/android/service/carrier/MessagePdu.aidl \
frameworks/base/core/java/android/service/notification/StatusBarNotification.aidl \
+ frameworks/base/core/java/android/service/chooser/ChooserTarget.aidl \
frameworks/base/core/java/android/speech/tts/Voice.aidl \
frameworks/base/core/java/android/app/usage/UsageEvents.aidl \
frameworks/base/core/java/android/app/Notification.aidl \
diff --git a/api/current.txt b/api/current.txt
index 00afda2..c36d03f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21,6 +21,7 @@
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
field public static final java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
+ field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
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";
@@ -3544,6 +3545,7 @@
method public int getLargeMemoryClass();
method public int getLauncherLargeIconDensity();
method public int getLauncherLargeIconSize();
+ method public int getLockTaskModeState();
method public int getMemoryClass();
method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
@@ -3554,7 +3556,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 deprecated boolean isInLockTaskMode();
method public boolean isLowRamDevice();
method public static boolean isRunningInTestHarness();
method public static boolean isUserAMonkey();
@@ -3562,6 +3564,9 @@
method public void moveTaskToFront(int, int);
method public void moveTaskToFront(int, int, android.os.Bundle);
method public deprecated void restartPackage(java.lang.String);
+ field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1
+ field public static final int LOCK_TASK_MODE_NONE = 0; // 0x0
+ field public static final int LOCK_TASK_MODE_PINNED = 2; // 0x2
field public static final java.lang.String META_HOME_ALTERNATE = "android.app.home.alternate";
field public static final int MOVE_TASK_NO_USER_ACTION = 2; // 0x2
field public static final int MOVE_TASK_WITH_HOME = 1; // 0x1
@@ -5429,6 +5434,7 @@
method public void onPasswordFailed(android.content.Context, android.content.Intent);
method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
+ method public void onReadyForUserInitialization(android.content.Context, android.content.Intent);
method public void onReceive(android.content.Context, android.content.Intent);
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
@@ -5440,6 +5446,7 @@
field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
field public static final java.lang.String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
field public static final java.lang.String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
+ field public static final java.lang.String ACTION_READY_FOR_USER_INITIALIZATION = "android.app.action.READY_FOR_USER_INITIALIZATION";
field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
@@ -5451,6 +5458,7 @@
method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
method public void addUserRestriction(android.content.ComponentName, java.lang.String);
method public void clearCrossProfileIntentFilters(android.content.ComponentName);
+ method public void clearDeviceInitializerApp(android.content.ComponentName);
method public void clearDeviceOwnerApp(java.lang.String);
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
@@ -5494,6 +5502,7 @@
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
+ method public boolean isDeviceInitializerApp(java.lang.String);
method public boolean isDeviceOwnerApp(java.lang.String);
method public boolean isLockTaskPermitted(java.lang.String);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
@@ -5510,6 +5519,7 @@
method public void setAutoTimeRequired(android.content.ComponentName, boolean);
method public void setCameraDisabled(android.content.ComponentName, boolean);
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
+ method public boolean setDeviceInitializer(android.content.ComponentName, android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
@@ -5536,6 +5546,8 @@
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
+ method public boolean setUserEnabled(android.content.ComponentName);
+ method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
method public void uninstallAllUserCaCerts(android.content.ComponentName);
method public void uninstallCaCert(android.content.ComponentName, byte[]);
@@ -5557,6 +5569,10 @@
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
@@ -12902,7 +12918,6 @@
public static abstract class CameraManager.TorchCallback {
ctor public CameraManager.TorchCallback();
- method public void onTorchModeAvailable(java.lang.String);
method public void onTorchModeChanged(java.lang.String, boolean);
method public void onTorchModeUnavailable(java.lang.String);
}
@@ -15405,6 +15420,7 @@
method public void setOnSeekCompleteListener(android.media.MediaPlayer.OnSeekCompleteListener);
method public void setOnTimedTextListener(android.media.MediaPlayer.OnTimedTextListener);
method public void setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener);
+ method public void setPlaybackRate(float, int);
method public void setScreenOnWhilePlaying(boolean);
method public void setSurface(android.view.Surface);
method public void setVideoScalingMode(int);
@@ -15430,6 +15446,7 @@
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+ field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0; // 0x0
field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
}
@@ -24898,6 +24915,7 @@
field public static final int ORGANIZATION = 30; // 0x1e
field public static final int PHONE = 20; // 0x14
field public static final int STRUCTURED_NAME = 40; // 0x28
+ field public static final int STRUCTURED_PHONETIC_NAME = 37; // 0x25
field public static final int UNDEFINED = 0; // 0x0
}
@@ -27448,6 +27466,30 @@
}
+package android.service.chooser {
+
+ public final class ChooserTarget implements android.os.Parcelable {
+ ctor public ChooserTarget(java.lang.CharSequence, android.graphics.Bitmap, float, android.app.PendingIntent);
+ ctor public ChooserTarget(java.lang.CharSequence, android.graphics.Bitmap, float, android.content.IntentSender);
+ method public int describeContents();
+ method public android.graphics.Bitmap getIcon();
+ method public android.content.IntentSender getIntentSender();
+ method public float getScore();
+ method public java.lang.CharSequence getTitle();
+ method public boolean sendIntent(android.content.Context, android.content.Intent);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.chooser.ChooserTarget> CREATOR;
+ }
+
+ public abstract class ChooserTargetService extends android.app.Service {
+ ctor public ChooserTargetService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract java.util.List<android.service.chooser.ChooserTarget> onGetChooserTargets(android.content.ComponentName, android.content.IntentFilter);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.chooser.ChooserTargetService";
+ }
+
+}
+
package android.service.dreams {
public class DreamService extends android.app.Service implements android.view.Window.Callback {
@@ -29289,6 +29331,7 @@
}
public class TelephonyManager {
+ method public boolean canChangeDtmfToneLength();
method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
method public int getCallState();
method public android.telephony.CellLocation getCellLocation();
@@ -29324,6 +29367,7 @@
method public boolean isNetworkRoaming();
method public boolean isSmsCapable();
method public boolean isVoiceCapable();
+ method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index 4992d8d..52098e6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -29,6 +29,7 @@
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
field public static final java.lang.String BIND_CARRIER_MESSAGING_SERVICE = "android.permission.BIND_CARRIER_MESSAGING_SERVICE";
+ field public static final java.lang.String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
field public static final java.lang.String BIND_CONDITION_PROVIDER_SERVICE = "android.permission.BIND_CONDITION_PROVIDER_SERVICE";
field public static final java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE";
field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
@@ -3632,6 +3633,7 @@
method public int getLargeMemoryClass();
method public int getLauncherLargeIconDensity();
method public int getLauncherLargeIconSize();
+ method public int getLockTaskModeState();
method public int getMemoryClass();
method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
@@ -3642,7 +3644,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 deprecated boolean isInLockTaskMode();
method public boolean isLowRamDevice();
method public static boolean isRunningInTestHarness();
method public static boolean isUserAMonkey();
@@ -3650,6 +3652,9 @@
method public void moveTaskToFront(int, int);
method public void moveTaskToFront(int, int, android.os.Bundle);
method public deprecated void restartPackage(java.lang.String);
+ field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1
+ field public static final int LOCK_TASK_MODE_NONE = 0; // 0x0
+ field public static final int LOCK_TASK_MODE_PINNED = 2; // 0x2
field public static final java.lang.String META_HOME_ALTERNATE = "android.app.home.alternate";
field public static final int MOVE_TASK_NO_USER_ACTION = 2; // 0x2
field public static final int MOVE_TASK_WITH_HOME = 1; // 0x1
@@ -5523,6 +5528,7 @@
method public void onPasswordFailed(android.content.Context, android.content.Intent);
method public void onPasswordSucceeded(android.content.Context, android.content.Intent);
method public void onProfileProvisioningComplete(android.content.Context, android.content.Intent);
+ method public void onReadyForUserInitialization(android.content.Context, android.content.Intent);
method public void onReceive(android.content.Context, android.content.Intent);
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
@@ -5534,6 +5540,7 @@
field public static final java.lang.String ACTION_PASSWORD_FAILED = "android.app.action.ACTION_PASSWORD_FAILED";
field public static final java.lang.String ACTION_PASSWORD_SUCCEEDED = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
field public static final java.lang.String ACTION_PROFILE_PROVISIONING_COMPLETE = "android.app.action.PROFILE_PROVISIONING_COMPLETE";
+ field public static final java.lang.String ACTION_READY_FOR_USER_INITIALIZATION = "android.app.action.READY_FOR_USER_INITIALIZATION";
field public static final java.lang.String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
field public static final java.lang.String EXTRA_DISABLE_WARNING = "android.app.extra.DISABLE_WARNING";
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
@@ -5545,6 +5552,7 @@
method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
method public void addUserRestriction(android.content.ComponentName, java.lang.String);
method public void clearCrossProfileIntentFilters(android.content.ComponentName);
+ method public void clearDeviceInitializerApp(android.content.ComponentName);
method public void clearDeviceOwnerApp(java.lang.String);
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
method public void clearProfileOwner(android.content.ComponentName);
@@ -5561,6 +5569,7 @@
method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
method public java.util.List<java.lang.String> getCrossProfileWidgetProviders(android.content.ComponentName);
method public int getCurrentFailedPasswordAttempts();
+ method public java.lang.String getDeviceInitializerApp();
method public java.lang.String getDeviceOwner();
method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -5594,6 +5603,7 @@
method public boolean isActivePasswordSufficient();
method public boolean isAdminActive(android.content.ComponentName);
method public boolean isApplicationHidden(android.content.ComponentName, java.lang.String);
+ method public boolean isDeviceInitializerApp(java.lang.String);
method public boolean isDeviceOwnerApp(java.lang.String);
method public boolean isLockTaskPermitted(java.lang.String);
method public boolean isMasterVolumeMuted(android.content.ComponentName);
@@ -5611,6 +5621,7 @@
method public void setAutoTimeRequired(android.content.ComponentName, boolean);
method public void setCameraDisabled(android.content.ComponentName, boolean);
method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
+ method public boolean setDeviceInitializer(android.content.ComponentName, android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
method public void setLockTaskPackages(android.content.ComponentName, java.lang.String[]) throws java.lang.SecurityException;
@@ -5637,6 +5648,8 @@
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
+ method public boolean setUserEnabled(android.content.ComponentName);
+ method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap);
method public boolean switchUser(android.content.ComponentName, android.os.UserHandle);
method public void uninstallAllUserCaCerts(android.content.ComponentName);
method public void uninstallCaCert(android.content.ComponentName, byte[]);
@@ -5660,6 +5673,10 @@
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+ field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
@@ -13178,7 +13195,6 @@
public static abstract class CameraManager.TorchCallback {
ctor public CameraManager.TorchCallback();
- method public void onTorchModeAvailable(java.lang.String);
method public void onTorchModeChanged(java.lang.String, boolean);
method public void onTorchModeUnavailable(java.lang.String);
}
@@ -16401,6 +16417,7 @@
method public void setOnSeekCompleteListener(android.media.MediaPlayer.OnSeekCompleteListener);
method public void setOnTimedTextListener(android.media.MediaPlayer.OnTimedTextListener);
method public void setOnVideoSizeChangedListener(android.media.MediaPlayer.OnVideoSizeChangedListener);
+ method public void setPlaybackRate(float, int);
method public void setScreenOnWhilePlaying(boolean);
method public void setSurface(android.view.Surface);
method public void setVideoScalingMode(int);
@@ -16426,6 +16443,7 @@
field public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3; // 0x3
field public static final int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700; // 0x2bc
field public static final java.lang.String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+ field public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0; // 0x0
field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT = 1; // 0x1
field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
}
@@ -26497,6 +26515,7 @@
field public static final int ORGANIZATION = 30; // 0x1e
field public static final int PHONE = 20; // 0x14
field public static final int STRUCTURED_NAME = 40; // 0x28
+ field public static final int STRUCTURED_PHONETIC_NAME = 37; // 0x25
field public static final int UNDEFINED = 0; // 0x0
}
@@ -29048,6 +29067,30 @@
}
+package android.service.chooser {
+
+ public final class ChooserTarget implements android.os.Parcelable {
+ ctor public ChooserTarget(java.lang.CharSequence, android.graphics.Bitmap, float, android.app.PendingIntent);
+ ctor public ChooserTarget(java.lang.CharSequence, android.graphics.Bitmap, float, android.content.IntentSender);
+ method public int describeContents();
+ method public android.graphics.Bitmap getIcon();
+ method public android.content.IntentSender getIntentSender();
+ method public float getScore();
+ method public java.lang.CharSequence getTitle();
+ method public boolean sendIntent(android.content.Context, android.content.Intent);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.chooser.ChooserTarget> CREATOR;
+ }
+
+ public abstract class ChooserTargetService extends android.app.Service {
+ ctor public ChooserTargetService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract java.util.List<android.service.chooser.ChooserTarget> onGetChooserTargets(android.content.ComponentName, android.content.IntentFilter);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.chooser.ChooserTargetService";
+ }
+
+}
+
package android.service.dreams {
public class DreamService extends android.app.Service implements android.view.Window.Callback {
@@ -30893,8 +30936,8 @@
method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle);
field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
- field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
+ field public static final java.lang.String ACTION_SHOW_CALL_ACCESSIBILITY_SETTINGS = "android.telecom.action.SHOW_CALL_ACCESSIBILITY_SETTINGS";
field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
field public static final java.lang.String ACTION_SHOW_RESPOND_VIA_SMS_SETTINGS = "android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS";
field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
@@ -31415,6 +31458,7 @@
public class TelephonyManager {
method public void answerRingingCall();
method public void call(java.lang.String, java.lang.String);
+ method public boolean canChangeDtmfToneLength();
method public int checkCarrierPrivilegesForPackage(java.lang.String);
method public void dial(java.lang.String);
method public boolean disableDataConnectivity();
@@ -31474,6 +31518,7 @@
method public boolean isSmsCapable();
method public boolean isVideoCallingEnabled();
method public boolean isVoiceCapable();
+ method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public boolean needsOtaServiceProvisioning();
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
diff --git a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
index a31b150..c27d0c0 100644
--- a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
+++ b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java
@@ -20,6 +20,7 @@
import android.app.IActivityManager;
import android.app.IActivityManager.ContentProviderHolder;
import android.content.IContentProvider;
+import android.database.Cursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -29,13 +30,18 @@
import android.os.UserHandle;
import android.provider.Settings;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
public final class SettingsCmd {
enum CommandVerb {
UNSPECIFIED,
GET,
PUT,
- DELETE
+ DELETE,
+ LIST,
}
static String[] mArgs;
@@ -47,7 +53,7 @@
String mValue = null;
public static void main(String[] args) {
- if (args == null || args.length < 3) {
+ if (args == null || args.length < 2) {
printUsage();
return;
}
@@ -78,6 +84,8 @@
mVerb = CommandVerb.PUT;
} else if ("delete".equalsIgnoreCase(arg)) {
mVerb = CommandVerb.DELETE;
+ } else if ("list".equalsIgnoreCase(arg)) {
+ mVerb = CommandVerb.LIST;
} else {
// invalid
System.err.println("Invalid command: " + arg);
@@ -91,6 +99,10 @@
break; // invalid
}
mTable = arg.toLowerCase();
+ if (mVerb == CommandVerb.LIST) {
+ valid = true;
+ break;
+ }
} else if (mVerb == CommandVerb.GET || mVerb == CommandVerb.DELETE) {
mKey = arg;
if (mNextArg >= mArgs.length) {
@@ -144,6 +156,11 @@
System.out.println("Deleted "
+ deleteForUser(provider, mUser, mTable, mKey) + " rows");
break;
+ case LIST:
+ for (String line : listForUser(provider, mUser, mTable)) {
+ System.out.println(line);
+ }
+ break;
default:
System.err.println("Unspecified command");
break;
@@ -164,6 +181,34 @@
}
}
+ private List<String> listForUser(IContentProvider provider, int userHandle, String table) {
+ final Uri uri = "system".equals(table) ? Settings.System.CONTENT_URI
+ : "secure".equals(table) ? Settings.Secure.CONTENT_URI
+ : "global".equals(table) ? Settings.Global.CONTENT_URI
+ : null;
+ final ArrayList<String> lines = new ArrayList<String>();
+ if (uri == null) {
+ return lines;
+ }
+ try {
+ final Cursor cursor = provider.query(resolveCallingPackage(), uri, null, null, null,
+ null, null);
+ try {
+ while (cursor != null && cursor.moveToNext()) {
+ lines.add(cursor.getString(1) + "=" + cursor.getString(2));
+ }
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ Collections.sort(lines);
+ } catch (RemoteException e) {
+ System.err.println("List failed in " + table + " for user " + userHandle);
+ }
+ return lines;
+ }
+
private String nextArg() {
if (mNextArg >= mArgs.length) {
return null;
@@ -244,6 +289,7 @@
System.err.println("usage: settings [--user NUM] get namespace key");
System.err.println(" settings [--user NUM] put namespace key value");
System.err.println(" settings [--user NUM] delete namespace key");
+ System.err.println(" settings [--user NUM] list namespace");
System.err.println("\n'namespace' is one of {system, secure, global}, case-insensitive");
System.err.println("If '--user NUM' is not given, the operations are performed on the owner user.");
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index c6ffef6..c525ef2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -309,6 +309,21 @@
/** @hide Process is being cached for later use and is empty. */
public static final int PROCESS_STATE_CACHED_EMPTY = 13;
+ /**
+ * Lock task mode is not active.
+ */
+ public static final int LOCK_TASK_MODE_NONE = 0;
+
+ /**
+ * Full lock task mode is active.
+ */
+ public static final int LOCK_TASK_MODE_LOCKED = 1;
+
+ /**
+ * App pinning mode is active.
+ */
+ public static final int LOCK_TASK_MODE_PINNED = 2;
+
Point mAppTaskThumbnailSize;
/*package*/ ActivityManager(Context context, Handler handler) {
@@ -2684,12 +2699,25 @@
* no new tasks can be created or switched to.
*
* @see Activity#startLockTask()
+ *
+ * @deprecated Use {@link #getLockTaskModeState} instead.
*/
public boolean isInLockTaskMode() {
+ return getLockTaskModeState() != LOCK_TASK_MODE_NONE;
+ }
+
+ /**
+ * Return the current state of task locking. The three possible outcomes
+ * are {@link #LOCK_TASK_MODE_NONE}, {@link #LOCK_TASK_MODE_LOCKED}
+ * and {@link #LOCK_TASK_MODE_PINNED}.
+ *
+ * @see Activity#startLockTask()
+ */
+ public int getLockTaskModeState() {
try {
- return ActivityManagerNative.getDefault().isInLockTaskMode();
+ return ActivityManagerNative.getDefault().getLockTaskModeState();
} catch (RemoteException e) {
- return false;
+ return ActivityManager.LOCK_TASK_MODE_NONE;
}
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index bb307bb..3197461 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2294,6 +2294,14 @@
return true;
}
+ case GET_LOCK_TASK_MODE_STATE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final int lockTaskModeState = getLockTaskModeState();
+ reply.writeNoException();
+ reply.writeInt(lockTaskModeState);
+ return true;
+ }
+
case SET_TASK_DESCRIPTION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -5420,6 +5428,19 @@
}
@Override
+ public int getLockTaskModeState() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(GET_LOCK_TASK_MODE_STATE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ int lockTaskModeState = reply.readInt();
+ data.recycle();
+ reply.recycle();
+ return lockTaskModeState;
+ }
+
+ @Override
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 6d455b1..2cb27b0 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -16,6 +16,8 @@
package android.app;
+import static android.app.ActivityManager.START_CANCELED;
+
import android.content.Context;
import android.content.ContextWrapper;
import android.content.IIntentSender;
@@ -23,6 +25,7 @@
import android.content.IntentSender;
import android.graphics.SurfaceTexture;
import android.os.IBinder;
+import android.os.OperationCanceledException;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -55,10 +58,6 @@
private int mLastVisibility;
private ActivityViewCallback mActivityViewCallback;
- // Only one IIntentSender or Intent may be queued at a time. Most recent one wins.
- IIntentSender mQueuedPendingIntent;
- Intent mQueuedIntent;
-
public ActivityView(Context context) {
this(context, null);
}
@@ -167,14 +166,13 @@
if (mActivityContainer == null) {
throw new IllegalStateException("Attempt to call startActivity after release");
}
+ if (mSurface == null) {
+ throw new IllegalStateException("Surface not yet created.");
+ }
if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
(isAttachedToDisplay() ? "" : "not") + " attached");
- if (mSurface != null) {
- mActivityContainer.startActivity(intent);
- } else {
- mActivityContainer.checkEmbeddedAllowed(intent);
- mQueuedIntent = intent;
- mQueuedPendingIntent = null;
+ if (mActivityContainer.startActivity(intent) == START_CANCELED) {
+ throw new OperationCanceledException();
}
}
@@ -182,15 +180,14 @@
if (mActivityContainer == null) {
throw new IllegalStateException("Attempt to call startActivity after release");
}
+ if (mSurface == null) {
+ throw new IllegalStateException("Surface not yet created.");
+ }
if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
(isAttachedToDisplay() ? "" : "not") + " attached");
final IIntentSender iIntentSender = intentSender.getTarget();
- if (mSurface != null) {
- mActivityContainer.startActivityIntentSender(iIntentSender);
- } else {
- mActivityContainer.checkEmbeddedAllowedIntentSender(iIntentSender);
- mQueuedPendingIntent = iIntentSender;
- mQueuedIntent = null;
+ if (mActivityContainer.startActivityIntentSender(iIntentSender) == START_CANCELED) {
+ throw new OperationCanceledException();
}
}
@@ -198,15 +195,14 @@
if (mActivityContainer == null) {
throw new IllegalStateException("Attempt to call startActivity after release");
}
+ if (mSurface == null) {
+ throw new IllegalStateException("Surface not yet created.");
+ }
if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
+ (isAttachedToDisplay() ? "" : "not") + " attached");
final IIntentSender iIntentSender = pendingIntent.getTarget();
- if (mSurface != null) {
- mActivityContainer.startActivityIntentSender(iIntentSender);
- } else {
- mActivityContainer.checkEmbeddedAllowedIntentSender(iIntentSender);
- mQueuedPendingIntent = iIntentSender;
- mQueuedIntent = null;
+ if (mActivityContainer.startActivityIntentSender(iIntentSender) == START_CANCELED) {
+ throw new OperationCanceledException();
}
}
@@ -243,26 +239,24 @@
mSurface = null;
throw new RuntimeException("ActivityView: Unable to create ActivityContainer. " + e);
}
-
- if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null ||
- mQueuedPendingIntent != null ? "" : "no") + " queued intent");
- if (mQueuedIntent != null) {
- mActivityContainer.startActivity(mQueuedIntent);
- mQueuedIntent = null;
- } else if (mQueuedPendingIntent != null) {
- mActivityContainer.startActivityIntentSender(mQueuedPendingIntent);
- mQueuedPendingIntent = null;
- }
}
/**
* Set the callback to use to report certain state changes.
- * @param callback The callback to report events to.
+ *
+ * Note: If the surface has been created prior to this call being made, then
+ * ActivityViewCallback.onSurfaceAvailable will be called from within setCallback.
+ *
+ * @param callback The callback to report events to.
*
* @see ActivityViewCallback
*/
public void setCallback(ActivityViewCallback callback) {
mActivityViewCallback = callback;
+
+ if (mSurface != null) {
+ mActivityViewCallback.onSurfaceAvailable(this);
+ }
}
public static abstract class ActivityViewCallback {
@@ -272,6 +266,16 @@
* have at most one callback registered.
*/
public abstract void onAllActivitiesComplete(ActivityView view);
+ /**
+ * Called when the surface is ready to be drawn to. Calling startActivity prior to this
+ * callback will result in an IllegalStateException.
+ */
+ public abstract void onSurfaceAvailable(ActivityView view);
+ /**
+ * Called when the surface has been removed. Calling startActivity after this callback
+ * will result in an IllegalStateException.
+ */
+ public abstract void onSurfaceDestroyed(ActivityView view);
}
private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
@@ -286,6 +290,9 @@
mWidth = width;
mHeight = height;
attachToSurfaceWhenReady();
+ if (mActivityViewCallback != null) {
+ mActivityViewCallback.onSurfaceAvailable(ActivityView.this);
+ }
}
@Override
@@ -311,6 +318,9 @@
throw new RuntimeException(
"ActivityView: Unable to set surface of ActivityContainer. " + e);
}
+ if (mActivityViewCallback != null) {
+ mActivityViewCallback.onSurfaceDestroyed(ActivityView.this);
+ }
return true;
}
@@ -325,7 +335,7 @@
private final WeakReference<ActivityView> mActivityViewWeakReference;
ActivityContainerCallback(ActivityView activityView) {
- mActivityViewWeakReference = new WeakReference<ActivityView>(activityView);
+ mActivityViewWeakReference = new WeakReference<>(activityView);
}
@Override
@@ -391,24 +401,6 @@
}
}
- void checkEmbeddedAllowed(Intent intent) {
- try {
- mIActivityContainer.checkEmbeddedAllowed(intent);
- } catch (RemoteException e) {
- throw new RuntimeException(
- "ActivityView: Unable to startActivity from Intent. " + e);
- }
- }
-
- void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
- try {
- mIActivityContainer.checkEmbeddedAllowedIntentSender(intentSender);
- } catch (RemoteException e) {
- throw new RuntimeException(
- "ActivityView: Unable to startActivity from IntentSender. " + e);
- }
- }
-
int getDisplayId() {
try {
return mIActivityContainer.getDisplayId();
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
index ff1175f..170aff3 100644
--- a/core/java/android/app/IActivityContainer.aidl
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -29,8 +29,6 @@
void setSurface(in Surface surface, int width, int height, int density);
int startActivity(in Intent intent);
int startActivityIntentSender(in IIntentSender intentSender);
- void checkEmbeddedAllowed(in Intent intent);
- void checkEmbeddedAllowedIntentSender(in IIntentSender intentSender);
int getDisplayId();
int getStackId();
boolean injectEvent(in InputEvent event);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index a7e9413..1277cfa 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -461,6 +461,8 @@
public boolean isInLockTaskMode() throws RemoteException;
+ public int getLockTaskModeState() throws RemoteException;
+
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
throws RemoteException;
public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException;
@@ -810,4 +812,5 @@
int SET_TASK_RESIZEABLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+283;
int REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+284;
int RESIZE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+285;
+ int GET_LOCK_TASK_MODE_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+286;
}
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 9a8dc52..fe284ce 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -168,8 +168,8 @@
/**
* Action sent to a device administrator to notify that the device is entering
- * lock task mode from an authorized package. The extra {@link #EXTRA_LOCK_TASK_PACKAGE}
- * will describe the authorized package using lock task mode.
+ * lock task mode. The extra {@link #EXTRA_LOCK_TASK_PACKAGE}
+ * will describe the package using lock task mode.
*
* <p>The calling device admin must be the device owner or profile
* owner to receive this broadcast.
@@ -182,7 +182,7 @@
/**
* Action sent to a device administrator to notify that the device is exiting
- * lock task mode from an authorized package.
+ * lock task mode.
*
* <p>The calling device admin must be the device owner or profile
* owner to receive this broadcast.
@@ -209,12 +209,14 @@
* requested provisioning. In the device owner case the profile is the primary user.
* The broadcast will also be limited to the {@link DeviceAdminReceiver} component
* specified in the original intent or NFC bump that started the provisioning process
- * (@see DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE).
+ * (see {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE
+ * DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE}).
*
* <p>A device admin application which listens to this intent can find out if the device was
* provisioned for the device owner or profile owner case by calling respectively
* {@link android.app.admin.DevicePolicyManager#isDeviceOwnerApp} and
- * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}.
+ * {@link android.app.admin.DevicePolicyManager#isProfileOwnerApp}. You will generally handle
+ * this in {@link DeviceAdminReceiver#onProfileProvisioningComplete}.
*
* <p>Input: Nothing.</p>
* <p>Output: Nothing</p>
@@ -223,6 +225,23 @@
public static final String ACTION_PROFILE_PROVISIONING_COMPLETE =
"android.app.action.PROFILE_PROVISIONING_COMPLETE";
+ /**
+ * Broadcast Action: This broadcast is sent to indicate that the system is ready for the device
+ * initializer to perform user setup tasks. This is only applicable to devices managed by a
+ * device owner app.
+ *
+ * <p>The broadcast will be limited to the {@link DeviceAdminReceiver} component specified in
+ * the (@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME) field
+ * of the original intent or NFC bump that started the provisioning process. You will generally
+ * handle this in {@link DeviceAdminReceiver#onReadyForUserInitialization}.
+ *
+ * <p>Input: Nothing.</p>
+ * <p>Output: Nothing</p>
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_READY_FOR_USER_INITIALIZATION =
+ "android.app.action.READY_FOR_USER_INITIALIZATION";
+
/** @hide */
public static final String ACTION_CHOOSE_PRIVATE_KEY_ALIAS = "android.app.action.CHOOSE_PRIVATE_KEY_ALIAS";
@@ -244,11 +263,12 @@
/** @hide */
public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE = "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE";
- /**
+ /**
* Name under which a DevicePolicy component publishes information
* about itself. This meta-data must reference an XML resource containing
- * a device-admin tag. XXX TO DO: describe syntax.
+ * a device-admin tag.
*/
+ // TO DO: describe syntax.
public static final String DEVICE_ADMIN_META_DATA = "android.app.device_admin";
private DevicePolicyManager mManager;
@@ -380,20 +400,20 @@
/**
* Called when provisioning of a managed profile or managed device has completed successfully.
*
- * <p> As a prerequisit for the execution of this callback the (@link DeviceAdminReceiver} has
+ * <p> As a prerequisite for the execution of this callback the {@link DeviceAdminReceiver} has
* to declare an intent filter for {@link #ACTION_PROFILE_PROVISIONING_COMPLETE}.
* Its component must also be specified in the {@link DevicePolicyManager#EXTRA_DEVICE_ADMIN}
* of the {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} intent that started the
* managed provisioning.
*
- * <p>When provisioning is complete, the managed profile is hidden until the profile owner
- * calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}. Typically a profile
- * owner will enable the profile when it has finished any additional setup such as adding an
- * account by using the {@link AccountManager} and calling apis to bring the profile into the
- * desired state.
+ * <p>When provisioning of a managed profile is complete, the managed profile is hidden until
+ * the profile owner calls {DevicePolicyManager#setProfileEnabled(ComponentName admin)}.
+ * Typically a profile owner will enable the profile when it has finished any additional setup
+ * such as adding an account by using the {@link AccountManager} and calling apis to bring the
+ * profile into the desired state.
*
* <p> Note that provisioning completes without waiting for any server interactions, so the
- * profile owner needs to wait for data to be available if required (e.g android device ids or
+ * profile owner needs to wait for data to be available if required (e.g. android device ids or
* other data that is set as a result of server interactions).
*
* @param context The running context as per {@link #onReceive}.
@@ -403,8 +423,31 @@
}
/**
- * Called when a device is entering lock task mode by a package authorized
- * by {@link DevicePolicyManager#isLockTaskPermitted(String)}
+ * Called during provisioning of a managed device to allow the device initializer to perform
+ * user setup steps. Only device initializers should override this method.
+ *
+ * <p> Called when the DeviceAdminReceiver receives a
+ * {@link #ACTION_READY_FOR_USER_INITIALIZATION} broadcast. As a prerequisite for the execution
+ * of this callback the {@link DeviceAdminReceiver} has
+ * to declare an intent filter for {@link #ACTION_READY_FOR_USER_INITIALIZATION}. Only the
+ * component specified in the
+ * {@link DevicePolicyManager#EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME} field of the
+ * original intent or NFC bump that started the provisioning process will receive this callback.
+ *
+ * <p>It is not assumed that the device initializer is finished when it returns from
+ * this call, as it may do additional setup asynchronously. The device initializer must call
+ * {DevicePolicyManager#setUserEnabled(ComponentName admin)} when it has finished any additional
+ * setup (such as adding an account by using the {@link AccountManager}) in order for the user
+ * to be functional.
+ *
+ * @param context The running context as per {@link #onReceive}.
+ * @param intent The received intent as per {@link #onReceive}.
+ */
+ public void onReadyForUserInitialization(Context context, Intent intent) {
+ }
+
+ /**
+ * Called when a device is entering lock task mode.
*
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
@@ -414,8 +457,7 @@
}
/**
- * Called when a device is exiting lock task mode by a package authorized
- * by {@link DevicePolicyManager#isLockTaskPermitted(String)}
+ * Called when a device is exiting lock task mode.
*
* @param context The running context as per {@link #onReceive}.
* @param intent The received intent as per {@link #onReceive}.
@@ -486,6 +528,8 @@
onLockTaskModeEntering(context, intent, pkg);
} else if (ACTION_LOCK_TASK_EXITING.equals(action)) {
onLockTaskModeExiting(context, intent);
+ } else if (ACTION_READY_FOR_USER_INITIALIZATION.equals(action)) {
+ onReadyForUserInitialization(context, intent);
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6d5b4e0..c7088599 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -28,6 +28,7 @@
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.Handler;
@@ -104,9 +105,9 @@
* device as a personal and corporate device. The user which provisioning is started from and
* the managed profile share a launcher.
*
- * <p>This intent will typically be sent by a mobile device management application (mdm).
- * Provisioning adds a managed profile and sets the mdm as the profile owner who has full
- * control over the profile
+ * <p>This intent will typically be sent by a mobile device management application (MDM).
+ * Provisioning adds a managed profile and sets the MDM as the profile owner who has full
+ * control over the profile.
*
* <p>This intent must contain the extra {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME}.
*
@@ -357,6 +358,52 @@
"android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
/**
+ * On devices managed by a device owner app, a String representation of a Component name extra
+ * indicating the component of the application that is temporarily granted device owner
+ * privileges during device initialization and profile owner privileges during secondary user
+ * initialization.
+ *
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+ * provisioning via an NFC bump.
+ * @see ComponentName#unflattenFromString()
+ */
+ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME
+ = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
+
+ /**
+ * A String extra holding an http url that specifies the download location of the device
+ * initializer package. When not provided it is assumed that the device initializer package is
+ * already installed.
+ *
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+ * provisioning via an NFC bump.
+ */
+ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION
+ = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
+
+ /**
+ * A String extra holding a http cookie header which should be used in the http request to the
+ * url specified in {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
+ *
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+ * provisioning via an NFC bump.
+ */
+ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER
+ = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
+
+ /**
+ * A String extra holding the SHA-1 checksum of the file at download location specified in
+ * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}. If this doesn't
+ * match the file at the download location an error will be shown to the user and the user will
+ * be asked to factory reset the device.
+ *
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
+ * provisioning via an NFC bump.
+ */
+ public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM
+ = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
+
+ /**
* This MIME type is used for starting the Device Owner provisioning.
*
* <p>During device owner provisioning a device admin app is set as the owner of the device.
@@ -2382,6 +2429,113 @@
}
/**
+ * Sets the given component as the device initializer. The package must already be installed and
+ * set as an active device administrator, and there must not be an existing device initializer,
+ * for this call to succeed. This method can only be called by an app holding the
+ * MANAGE_DEVICE_ADMINS permission before the device is provisioned or by a device owner app. A
+ * device initializer app is granted device owner privileges during device initialization and
+ * profile owner privileges during secondary user initialization.
+ * @param who Which {@link DeviceAdminReceiver} this request is associated with, or null if not
+ * called by the device owner.
+ * @param initializer Which {@link DeviceAdminReceiver} to make device initializer.
+ * @param initializerName The user-visible name of the device initializer.
+ * @return whether the package was successfully registered as the device initializer.
+ * @throws IllegalArgumentException if the package name is null or invalid
+ * @throws IllegalStateException if the caller is not device owner or the device has
+ * already been provisioned or a device initializer already exists.
+ */
+ public boolean setDeviceInitializer(ComponentName who, ComponentName initializer,
+ String initializerName) throws IllegalArgumentException, IllegalStateException {
+ if (mService != null) {
+ try {
+ return mService.setDeviceInitializer(who, initializer, initializerName);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to set device initializer");
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Used to determine if a particular package has been registered as the device initializer.
+ *
+ * @param packageName the package name of the app, to compare with the registered device
+ * initializer app, if any.
+ * @return whether or not the caller is registered as the device initializer app.
+ */
+ public boolean isDeviceInitializerApp(String packageName) {
+ if (mService != null) {
+ try {
+ return mService.isDeviceInitializer(packageName);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to check device initializer");
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Removes the device initializer, so that it will not be invoked on user initialization for any
+ * subsequently created users. This method can be called by either the device owner or device
+ * initializer itself. The caller must be an active administrator.
+ *
+ * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ */
+ public void clearDeviceInitializerApp(ComponentName who) {
+ if (mService != null) {
+ try {
+ mService.clearDeviceInitializer(who);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to clear device initializer");
+ }
+ }
+ }
+
+ /**
+ * @hide
+ * Gets the device initializer of the system.
+ *
+ * @return the package name of the device initializer.
+ */
+ @SystemApi
+ public String getDeviceInitializerApp() {
+ if (mService != null) {
+ try {
+ return mService.getDeviceInitializer();
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to get device initializer");
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Sets the enabled state of the user. A user should be enabled only once it is ready to
+ * be used.
+ *
+ * <p>Device initializer must call this method to mark the user as functional.
+ * Only the device initializer agent can call this.
+ *
+ * <p>When the user is enabled, if the device initializer is not also the device owner, the
+ * device initializer will no longer have elevated permissions to call methods in this class.
+ * Additionally, it will be removed as an active administrator and its
+ * {@link DeviceAdminReceiver} will be disabled.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @return whether the user is now enabled.
+ */
+ public boolean setUserEnabled(ComponentName admin) {
+ if (mService != null) {
+ try {
+ return mService.setUserEnabled(admin);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed talking with device policy service", e);
+ }
+ }
+ return false;
+ }
+
+ /**
* @hide
* @deprecated Use #ACTION_SET_PROFILE_OWNER
* Sets the given component as an active admin and registers the package as the profile
@@ -3119,8 +3273,7 @@
}
/**
- * Called by a profile or device owner to set a user restriction specified
- * by the key.
+ * Called by a profile or device owner to set a user restriction specified by the key.
* <p>
* The calling device admin must be a profile or device owner; if it is not,
* a security exception will be thrown.
@@ -3141,8 +3294,7 @@
}
/**
- * Called by a profile or device owner to clear a user restriction specified
- * by the key.
+ * Called by a profile or device owner to clear a user restriction specified by the key.
* <p>
* The calling device admin must be a profile or device owner; if it is not,
* a security exception will be thrown.
@@ -3163,7 +3315,7 @@
}
/**
- * Called by device or profile owner to hide or unhide packages. When a package is hidden it
+ * Called by profile or device owners to hide or unhide packages. When a package is hidden it
* is unavailable for use, but the data and actual package file remain.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -3185,7 +3337,7 @@
}
/**
- * Called by device or profile owner to determine if a package is hidden.
+ * Called by profile or device owners to determine if a package is hidden.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The name of the package to retrieve the hidden status of.
@@ -3203,7 +3355,7 @@
}
/**
- * Called by profile or device owner to re-enable a system app that was disabled by default
+ * Called by profile or device owners to re-enable a system app that was disabled by default
* when the user was initialized.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -3220,7 +3372,7 @@
}
/**
- * Called by profile or device owner to re-enable system apps by intent that were disabled
+ * Called by profile or device owners to re-enable system apps by intent that were disabled
* by default when the user was initialized.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
@@ -3591,4 +3743,18 @@
}
return Collections.emptyList();
}
+
+ /**
+ * Called by profile or device owners to set the current user's photo.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param icon the bitmap to set as the photo.
+ */
+ public void setUserIcon(ComponentName admin, Bitmap icon) {
+ try {
+ mService.setUserIcon(admin, icon);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not set the user icon ", re);
+ }
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 714e740..f69cf36 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
+import android.graphics.Bitmap;
import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.PersistableBundle;
@@ -199,4 +200,12 @@
boolean getAutoTimeRequired();
boolean isRemovingAdmin(in ComponentName adminReceiver, int userHandle);
+
+ boolean setUserEnabled(in ComponentName who);
+ boolean isDeviceInitializer(String packageName);
+ void clearDeviceInitializer(in ComponentName who);
+ boolean setDeviceInitializer(in ComponentName who, in ComponentName initializer, String initializerName);
+ String getDeviceInitializer();
+
+ void setUserIcon(in ComponentName admin, in Bitmap icon);
}
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
index 2bc3dd4..9aede01 100644
--- a/core/java/android/hardware/ICameraService.aidl
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -81,4 +81,6 @@
int clientUid,
// Container for an ICamera object
out BinderHolder device);
+
+ int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
}
diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/core/java/android/hardware/ICameraServiceListener.aidl
index c5484965..49278b6 100644
--- a/core/java/android/hardware/ICameraServiceListener.aidl
+++ b/core/java/android/hardware/ICameraServiceListener.aidl
@@ -23,4 +23,6 @@
* Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h
*/
void onStatusChanged(int status, int cameraId);
+
+ void onTorchStatusChanged(int status, String cameraId);
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 8af3c15..faa782a 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -27,6 +27,7 @@
import android.hardware.camera2.utils.CameraRuntimeException;
import android.hardware.camera2.utils.BinderHolder;
import android.os.IBinder;
+import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
@@ -163,6 +164,15 @@
* no looper.
*/
public void registerTorchCallback(TorchCallback callback, Handler handler) {
+ if (handler == null) {
+ Looper looper = Looper.myLooper();
+ if (looper == null) {
+ throw new IllegalArgumentException(
+ "No handler given, and current thread has no looper!");
+ }
+ handler = new Handler(looper);
+ }
+ CameraManagerGlobal.get().registerTorchCallback(callback, handler);
}
/**
@@ -174,6 +184,7 @@
* @param callback The callback to remove from the notification list
*/
public void unregisterTorchCallback(TorchCallback callback) {
+ CameraManagerGlobal.get().unregisterTorchCallback(callback);
}
/**
@@ -437,11 +448,11 @@
* However, even if turning on the torch mode is successful, the application does not have the
* exclusive ownership of the flash unit or the camera device. The torch mode will be turned
* off and becomes unavailable when the camera device that the flash unit belongs to becomes
- * unavailable ({@link CameraManager.TorchCallback#onTorchModeAvailable} will be
- * invoked) or when other camera resources to keep the torch on become unavailable (
+ * unavailable or when other camera resources to keep the torch on become unavailable (
* {@link CameraManager.TorchCallback#onTorchModeUnavailable} will be invoked). Also,
* other applications are free to call {@link #setTorchMode} to turn off the torch mode (
- * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked).
+ * {@link CameraManager.TorchCallback#onTorchModeChanged} will be invoked). If the latest
+ * application that turned on the torch mode exits, the torch mode will be turned off.
*
* @param cameraId
* The unique identifier of the camera device that the flash unit belongs to.
@@ -454,13 +465,15 @@
* {@link CameraAccessException#CAMERA_IN_USE} will be thrown if the camera device
* is in use. {@link CameraAccessException#MAX_CAMERAS_IN_USE} will be thrown if
* other camera resources needed to turn on the torch mode are in use.
+ * {@link CameraAccessException#CAMERA_DISCONNECTED} will be thrown if camera
+ * service is not available.
*
* @throws IllegalArgumentException if cameraId was null, cameraId doesn't match any currently
* or previously available camera device, or the camera device doesn't have a
* flash unit.
*/
public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
-
+ CameraManagerGlobal.get().setTorchMode(cameraId, enabled);
}
/**
@@ -508,14 +521,19 @@
}
/**
- * A callback for camera flash torch modes becoming available, unavailable, enabled, or
- * disabled.
+ * A callback for camera flash torch modes becoming unavailable, disabled, or enabled.
*
- * <p>The torch mode becomes available when the camera device it belongs to is no longer in use
- * and other camera resources it needs are no longer busy. It becomes unavailable when the
- * camera device it belongs to becomes unavailable or other camera resouces it needs become
- * busy due to other higher priority camera activities. The torch mode changes when an
- * application calls {@link #setTorchMode} successfully.
+ * <p>The torch mode becomes unavailable when the camera device it belongs to becomes
+ * unavailable or other camera resouces it needs become busy due to other higher priority
+ * camera activities. The torch mode becomes disabled when it was turned off or when the camera
+ * device it belongs to is no longer in use and other camera resources it needs are no longer
+ * busy. A camera's torch mode is turned off when an application calls {@link #setTorchMode} to
+ * turn off the camera's torch mode, or when an application turns on another camera's torch mode
+ * if keeping multiple torch modes on simultaneously is not supported. The torch mode becomes
+ * enabled when it is turned on via {@link #setTorchMode}.</p>
+ *
+ * <p>The torch mode is available to set via {@link #setTorchMode} only when it's in a disabled
+ * or enabled state.</p>
*
* <p>Extend this callback and pass an instance of the subclass to
* {@link CameraManager#registerTorchCallback} to be notified of such status changes.
@@ -525,24 +543,12 @@
*/
public static abstract class TorchCallback {
/**
- * The torch mode of a camera has become available to use.
- *
- * <p>The default implementation of this method does nothing.</p>
- *
- * @param cameraId The unique identifier of the camera whose torch mode has become
- * available.
- */
- public void onTorchModeAvailable(String cameraId) {
- // default empty implementation
- }
-
- /**
- * A previously-available torch mode of a camera has become unavailable.
+ * A camera's torch mode has become unavailable to set via {@link #setTorchMode}.
*
* <p>If torch mode was previously turned on by calling {@link #setTorchMode}, it will be
* turned off before {@link CameraManager.TorchCallback#onTorchModeUnavailable} is
- * invoked. {@link #setTorchMode} will fail until the flash unit becomes available again.
- * </p>
+ * invoked. {@link #setTorchMode} will fail until the torch mode has entered a disabled or
+ * enabled state again.</p>
*
* <p>The default implementation of this method does nothing.</p>
*
@@ -554,15 +560,17 @@
}
/**
- * Torch mode of a camera has been turned on or off through {@link #setTorchMode}.
+ * A camera's torch mode has become enabled or disabled and can be changed via
+ * {@link #setTorchMode}.
*
* <p>The default implementation of this method does nothing.</p>
*
* @param cameraId The unique identifier of the camera whose torch mode has been changed.
*
* @param enabled The state that the torch mode of the camera has been changed to.
- * {@code true} when the torch mode has been turned on. {@code false} when
- * the torch mode has been turned off.
+ * {@code true} when the torch mode has become on and available to be turned
+ * off. {@code false} when the torch mode has becomes off and available to
+ * be turned on.
*/
public void onTorchModeChanged(String cameraId, boolean enabled) {
// default empty implementation
@@ -725,6 +733,27 @@
private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
new ArrayMap<AvailabilityCallback, Handler>();
+ // Keep up-to-date with ICameraServiceListener.h
+
+ // torch mode has become not available to set via setTorchMode().
+ public static final int TORCH_STATUS_NOT_AVAILABLE = 0;
+ // torch mode is off and available to be turned on via setTorchMode().
+ public static final int TORCH_STATUS_AVAILABLE_OFF = 1;
+ // torch mode is on and available to be turned off via setTorchMode().
+ public static final int TORCH_STATUS_AVAILABLE_ON = 2;
+
+ // End enums shared with ICameraServiceListener.h
+
+ // torch client binder to set the torch mode with.
+ private Binder mTorchClientBinder = new Binder();
+
+ // Camera ID -> Torch status map
+ private final ArrayMap<String, Integer> mTorchStatus = new ArrayMap<String, Integer>();
+
+ // Registered torch callbacks and their handlers
+ private final ArrayMap<TorchCallback, Handler> mTorchCallbackMap =
+ new ArrayMap<TorchCallback, Handler>();
+
private final Object mLock = new Object();
// Access only through getCameraService to deal with binder death
@@ -810,15 +839,46 @@
}
}
+ public void setTorchMode(String cameraId, boolean enabled) throws CameraAccessException {
+ synchronized(mLock) {
+
+ if (cameraId == null) {
+ throw new IllegalArgumentException("cameraId was null");
+ }
+
+ ICameraService cameraService = getCameraService();
+ if (cameraService == null) {
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service is currently unavailable");
+ }
+
+ try {
+ int status = cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
+ } catch(CameraRuntimeException e) {
+ int problem = e.getReason();
+ switch (problem) {
+ case CameraAccessException.CAMERA_ERROR:
+ throw new IllegalArgumentException(
+ "the camera device doesn't have a flash unit.");
+ default:
+ throw e.asChecked();
+ }
+ } catch (RemoteException e) {
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service is currently unavailable");
+ }
+ }
+ }
+
private void handleRecoverableSetupErrors(CameraRuntimeException e, String msg) {
int problem = e.getReason();
switch (problem) {
- case CameraAccessException.CAMERA_DISCONNECTED:
- String errorMsg = CameraAccessException.getDefaultMessage(problem);
- Log.w(TAG, msg + ": " + errorMsg);
- break;
- default:
- throw new IllegalStateException(msg, e.asChecked());
+ case CameraAccessException.CAMERA_DISCONNECTED:
+ String errorMsg = CameraAccessException.getDefaultMessage(problem);
+ Log.w(TAG, msg + ": " + errorMsg);
+ break;
+ default:
+ throw new IllegalStateException(msg, e.asChecked());
}
}
@@ -843,6 +903,17 @@
}
}
+ private boolean validTorchStatus(int status) {
+ switch (status) {
+ case TORCH_STATUS_NOT_AVAILABLE:
+ case TORCH_STATUS_AVAILABLE_ON:
+ case TORCH_STATUS_AVAILABLE_OFF:
+ return true;
+ default:
+ return false;
+ }
+ }
+
private void postSingleUpdate(final AvailabilityCallback callback, final Handler handler,
final String id, final int status) {
if (isAvailable(status)) {
@@ -864,6 +935,32 @@
}
}
+ private void postSingleTorchUpdate(final TorchCallback callback, final Handler handler,
+ final String id, final int status) {
+ switch(status) {
+ case TORCH_STATUS_AVAILABLE_ON:
+ case TORCH_STATUS_AVAILABLE_OFF:
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onTorchModeChanged(id, status ==
+ TORCH_STATUS_AVAILABLE_ON);
+ }
+ });
+ break;
+ default:
+ handler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ callback.onTorchModeUnavailable(id);
+ }
+ });
+ break;
+ }
+ }
+
/**
* Send the state of all known cameras to the provided listener, to initialize
* the listener's knowledge of camera state.
@@ -933,6 +1030,44 @@
}
} // onStatusChangedLocked
+ private void updateTorchCallbackLocked(TorchCallback callback, Handler handler) {
+ for (int i = 0; i < mTorchStatus.size(); i++) {
+ String id = mTorchStatus.keyAt(i);
+ Integer status = mTorchStatus.valueAt(i);
+ postSingleTorchUpdate(callback, handler, id, status);
+ }
+ }
+
+ private void onTorchStatusChangedLocked(int status, String id) {
+ if (DEBUG) {
+ Log.v(TAG,
+ String.format("Camera id %s has torch status changed to 0x%x", id, status));
+ }
+
+ if (!validTorchStatus(status)) {
+ Log.e(TAG, String.format("Ignoring invalid device %s torch status 0x%x", id,
+ status));
+ return;
+ }
+
+ Integer oldStatus = mTorchStatus.put(id, status);
+ if (oldStatus != null && oldStatus == status) {
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Torch status changed to 0x%x, which is what it already was",
+ status));
+ }
+ return;
+ }
+
+ final int callbackCount = mTorchCallbackMap.size();
+ for (int i = 0; i < callbackCount; i++) {
+ final Handler handler = mTorchCallbackMap.valueAt(i);
+ final TorchCallback callback = mTorchCallbackMap.keyAt(i);
+ postSingleTorchUpdate(callback, handler, id, status);
+ }
+ } // onTorchStatusChangedLocked
+
/**
* Register a callback to be notified about camera device availability with the
* global listener singleton.
@@ -962,6 +1097,22 @@
}
}
+ public void registerTorchCallback(TorchCallback callback, Handler handler) {
+ synchronized(mLock) {
+ Handler oldHandler = mTorchCallbackMap.put(callback, handler);
+ // For new callbacks, provide initial torch information
+ if (oldHandler == null) {
+ updateTorchCallbackLocked(callback, handler);
+ }
+ }
+ }
+
+ public void unregisterTorchCallback(TorchCallback callback) {
+ synchronized(mLock) {
+ mTorchCallbackMap.remove(callback);
+ }
+ }
+
/**
* Callback from camera service notifying the process about camera availability changes
*/
@@ -972,6 +1123,13 @@
}
}
+ @Override
+ public void onTorchStatusChanged(int status, String cameraId) throws RemoteException {
+ synchronized (mLock) {
+ onTorchStatusChangedLocked(status, cameraId);
+ }
+ }
+
/**
* Listener for camera service death.
*
@@ -986,9 +1144,9 @@
mCameraService = null;
- // Tell listeners that the cameras are _available_, because any existing clients
- // will have gotten disconnected. This is optimistic under the assumption that
- // the service will be back shortly.
+ // Tell listeners that the cameras and torch modes are _available_, because any
+ // existing clients will have gotten disconnected. This is optimistic under the
+ // assumption that the service will be back shortly.
//
// Without this, a camera service crash while a camera is open will never signal
// to listeners that previously in-use cameras are now available.
@@ -996,6 +1154,11 @@
String cameraId = mDeviceStatus.keyAt(i);
onStatusChangedLocked(STATUS_PRESENT, cameraId);
}
+ for (int i = 0; i < mTorchStatus.size(); i++) {
+ String cameraId = mTorchStatus.keyAt(i);
+ onTorchStatusChangedLocked(TORCH_STATUS_AVAILABLE_OFF, cameraId);
+ }
+
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4dadda2..0fee4b3 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -30,6 +30,7 @@
import android.telephony.SignalStrength;
import android.text.format.DateFormat;
import android.util.Printer;
+import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
@@ -542,6 +543,297 @@
}
}
+ public static final class LevelStepTracker {
+ public long mLastStepTime = -1;
+ public int mNumStepDurations;
+ public final long[] mStepDurations;
+
+ public LevelStepTracker(int maxLevelSteps) {
+ mStepDurations = new long[maxLevelSteps];
+ }
+
+ public LevelStepTracker(int numSteps, long[] steps) {
+ mNumStepDurations = numSteps;
+ mStepDurations = new long[numSteps];
+ System.arraycopy(steps, 0, mStepDurations, 0, numSteps);
+ }
+
+ public long getDurationAt(int index) {
+ return mStepDurations[index] & STEP_LEVEL_TIME_MASK;
+ }
+
+ public int getLevelAt(int index) {
+ return (int)((mStepDurations[index] & STEP_LEVEL_LEVEL_MASK)
+ >> STEP_LEVEL_LEVEL_SHIFT);
+ }
+
+ public int getInitModeAt(int index) {
+ return (int)((mStepDurations[index] & STEP_LEVEL_INITIAL_MODE_MASK)
+ >> STEP_LEVEL_INITIAL_MODE_SHIFT);
+ }
+
+ public int getModModeAt(int index) {
+ return (int)((mStepDurations[index] & STEP_LEVEL_MODIFIED_MODE_MASK)
+ >> STEP_LEVEL_MODIFIED_MODE_SHIFT);
+ }
+
+ private void appendHex(long val, int topOffset, StringBuilder out) {
+ boolean hasData = false;
+ while (topOffset >= 0) {
+ int digit = (int)( (val>>topOffset) & 0xf );
+ topOffset -= 4;
+ if (!hasData && digit == 0) {
+ continue;
+ }
+ hasData = true;
+ if (digit >= 0 && digit <= 9) {
+ out.append((char)('0' + digit));
+ } else {
+ out.append((char)('a' + digit - 10));
+ }
+ }
+ }
+
+ public void encodeEntryAt(int index, StringBuilder out) {
+ long item = mStepDurations[index];
+ long duration = item & STEP_LEVEL_TIME_MASK;
+ int level = (int)((item & STEP_LEVEL_LEVEL_MASK)
+ >> STEP_LEVEL_LEVEL_SHIFT);
+ int initMode = (int)((item & STEP_LEVEL_INITIAL_MODE_MASK)
+ >> STEP_LEVEL_INITIAL_MODE_SHIFT);
+ int modMode = (int)((item & STEP_LEVEL_MODIFIED_MODE_MASK)
+ >> STEP_LEVEL_MODIFIED_MODE_SHIFT);
+ switch ((initMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
+ case Display.STATE_OFF: out.append('f'); break;
+ case Display.STATE_ON: out.append('o'); break;
+ case Display.STATE_DOZE: out.append('d'); break;
+ case Display.STATE_DOZE_SUSPEND: out.append('z'); break;
+ }
+ if ((initMode&STEP_LEVEL_MODE_POWER_SAVE) != 0) {
+ out.append('p');
+ }
+ switch ((modMode&STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
+ case Display.STATE_OFF: out.append('F'); break;
+ case Display.STATE_ON: out.append('O'); break;
+ case Display.STATE_DOZE: out.append('D'); break;
+ case Display.STATE_DOZE_SUSPEND: out.append('Z'); break;
+ }
+ if ((modMode&STEP_LEVEL_MODE_POWER_SAVE) != 0) {
+ out.append('P');
+ }
+ out.append('-');
+ appendHex(level, 4, out);
+ out.append('-');
+ appendHex(duration, STEP_LEVEL_LEVEL_SHIFT-4, out);
+ }
+
+ public void decodeEntryAt(int index, String value) {
+ final int N = value.length();
+ int i = 0;
+ char c;
+ long out = 0;
+ while (i < N && (c=value.charAt(i)) != '-') {
+ i++;
+ switch (c) {
+ case 'f': out |= (((long)Display.STATE_OFF-1)<<STEP_LEVEL_INITIAL_MODE_SHIFT);
+ break;
+ case 'o': out |= (((long)Display.STATE_ON-1)<<STEP_LEVEL_INITIAL_MODE_SHIFT);
+ break;
+ case 'd': out |= (((long)Display.STATE_DOZE-1)<<STEP_LEVEL_INITIAL_MODE_SHIFT);
+ break;
+ case 'z': out |= (((long)Display.STATE_DOZE_SUSPEND-1)
+ << STEP_LEVEL_INITIAL_MODE_SHIFT);
+ break;
+ case 'p': out |= (((long)STEP_LEVEL_MODE_POWER_SAVE)
+ << STEP_LEVEL_INITIAL_MODE_SHIFT);
+ break;
+ case 'F': out |= (((long)Display.STATE_OFF-1)<<STEP_LEVEL_MODIFIED_MODE_SHIFT);
+ break;
+ case 'O': out |= (((long)Display.STATE_ON-1)<<STEP_LEVEL_MODIFIED_MODE_SHIFT);
+ break;
+ case 'D': out |= (((long)Display.STATE_DOZE-1)<<STEP_LEVEL_MODIFIED_MODE_SHIFT);
+ break;
+ case 'Z': out |= (((long)Display.STATE_DOZE_SUSPEND-1)
+ << STEP_LEVEL_MODIFIED_MODE_SHIFT);
+ break;
+ case 'P': out |= (((long)STEP_LEVEL_MODE_POWER_SAVE)
+ << STEP_LEVEL_MODIFIED_MODE_SHIFT);
+ break;
+ }
+ }
+ i++;
+ long level = 0;
+ while (i < N && (c=value.charAt(i)) != '-') {
+ i++;
+ level <<= 4;
+ if (c >= '0' && c <= '9') {
+ level += c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ level += c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ level += c - 'A' + 10;
+ }
+ }
+ i++;
+ out |= (level << STEP_LEVEL_LEVEL_SHIFT) & STEP_LEVEL_LEVEL_MASK;
+ long duration = 0;
+ while (i < N && (c=value.charAt(i)) != '-') {
+ i++;
+ duration <<= 4;
+ if (c >= '0' && c <= '9') {
+ duration += c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ duration += c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ duration += c - 'A' + 10;
+ }
+ }
+ mStepDurations[index] = out | (duration & STEP_LEVEL_TIME_MASK);
+ }
+
+ public void init() {
+ mLastStepTime = -1;
+ mNumStepDurations = 0;
+ }
+
+ public void clearTime() {
+ mLastStepTime = -1;
+ }
+
+ public long computeTimePerLevel() {
+ final long[] steps = mStepDurations;
+ final int numSteps = mNumStepDurations;
+
+ // For now we'll do a simple average across all steps.
+ if (numSteps <= 0) {
+ return -1;
+ }
+ long total = 0;
+ for (int i=0; i<numSteps; i++) {
+ total += steps[i] & STEP_LEVEL_TIME_MASK;
+ }
+ return total / numSteps;
+ /*
+ long[] buckets = new long[numSteps];
+ int numBuckets = 0;
+ int numToAverage = 4;
+ int i = 0;
+ while (i < numSteps) {
+ long totalTime = 0;
+ int num = 0;
+ for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
+ totalTime += steps[i+j] & STEP_LEVEL_TIME_MASK;
+ num++;
+ }
+ buckets[numBuckets] = totalTime / num;
+ numBuckets++;
+ numToAverage *= 2;
+ i += num;
+ }
+ if (numBuckets < 1) {
+ return -1;
+ }
+ long averageTime = buckets[numBuckets-1];
+ for (i=numBuckets-2; i>=0; i--) {
+ averageTime = (averageTime + buckets[i]) / 2;
+ }
+ return averageTime;
+ */
+ }
+
+ public long computeTimeEstimate(long modesOfInterest, long modeValues,
+ int[] outNumOfInterest) {
+ final long[] steps = mStepDurations;
+ final int count = mNumStepDurations;
+ if (count <= 0) {
+ return -1;
+ }
+ long total = 0;
+ int numOfInterest = 0;
+ for (int i=0; i<count; i++) {
+ long initMode = (steps[i] & STEP_LEVEL_INITIAL_MODE_MASK)
+ >> STEP_LEVEL_INITIAL_MODE_SHIFT;
+ long modMode = (steps[i] & STEP_LEVEL_MODIFIED_MODE_MASK)
+ >> STEP_LEVEL_MODIFIED_MODE_SHIFT;
+ // If the modes of interest didn't change during this step period...
+ if ((modMode&modesOfInterest) == 0) {
+ // And the mode values during this period match those we are measuring...
+ if ((initMode&modesOfInterest) == modeValues) {
+ // Then this can be used to estimate the total time!
+ numOfInterest++;
+ total += steps[i] & STEP_LEVEL_TIME_MASK;
+ }
+ }
+ }
+ if (numOfInterest <= 0) {
+ return -1;
+ }
+
+ if (outNumOfInterest != null) {
+ outNumOfInterest[0] = numOfInterest;
+ }
+
+ // The estimated time is the average time we spend in each level, multipled
+ // by 100 -- the total number of battery levels
+ return (total / numOfInterest) * 100;
+ }
+
+ public void addLevelSteps(int numStepLevels, long modeBits, long elapsedRealtime) {
+ int stepCount = mNumStepDurations;
+ final long lastStepTime = mLastStepTime;
+ if (lastStepTime >= 0 && numStepLevels > 0) {
+ final long[] steps = mStepDurations;
+ long duration = elapsedRealtime - lastStepTime;
+ for (int i=0; i<numStepLevels; i++) {
+ System.arraycopy(steps, 0, steps, 1, steps.length-1);
+ long thisDuration = duration / (numStepLevels-i);
+ duration -= thisDuration;
+ if (thisDuration > STEP_LEVEL_TIME_MASK) {
+ thisDuration = STEP_LEVEL_TIME_MASK;
+ }
+ steps[0] = thisDuration | modeBits;
+ }
+ stepCount += numStepLevels;
+ if (stepCount > steps.length) {
+ stepCount = steps.length;
+ }
+ }
+ mNumStepDurations = stepCount;
+ mLastStepTime = elapsedRealtime;
+ }
+
+ public void readFromParcel(Parcel in) {
+ final int N = in.readInt();
+ mNumStepDurations = N;
+ for (int i=0; i<N; i++) {
+ mStepDurations[i] = in.readLong();
+ }
+ }
+
+ public void writeToParcel(Parcel out) {
+ final int N = mNumStepDurations;
+ out.writeInt(N);
+ for (int i=0; i<N; i++) {
+ out.writeLong(mStepDurations[i]);
+ }
+ }
+ }
+
+ public static final class DailyItem {
+ public long mStartTime;
+ public long mEndTime;
+ public LevelStepTracker mDischargeSteps;
+ public LevelStepTracker mChargeSteps;
+ }
+
+ public abstract DailyItem getDailyItemLocked(int daysAgo);
+
+ public abstract long getCurrentDailyStartTime();
+
+ public abstract long getNextMinDailyDeadline();
+
+ public abstract long getNextMaxDailyDeadline();
+
public final static class HistoryTag {
public String string;
public int uid;
@@ -1724,15 +2016,15 @@
// Bits in a step duration that are the new battery level we are at.
public static final long STEP_LEVEL_LEVEL_MASK = 0x0000ff0000000000L;
- public static final long STEP_LEVEL_LEVEL_SHIFT = 40;
+ public static final int STEP_LEVEL_LEVEL_SHIFT = 40;
// Bits in a step duration that are the initial mode we were in at that step.
public static final long STEP_LEVEL_INITIAL_MODE_MASK = 0x00ff000000000000L;
- public static final long STEP_LEVEL_INITIAL_MODE_SHIFT = 48;
+ public static final int STEP_LEVEL_INITIAL_MODE_SHIFT = 48;
// Bits in a step duration that indicate which modes changed during that step.
public static final long STEP_LEVEL_MODIFIED_MODE_MASK = 0xff00000000000000L;
- public static final long STEP_LEVEL_MODIFIED_MODE_SHIFT = 56;
+ public static final int STEP_LEVEL_MODIFIED_MODE_SHIFT = 56;
// Step duration mode: the screen is on, off, dozed, etc; value is Display.STATE_* - 1.
public static final int STEP_LEVEL_MODE_SCREEN_STATE = 0x03;
@@ -1740,17 +2032,56 @@
// Step duration mode: power save is on.
public static final int STEP_LEVEL_MODE_POWER_SAVE = 0x04;
- /**
- * Return the historical number of discharge steps we currently have.
- */
- public abstract int getNumDischargeStepDurations();
+ public static final int[] STEP_LEVEL_MODES_OF_INTEREST = new int[] {
+ STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+ STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+ STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+ STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+ STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+ STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+ STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+ STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
+ };
+ public static final int[] STEP_LEVEL_MODE_VALUES = new int[] {
+ (Display.STATE_OFF-1),
+ (Display.STATE_OFF-1)|STEP_LEVEL_MODE_POWER_SAVE,
+ (Display.STATE_ON-1),
+ (Display.STATE_ON-1)|STEP_LEVEL_MODE_POWER_SAVE,
+ (Display.STATE_DOZE-1),
+ (Display.STATE_DOZE-1)|STEP_LEVEL_MODE_POWER_SAVE,
+ (Display.STATE_DOZE_SUSPEND-1),
+ (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_POWER_SAVE,
+ };
+ public static final String[] STEP_LEVEL_MODE_LABELS = new String[] {
+ "screen off",
+ "screen off power save",
+ "screen on",
+ "screen on power save",
+ "screen doze",
+ "screen doze power save",
+ "screen doze-suspend",
+ "screen doze-suspend power save",
+ };
+ public static final String[] STEP_LEVEL_MODE_TAGS = new String[] {
+ "off",
+ "off-save",
+ "on",
+ "on-save",
+ "doze",
+ "doze-save",
+ "susp",
+ "susp-save",
+ };
/**
- * Return the array of discharge step durations; the number of valid
- * items in it is returned by {@link #getNumDischargeStepDurations()}.
- * These values are in milliseconds.
+ * Return the array of discharge step durations.
*/
- public abstract long[] getDischargeStepDurationsArray();
+ public abstract LevelStepTracker getDischargeLevelStepTracker();
+
+ /**
+ * Return the array of daily discharge step durations.
+ */
+ public abstract LevelStepTracker getDailyDischargeLevelStepTracker();
/**
* Compute an approximation for how much time (in microseconds) remains until the battery
@@ -1763,16 +2094,14 @@
public abstract long computeChargeTimeRemaining(long curTime);
/**
- * Return the historical number of charge steps we currently have.
+ * Return the array of charge step durations.
*/
- public abstract int getNumChargeStepDurations();
+ public abstract LevelStepTracker getChargeLevelStepTracker();
/**
- * Return the array of charge step durations; the number of valid
- * items in it is returned by {@link #getNumChargeStepDurations()}.
- * These values are in milliseconds.
+ * Return the array of daily charge step durations.
*/
- public abstract long[] getChargeStepDurationsArray();
+ public abstract LevelStepTracker getDailyChargeLevelStepTracker();
public abstract Map<String, ? extends Timer> getWakeupReasonStats();
@@ -3913,47 +4242,27 @@
pw.print(suffix);
}
- private static boolean dumpTimeEstimate(PrintWriter pw, String label, long[] steps,
- int count, long modesOfInterest, long modeValues) {
- if (count <= 0) {
+ private static boolean dumpTimeEstimate(PrintWriter pw, String label1, String label2,
+ String label3, long estimatedTime) {
+ if (estimatedTime < 0) {
return false;
}
- long total = 0;
- int numOfInterest = 0;
- for (int i=0; i<count; i++) {
- long initMode = (steps[i] & STEP_LEVEL_INITIAL_MODE_MASK)
- >> STEP_LEVEL_INITIAL_MODE_SHIFT;
- long modMode = (steps[i] & STEP_LEVEL_MODIFIED_MODE_MASK)
- >> STEP_LEVEL_MODIFIED_MODE_SHIFT;
- // If the modes of interest didn't change during this step period...
- if ((modMode&modesOfInterest) == 0) {
- // And the mode values during this period match those we are measuring...
- if ((initMode&modesOfInterest) == modeValues) {
- // Then this can be used to estimate the total time!
- numOfInterest++;
- total += steps[i] & STEP_LEVEL_TIME_MASK;
- }
- }
- }
- if (numOfInterest <= 0) {
- return false;
- }
-
- // The estimated time is the average time we spend in each level, multipled
- // by 100 -- the total number of battery levels
- long estimatedTime = (total / numOfInterest) * 100;
-
- pw.print(label);
+ pw.print(label1);
+ pw.print(label2);
+ pw.print(label3);
StringBuilder sb = new StringBuilder(64);
formatTimeMs(sb, estimatedTime);
pw.print(sb);
pw.println();
-
return true;
}
- private static boolean dumpDurationSteps(PrintWriter pw, String header, long[] steps,
- int count, boolean checkin) {
+ private static boolean dumpDurationSteps(PrintWriter pw, String prefix, String header,
+ LevelStepTracker steps, boolean checkin) {
+ if (steps == null) {
+ return false;
+ }
+ int count = steps.mNumStepDurations;
if (count <= 0) {
return false;
}
@@ -3962,13 +4271,10 @@
}
String[] lineArgs = new String[4];
for (int i=0; i<count; i++) {
- long duration = steps[i] & STEP_LEVEL_TIME_MASK;
- int level = (int)((steps[i] & STEP_LEVEL_LEVEL_MASK)
- >> STEP_LEVEL_LEVEL_SHIFT);
- long initMode = (steps[i] & STEP_LEVEL_INITIAL_MODE_MASK)
- >> STEP_LEVEL_INITIAL_MODE_SHIFT;
- long modMode = (steps[i] & STEP_LEVEL_MODIFIED_MODE_MASK)
- >> STEP_LEVEL_MODIFIED_MODE_SHIFT;
+ long duration = steps.getDurationAt(i);
+ int level = steps.getLevelAt(i);
+ long initMode = steps.getInitModeAt(i);
+ long modMode = steps.getModModeAt(i);
if (checkin) {
lineArgs[0] = Long.toString(duration);
lineArgs[1] = Integer.toString(level);
@@ -3990,7 +4296,8 @@
}
dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
} else {
- pw.print(" #"); pw.print(i); pw.print(": ");
+ pw.print(prefix);
+ pw.print("#"); pw.print(i); pw.print(": ");
TimeUtils.formatDuration(duration, pw);
pw.print(" to "); pw.print(level);
boolean haveModes = false;
@@ -4022,10 +4329,11 @@
public static final int DUMP_UNPLUGGED_ONLY = 1<<0;
public static final int DUMP_CHARGED_ONLY = 1<<1;
- public static final int DUMP_HISTORY_ONLY = 1<<2;
- public static final int DUMP_INCLUDE_HISTORY = 1<<3;
- public static final int DUMP_VERBOSE = 1<<4;
- public static final int DUMP_DEVICE_WIFI_ONLY = 1<<5;
+ public static final int DUMP_DAILY_ONLY = 1<<2;
+ public static final int DUMP_HISTORY_ONLY = 1<<3;
+ public static final int DUMP_INCLUDE_HISTORY = 1<<4;
+ public static final int DUMP_VERBOSE = 1<<5;
+ public static final int DUMP_DEVICE_WIFI_ONLY = 1<<6;
private void dumpHistoryLocked(PrintWriter pw, int flags, long histStart, boolean checkin) {
final HistoryPrinter hprinter = new HistoryPrinter();
@@ -4111,6 +4419,36 @@
}
}
+ private void dumpDailyLevelStepSummary(PrintWriter pw, String prefix, String label,
+ LevelStepTracker steps, StringBuilder tmpSb, int[] tmpOutInt) {
+ if (steps == null) {
+ return;
+ }
+ long timeRemaining = steps.computeTimeEstimate(0, 0, tmpOutInt);
+ if (timeRemaining >= 0) {
+ pw.print(prefix); pw.print(label); pw.print(" total time: ");
+ tmpSb.setLength(0);
+ formatTimeMs(tmpSb, timeRemaining);
+ pw.print(tmpSb);
+ pw.print(" (from "); pw.print(tmpOutInt[0]);
+ pw.println(" steps)");
+ }
+ for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
+ long estimatedTime = steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
+ STEP_LEVEL_MODE_VALUES[i], tmpOutInt);
+ if (estimatedTime > 0) {
+ pw.print(prefix); pw.print(label); pw.print(" ");
+ pw.print(STEP_LEVEL_MODE_LABELS[i]);
+ pw.print(" time: ");
+ tmpSb.setLength(0);
+ formatTimeMs(tmpSb, estimatedTime);
+ pw.print(tmpSb);
+ pw.print(" (from "); pw.print(tmpOutInt[0]);
+ pw.println(" steps)");
+ }
+ }
+ }
+
/**
* Dumps a human-readable summary of the battery statistics to the given PrintWriter.
*
@@ -4120,8 +4458,8 @@
public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
prepareForDumpLocked();
- final boolean filtering =
- (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
+ final boolean filtering = (flags
+ & (DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
if ((flags&DUMP_HISTORY_ONLY) != 0 || !filtering) {
final long historyTotalSize = getHistoryTotalSize();
@@ -4165,7 +4503,7 @@
}
}
- if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
+ if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
return;
}
@@ -4199,50 +4537,24 @@
}
if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
- if (dumpDurationSteps(pw, "Discharge step durations:", getDischargeStepDurationsArray(),
- getNumDischargeStepDurations(), false)) {
+ if (dumpDurationSteps(pw, " ", "Discharge step durations:",
+ getDischargeLevelStepTracker(), false)) {
long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
if (timeRemaining >= 0) {
pw.print(" Estimated discharge time remaining: ");
TimeUtils.formatDuration(timeRemaining / 1000, pw);
pw.println();
}
- dumpTimeEstimate(pw, " Estimated screen off time: ",
- getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
- STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
- (Display.STATE_OFF-1));
- dumpTimeEstimate(pw, " Estimated screen off power save time: ",
- getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
- STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
- (Display.STATE_OFF-1)|STEP_LEVEL_MODE_POWER_SAVE);
- dumpTimeEstimate(pw, " Estimated screen on time: ",
- getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
- STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
- (Display.STATE_ON-1));
- dumpTimeEstimate(pw, " Estimated screen on power save time: ",
- getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
- STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
- (Display.STATE_ON-1)|STEP_LEVEL_MODE_POWER_SAVE);
- dumpTimeEstimate(pw, " Estimated screen doze time: ",
- getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
- STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
- (Display.STATE_DOZE-1));
- dumpTimeEstimate(pw, " Estimated screen doze power save time: ",
- getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
- STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
- (Display.STATE_DOZE-1)|STEP_LEVEL_MODE_POWER_SAVE);
- dumpTimeEstimate(pw, " Estimated screen doze suspend time: ",
- getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
- STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
- (Display.STATE_DOZE_SUSPEND-1));
- dumpTimeEstimate(pw, " Estimated screen doze suspend power save time: ",
- getDischargeStepDurationsArray(), getNumDischargeStepDurations(),
- STEP_LEVEL_MODE_SCREEN_STATE|STEP_LEVEL_MODE_POWER_SAVE,
- (Display.STATE_DOZE_SUSPEND-1)|STEP_LEVEL_MODE_POWER_SAVE);
+ final LevelStepTracker steps = getDischargeLevelStepTracker();
+ for (int i=0; i< STEP_LEVEL_MODES_OF_INTEREST.length; i++) {
+ dumpTimeEstimate(pw, " Estimated ", STEP_LEVEL_MODE_LABELS[i], " time: ",
+ steps.computeTimeEstimate(STEP_LEVEL_MODES_OF_INTEREST[i],
+ STEP_LEVEL_MODE_VALUES[i], null));
+ }
pw.println();
}
- if (dumpDurationSteps(pw, "Charge step durations:", getChargeStepDurationsArray(),
- getNumChargeStepDurations(), false)) {
+ if (dumpDurationSteps(pw, " ", "Charge step durations:",
+ getChargeLevelStepTracker(), false)) {
long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
if (timeRemaining >= 0) {
pw.print(" Estimated charge time remaining: ");
@@ -4251,6 +4563,75 @@
}
pw.println();
}
+ }
+ if (!filtering || (flags&(DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0) {
+ pw.println("Daily stats:");
+ pw.print(" Current start time: ");
+ pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+ getCurrentDailyStartTime()).toString());
+ pw.print(" Next min deadline: ");
+ pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+ getNextMinDailyDeadline()).toString());
+ pw.print(" Next max deadline: ");
+ pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+ getNextMaxDailyDeadline()).toString());
+ StringBuilder sb = new StringBuilder(64);
+ int[] outInt = new int[1];
+ LevelStepTracker dsteps = getDailyDischargeLevelStepTracker();
+ LevelStepTracker csteps = getDailyChargeLevelStepTracker();
+ if (dsteps.mNumStepDurations > 0 || csteps.mNumStepDurations > 0) {
+ if ((flags&DUMP_DAILY_ONLY) != 0) {
+ if (dumpDurationSteps(pw, " ", " Current daily discharge step durations:",
+ dsteps, false)) {
+ dumpDailyLevelStepSummary(pw, " ", "Discharge", dsteps,
+ sb, outInt);
+ }
+ if (dumpDurationSteps(pw, " ", " Current daily charge step durations:",
+ csteps, false)) {
+ dumpDailyLevelStepSummary(pw, " ", "Charge", csteps,
+ sb, outInt);
+ }
+ } else {
+ pw.println(" Current daily steps:");
+ dumpDailyLevelStepSummary(pw, " ", "Discharge", dsteps,
+ sb, outInt);
+ dumpDailyLevelStepSummary(pw, " ", "Charge", csteps,
+ sb, outInt);
+ }
+ }
+ DailyItem dit;
+ int curIndex = 0;
+ while ((dit=getDailyItemLocked(curIndex)) != null) {
+ curIndex++;
+ if ((flags&DUMP_DAILY_ONLY) != 0) {
+ pw.println();
+ }
+ pw.print(" Daily from ");
+ pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mStartTime).toString());
+ pw.print(" to ");
+ pw.print(DateFormat.format("yyyy-MM-dd-HH-mm-ss", dit.mEndTime).toString());
+ pw.println(":");
+ if ((flags&DUMP_DAILY_ONLY) != 0) {
+ if (dumpDurationSteps(pw, " ",
+ " Discharge step durations:", dit.mDischargeSteps, false)) {
+ dumpDailyLevelStepSummary(pw, " ", "Discharge", dit.mDischargeSteps,
+ sb, outInt);
+ }
+ if (dumpDurationSteps(pw, " ",
+ " Charge step durations:", dit.mChargeSteps, false)) {
+ dumpDailyLevelStepSummary(pw, " ", "Charge", dit.mChargeSteps,
+ sb, outInt);
+ }
+ } else {
+ dumpDailyLevelStepSummary(pw, " ", "Discharge", dit.mDischargeSteps,
+ sb, outInt);
+ dumpDailyLevelStepSummary(pw, " ", "Charge", dit.mChargeSteps,
+ sb, outInt);
+ }
+ }
+ pw.println();
+ }
+ if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
pw.println("Statistics since last charge:");
pw.println(" System starts: " + getStartCount()
+ ", currently on battery: " + getIsOnBattery());
@@ -4275,8 +4656,8 @@
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
- final boolean filtering =
- (flags&(DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) != 0;
+ final boolean filtering = (flags &
+ (DUMP_HISTORY_ONLY|DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) != 0;
if ((flags&DUMP_INCLUDE_HISTORY) != 0 || (flags&DUMP_HISTORY_ONLY) != 0) {
if (startIteratingHistoryLocked()) {
@@ -4302,7 +4683,7 @@
}
}
- if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY)) == 0) {
+ if (filtering && (flags&(DUMP_UNPLUGGED_ONLY|DUMP_CHARGED_ONLY|DUMP_DAILY_ONLY)) == 0) {
return;
}
@@ -4334,8 +4715,7 @@
}
}
if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
- dumpDurationSteps(pw, DISCHARGE_STEP_DATA, getDischargeStepDurationsArray(),
- getNumDischargeStepDurations(), true);
+ dumpDurationSteps(pw, "", DISCHARGE_STEP_DATA, getDischargeLevelStepTracker(), true);
String[] lineArgs = new String[1];
long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
if (timeRemaining >= 0) {
@@ -4343,8 +4723,7 @@
dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
(Object[])lineArgs);
}
- dumpDurationSteps(pw, CHARGE_STEP_DATA, getChargeStepDurationsArray(),
- getNumChargeStepDurations(), true);
+ dumpDurationSteps(pw, "", CHARGE_STEP_DATA, getChargeLevelStepTracker(), true);
timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
if (timeRemaining >= 0) {
lineArgs[0] = Long.toString(timeRemaining);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 9cc12b5..cc7783f 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1010,7 +1010,8 @@
/**
* Types of data used to produce the display name for a contact. In the order
* of increasing priority: {@link #EMAIL}, {@link #PHONE},
- * {@link #ORGANIZATION}, {@link #NICKNAME}, {@link #STRUCTURED_NAME}.
+ * {@link #ORGANIZATION}, {@link #NICKNAME}, {@link #STRUCTURED_PHONETIC_NAME},
+ * {@link #STRUCTURED_NAME}.
*/
public interface DisplayNameSources {
public static final int UNDEFINED = 0;
@@ -1018,6 +1019,8 @@
public static final int PHONE = 20;
public static final int ORGANIZATION = 30;
public static final int NICKNAME = 35;
+ /** Display name comes from a structured name that only has phonetic components. */
+ public static final int STRUCTURED_PHONETIC_NAME = 37;
public static final int STRUCTURED_NAME = 40;
}
diff --git a/media/java/android/media/midi/IMidiListener.aidl b/core/java/android/service/chooser/ChooserTarget.aidl
similarity index 66%
copy from media/java/android/media/midi/IMidiListener.aidl
copy to core/java/android/service/chooser/ChooserTarget.aidl
index a4129e9..ca91bc8 100644
--- a/media/java/android/media/midi/IMidiListener.aidl
+++ b/core/java/android/service/chooser/ChooserTarget.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open 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,13 +14,6 @@
* limitations under the License.
*/
-package android.media.midi;
+package android.service.chooser;
-import android.media.midi.MidiDeviceInfo;
-
-/** @hide */
-oneway interface IMidiListener
-{
- void onDeviceAdded(in MidiDeviceInfo device);
- void onDeviceRemoved(in MidiDeviceInfo device);
-}
+parcelable ChooserTarget;
diff --git a/core/java/android/service/chooser/ChooserTarget.java b/core/java/android/service/chooser/ChooserTarget.java
new file mode 100644
index 0000000..7fd1d10
--- /dev/null
+++ b/core/java/android/service/chooser/ChooserTarget.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.service.chooser;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * A ChooserTarget represents a deep-link into an application as returned by a
+ * {@link android.service.chooser.ChooserTargetService}.
+ */
+public final class ChooserTarget implements Parcelable {
+ private static final String TAG = "ChooserTarget";
+
+ /**
+ * The title of this target that will be shown to the user. The title may be truncated
+ * if it is too long to display in the space provided.
+ */
+ private CharSequence mTitle;
+
+ /**
+ * The icon that will be shown to the user to represent this target.
+ * The system may resize this icon as appropriate.
+ */
+ private Bitmap mIcon;
+
+ /**
+ * The IntentSender that will be used to deliver the intent to the target.
+ * It will be {@link android.content.Intent#fillIn(android.content.Intent, int)} filled in}
+ * by the real intent sent by the application.
+ */
+ private IntentSender mIntentSender;
+
+ /**
+ * The score given to this item. It can be normalized.
+ */
+ private float mScore;
+
+ /**
+ * Construct a deep link target for presentation by a chooser UI.
+ *
+ * <p>A target is composed of a title and an icon for presentation to the user.
+ * The UI presenting this target may truncate the title if it is too long to be presented
+ * in the available space, as well as crop, resize or overlay the supplied icon.</p>
+ *
+ * <p>The creator of a target may supply a ranking score. This score is assumed to be relative
+ * to the other targets supplied by the same
+ * {@link ChooserTargetService#onGetChooserTargets(ComponentName, IntentFilter) query}.
+ * Scores should be in the range from 0.0f (unlikely match) to 1.0f (very relevant match).</p>
+ *
+ * <p>Before being sent, the PendingIntent supplied will be
+ * {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied
+ * to the chooser. When constructing a PendingIntent for use in a ChooserTarget, make sure
+ * that you permit the relevant fields to be filled in using the appropriate flags such as
+ * {@link Intent#FILL_IN_ACTION}, {@link Intent#FILL_IN_CATEGORIES},
+ * {@link Intent#FILL_IN_DATA} and {@link Intent#FILL_IN_CLIP_DATA}. Note that
+ * {@link Intent#FILL_IN_CLIP_DATA} is required to appropriately receive URI permission grants
+ * for {@link Intent#ACTION_SEND} intents.</p>
+ *
+ * <p>Take care not to place custom {@link android.os.Parcelable} types into
+ * the PendingIntent as extras, as the system will not be able to unparcel it to merge
+ * additional extras.</p>
+ *
+ * @param title title of this target that will be shown to a user
+ * @param icon icon to represent this target
+ * @param score ranking score for this target between 0.0f and 1.0f, inclusive
+ * @param pendingIntent PendingIntent to fill in and send if the user chooses this target
+ */
+ public ChooserTarget(CharSequence title, Bitmap icon, float score,
+ PendingIntent pendingIntent) {
+ this(title, icon, score, pendingIntent.getIntentSender());
+ }
+
+ /**
+ * Construct a deep link target for presentation by a chooser UI.
+ *
+ * <p>A target is composed of a title and an icon for presentation to the user.
+ * The UI presenting this target may truncate the title if it is too long to be presented
+ * in the available space, as well as crop, resize or overlay the supplied icon.</p>
+ *
+ * <p>The creator of a target may supply a ranking score. This score is assumed to be relative
+ * to the other targets supplied by the same
+ * {@link ChooserTargetService#onGetChooserTargets(ComponentName, IntentFilter) query}.
+ * Scores should be in the range from 0.0f (unlikely match) to 1.0f (very relevant match).</p>
+ *
+ * <p>Before being sent, the IntentSender supplied will be
+ * {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied
+ * to the chooser. When constructing an IntentSender for use in a ChooserTarget, make sure
+ * that you permit the relevant fields to be filled in using the appropriate flags such as
+ * {@link Intent#FILL_IN_ACTION}, {@link Intent#FILL_IN_CATEGORIES},
+ * {@link Intent#FILL_IN_DATA} and {@link Intent#FILL_IN_CLIP_DATA}. Note that
+ * {@link Intent#FILL_IN_CLIP_DATA} is required to appropriately receive URI permission grants
+ * for {@link Intent#ACTION_SEND} intents.</p>
+ *
+ * <p>Take care not to place custom {@link android.os.Parcelable} types into
+ * the IntentSender as extras, as the system will not be able to unparcel it to merge
+ * additional extras.</p>
+ *
+ * @param title title of this target that will be shown to a user
+ * @param icon icon to represent this target
+ * @param score ranking score for this target between 0.0f and 1.0f, inclusive
+ * @param intentSender IntentSender to fill in and send if the user chooses this target
+ */
+ public ChooserTarget(CharSequence title, Bitmap icon, float score, IntentSender intentSender) {
+ mTitle = title;
+ mIcon = icon;
+ if (score > 1.f || score < 0.f) {
+ throw new IllegalArgumentException("Score " + score + " out of range; "
+ + "must be between 0.0f and 1.0f");
+ }
+ mScore = score;
+ mIntentSender = intentSender;
+ }
+
+ ChooserTarget(Parcel in) {
+ mTitle = in.readCharSequence();
+ if (in.readInt() != 0) {
+ mIcon = Bitmap.CREATOR.createFromParcel(in);
+ } else {
+ mIcon = null;
+ }
+ mScore = in.readFloat();
+ mIntentSender = IntentSender.readIntentSenderOrNullFromParcel(in);
+ }
+
+ /**
+ * Returns the title of this target for display to a user. The UI displaying the title
+ * may truncate this title if it is too long to be displayed in full.
+ *
+ * @return the title of this target, intended to be shown to a user
+ */
+ public CharSequence getTitle() {
+ return mTitle;
+ }
+
+ /**
+ * Returns the icon representing this target for display to a user. The UI displaying the icon
+ * may crop, resize or overlay this icon.
+ *
+ * @return the icon representing this target, intended to be shown to a user
+ */
+ public Bitmap getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * Returns the ranking score supplied by the creator of this ChooserTarget.
+ * Values are between 0.0f and 1.0f. The UI displaying the target may
+ * take this score into account when sorting and merging targets from multiple sources.
+ *
+ * @return the ranking score for this target between 0.0f and 1.0f, inclusive
+ */
+ public float getScore() {
+ return mScore;
+ }
+
+ /**
+ * Returns the raw IntentSender supplied by the ChooserTarget's creator.
+ *
+ * <p>To fill in and send the intent, see {@link #sendIntent(Context, Intent)}.</p>
+ *
+ * @return the IntentSender supplied by the ChooserTarget's creator
+ */
+ public IntentSender getIntentSender() {
+ return mIntentSender;
+ }
+
+ /**
+ * Fill in the IntentSender supplied by the ChooserTarget's creator and send it.
+ *
+ * @param context the sending Context; generally the Activity presenting the chooser UI
+ * @param fillInIntent the Intent provided to the Chooser to be sent to a selected target
+ * @return true if sending the Intent was successful
+ */
+ public boolean sendIntent(Context context, Intent fillInIntent) {
+ if (fillInIntent != null) {
+ fillInIntent.migrateExtraStreamToClipData();
+ fillInIntent.prepareToLeaveProcess();
+ }
+ try {
+ mIntentSender.sendIntent(context, 0, fillInIntent, null, null);
+ return true;
+ } catch (IntentSender.SendIntentException e) {
+ Log.e(TAG, "sendIntent " + this + " failed", e);
+ return false;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "ChooserTarget{" + mIntentSender.getCreatorPackage() + "'" + mTitle
+ + "', " + mScore + "}";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharSequence(mTitle);
+ if (mIcon != null) {
+ dest.writeInt(1);
+ mIcon.writeToParcel(dest, 0);
+ } else {
+ dest.writeInt(0);
+ }
+ dest.writeFloat(mScore);
+ IntentSender.writeIntentSenderOrNullToParcel(mIntentSender, dest);
+ }
+
+ public static final Creator<ChooserTarget> CREATOR
+ = new Creator<ChooserTarget>() {
+ @Override
+ public ChooserTarget createFromParcel(Parcel source) {
+ return new ChooserTarget(source);
+ }
+
+ @Override
+ public ChooserTarget[] newArray(int size) {
+ return new ChooserTarget[size];
+ }
+ };
+}
diff --git a/core/java/android/service/chooser/ChooserTargetService.java b/core/java/android/service/chooser/ChooserTargetService.java
new file mode 100644
index 0000000..9188806
--- /dev/null
+++ b/core/java/android/service/chooser/ChooserTargetService.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.service.chooser;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import java.util.List;
+
+/**
+ * A service that receives calls from the system when the user is asked to choose
+ * a target for an intent explicitly by another app. The calling app must have invoked
+ * {@link android.content.Intent#ACTION_CHOOSER ACTION_CHOOSER} as handled by the system;
+ * applications do not have the ability to query a ChooserTargetService directly.
+ *
+ * <p>Which ChooserTargetServices are queried depends on a system-level policy decision
+ * made at the moment the chooser is invoked, including but not limited to user time
+ * spent with the app package or associated components in the foreground, recency of usage
+ * or frequency of usage. These will generally correlate with the order that app targets
+ * are shown in the list of intent handlers shown in the system chooser or resolver.</p>
+ *
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_CHOOSER_TARGET_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * <pre>
+ * <service android:name=".ChooserTargetService"
+ * android:label="@string/service_name"
+ * android:permission="android.permission.BIND_CHOOSER_TARGET_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.service.chooser.ChooserTargetService" />
+ * </intent-filter>
+ * </service>
+ * </pre>
+ *
+ * <p>For the system to query your service, you must add a <meta-data> element to the
+ * Activity in your manifest that can handle Intents that you would also like to provide
+ * optional deep links for. For example, a chat app might offer deep links to recent active
+ * conversations instead of invoking a generic picker after the app itself is chosen as a target.
+ * </p>
+ *
+ * <p>The meta-data element should have the name
+ * <code>android.service.chooser.chooser_target_service</code> and a value corresponding to
+ * the component name of your service. Example:</p>
+ * <pre>
+ * <activity android:name=".MyShareActivity"
+ * android:label="@string/share_activity_label">
+ * <intent-filter>
+ * <action android:name="android.intent.action.SEND" />
+ * </intent-filter>
+ * <meta-data android:name="android.service.chooser.chooser_target_service"
+ * android:value=".ChooserTargetService" />
+ * </activity>
+ * </pre>
+ */
+public abstract class ChooserTargetService extends Service {
+ // TAG = "ChooserTargetService[MySubclass]";
+ private final String TAG = ChooserTargetService.class.getSimpleName()
+ + '[' + getClass().getSimpleName() + ']';
+
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE = "android.service.chooser.ChooserTargetService";
+
+ private IChooserTargetServiceWrapper mWrapper = null;
+
+ /**
+ * Called by the system to retrieve a set of deep-link {@link ChooserTarget targets} that
+ * can handle an intent.
+ *
+ * <p>The returned list should be sorted such that the most relevant targets appear first.
+ * Any PendingIntents used to construct the resulting ChooserTargets should always be prepared
+ * to have the relevant data fields filled in by the sender. See
+ * {@link ChooserTarget#ChooserTarget(CharSequence, android.graphics.Bitmap, float, android.app.PendingIntent) ChooserTarget}.</p>
+ *
+ * <p><em>Important:</em> Calls to this method from other applications will occur on
+ * a binder thread, not on your app's main thread. Make sure that access to relevant data
+ * within your app is thread-safe.</p>
+ *
+ * @param targetActivityName the ComponentName of the matched activity that referred the system
+ * to this ChooserTargetService
+ * @param matchedFilter the specific IntentFilter on the component that was matched
+ * @return a list of deep-link targets to fulfill the intent match, sorted by relevance
+ */
+ public abstract List<ChooserTarget> onGetChooserTargets(ComponentName targetActivityName,
+ IntentFilter matchedFilter);
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (!SERVICE_INTERFACE.equals(intent.getAction())) {
+ return null;
+ }
+
+ if (mWrapper == null) {
+ mWrapper = new IChooserTargetServiceWrapper();
+ }
+ return mWrapper;
+ }
+
+ private class IChooserTargetServiceWrapper extends IChooserTargetService.Stub {
+ @Override
+ public void getChooserTargets(ComponentName targetComponentName,
+ IntentFilter matchedFilter, IChooserTargetResult result) throws RemoteException {
+ List<ChooserTarget> targets = null;
+ try {
+ targets = onGetChooserTargets(targetComponentName, matchedFilter);
+ } finally {
+ result.sendResult(targets);
+ }
+ }
+ }
+}
diff --git a/media/java/android/media/midi/IMidiListener.aidl b/core/java/android/service/chooser/IChooserTargetResult.aidl
similarity index 67%
copy from media/java/android/media/midi/IMidiListener.aidl
copy to core/java/android/service/chooser/IChooserTargetResult.aidl
index a4129e9..dbd7cbd 100644
--- a/media/java/android/media/midi/IMidiListener.aidl
+++ b/core/java/android/service/chooser/IChooserTargetResult.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 The Android Open 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,13 +14,14 @@
* limitations under the License.
*/
-package android.media.midi;
+package android.service.chooser;
-import android.media.midi.MidiDeviceInfo;
+import android.service.chooser.ChooserTarget;
-/** @hide */
-oneway interface IMidiListener
+/**
+ * @hide
+ */
+interface IChooserTargetResult
{
- void onDeviceAdded(in MidiDeviceInfo device);
- void onDeviceRemoved(in MidiDeviceInfo device);
+ void sendResult(in List<ChooserTarget> targets);
}
diff --git a/core/java/android/service/chooser/IChooserTargetService.aidl b/core/java/android/service/chooser/IChooserTargetService.aidl
new file mode 100644
index 0000000..6cfa9a2
--- /dev/null
+++ b/core/java/android/service/chooser/IChooserTargetService.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.service.chooser;
+
+import android.content.ComponentName;
+import android.content.IntentFilter;
+import android.service.chooser.IChooserTargetResult;
+
+/**
+ * @hide
+ */
+oneway interface IChooserTargetService
+{
+ void getChooserTargets(in ComponentName targetComponentName,
+ in IntentFilter matchedFilter, IChooserTargetResult result);
+}
\ No newline at end of file
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 77ef1da..1bdaef0 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -270,22 +270,30 @@
// generate new layout for affected text
StaticLayout reflowed;
+ StaticLayout.Builder b;
synchronized (sLock) {
reflowed = sStaticLayout;
+ b = sBuilder;
sStaticLayout = null;
+ sBuilder = null;
}
+ // TODO: make sure reflowed is properly initialized
if (reflowed == null) {
reflowed = new StaticLayout(null);
- } else {
- reflowed.prepare();
+ b = StaticLayout.Builder.obtain();
}
- reflowed.generate(text, where, where + after,
- getPaint(), getWidth(), getTextDirectionHeuristic(), getSpacingMultiplier(),
- getSpacingAdd(), false,
- true, mEllipsizedWidth, mEllipsizeAt);
+ b.setText(text, where, where + after)
+ .setPaint(getPaint())
+ .setWidth(getWidth())
+ .setTextDir(getTextDirectionHeuristic())
+ .setSpacingMult(getSpacingMultiplier())
+ .setSpacingAdd(getSpacingAdd())
+ .setEllipsizedWidth(mEllipsizedWidth)
+ .setEllipsize(mEllipsizeAt);
+ reflowed.generate(b, false, true);
int n = reflowed.getLineCount();
// If the new layout has a blank line at the end, but it is not
@@ -359,9 +367,10 @@
updateBlocks(startline, endline - 1, n);
+ b.finish();
synchronized (sLock) {
sStaticLayout = reflowed;
- reflowed.finish();
+ sBuilder = b;
}
}
@@ -720,7 +729,8 @@
private int mTopPadding, mBottomPadding;
- private static StaticLayout sStaticLayout = new StaticLayout(null);
+ private static StaticLayout sStaticLayout = null;
+ private static StaticLayout.Builder sBuilder = null;
private static final Object[] sLock = new Object[0];
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index e72e18f..832002c 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -66,21 +66,28 @@
}
static MeasuredText recycle(MeasuredText mt) {
- mt.mText = null;
- if (mt.mLen < 1000) {
- synchronized(sLock) {
- for (int i = 0; i < sCached.length; ++i) {
- if (sCached[i] == null) {
- sCached[i] = mt;
- mt.mText = null;
- break;
- }
+ mt.finish();
+ synchronized(sLock) {
+ for (int i = 0; i < sCached.length; ++i) {
+ if (sCached[i] == null) {
+ sCached[i] = mt;
+ mt.mText = null;
+ break;
}
}
}
return null;
}
+ void finish() {
+ mText = null;
+ if (mLen > 1000) {
+ mWidths = null;
+ mChars = null;
+ mLevels = null;
+ }
+ }
+
void setPos(int pos) {
mPos = pos - mTextStart;
}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index ffb7d36..967e80c 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -28,6 +28,7 @@
import com.android.internal.util.GrowingArrayUtils;
import java.util.Arrays;
+import java.util.Locale;
/**
* StaticLayout is a Layout for text that will not be edited after it
@@ -43,6 +44,179 @@
static final String TAG = "StaticLayout";
+ /**
+ * Builder for static layouts. It would be better if this were a public
+ * API (as it would offer much greater flexibility for adding new options)
+ * but for the time being it's just internal.
+ *
+ * @hide
+ */
+ public final static class Builder {
+ private Builder() {
+ mNativePtr = nNewBuilder();
+ }
+
+ static Builder obtain() {
+ Builder b = null;
+ synchronized (sLock) {
+ for (int i = 0; i < sCached.length; i++) {
+ if (sCached[i] != null) {
+ b = sCached[i];
+ sCached[i] = null;
+ break;
+ }
+ }
+ }
+ if (b == null) {
+ b = new Builder();
+ }
+
+ // set default initial values
+ b.mWidth = 0;
+ b.mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
+ b.mSpacingMult = 1.0f;
+ b.mSpacingAdd = 0.0f;
+ b.mIncludePad = true;
+ b.mEllipsizedWidth = 0;
+ b.mEllipsize = null;
+ b.mMaxLines = Integer.MAX_VALUE;
+
+ b.mMeasuredText = MeasuredText.obtain();
+ return b;
+ }
+
+ static void recycle(Builder b) {
+ b.mPaint = null;
+ b.mText = null;
+ MeasuredText.recycle(b.mMeasuredText);
+ synchronized (sLock) {
+ for (int i = 0; i < sCached.length; i++) {
+ if (sCached[i] == null) {
+ sCached[i] = b;
+ break;
+ }
+ }
+ }
+ }
+
+ // release any expensive state
+ /* package */ void finish() {
+ nFinishBuilder(mNativePtr);
+ mMeasuredText.finish();
+ }
+
+ public Builder setText(CharSequence source) {
+ return setText(source, 0, source.length());
+ }
+
+ public Builder setText(CharSequence source, int start, int end) {
+ mText = source;
+ mStart = start;
+ mEnd = end;
+ return this;
+ }
+
+ public Builder setPaint(TextPaint paint) {
+ mPaint = paint;
+ return this;
+ }
+
+ public Builder setWidth(int width) {
+ mWidth = width;
+ if (mEllipsize == null) {
+ mEllipsizedWidth = width;
+ }
+ return this;
+ }
+
+ public Builder setTextDir(TextDirectionHeuristic textDir) {
+ mTextDir = textDir;
+ return this;
+ }
+
+ // TODO: combine the following, as they're almost always set together?
+ public Builder setSpacingMult(float spacingMult) {
+ mSpacingMult = spacingMult;
+ return this;
+ }
+
+ public Builder setSpacingAdd(float spacingAdd) {
+ mSpacingAdd = spacingAdd;
+ return this;
+ }
+
+ public Builder setIncludePad(boolean includePad) {
+ mIncludePad = includePad;
+ return this;
+ }
+
+ // TODO: combine the following?
+ public Builder setEllipsizedWidth(int ellipsizedWidth) {
+ mEllipsizedWidth = ellipsizedWidth;
+ return this;
+ }
+
+ public Builder setEllipsize(TextUtils.TruncateAt ellipsize) {
+ mEllipsize = ellipsize;
+ return this;
+ }
+
+ public Builder setMaxLines(int maxLines) {
+ mMaxLines = maxLines;
+ return this;
+ }
+
+ /* @hide */
+ public void setLocale(Locale locale) {
+ if (!locale.equals(mLocale)) {
+ nBuilderSetLocale(mNativePtr, locale.toLanguageTag());
+ mLocale = locale;
+ }
+ }
+
+ public StaticLayout build() {
+ // TODO: can optimize based on whether ellipsis is needed
+ StaticLayout result = new StaticLayout(mText);
+ result.initFromBuilder(this);
+ recycle(this);
+ return result;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ nFreeBuilder(mNativePtr);
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /* package */ long mNativePtr;
+
+ CharSequence mText;
+ int mStart;
+ int mEnd;
+ TextPaint mPaint;
+ int mWidth;
+ TextDirectionHeuristic mTextDir;
+ float mSpacingMult;
+ float mSpacingAdd;
+ boolean mIncludePad;
+ int mEllipsizedWidth;
+ TextUtils.TruncateAt mEllipsize;
+ int mMaxLines;
+
+ Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
+
+ // This will go away and be subsumed by native builder code
+ MeasuredText mMeasuredText;
+
+ Locale mLocale;
+
+ private static final Object sLock = new Object();
+ private static final Builder[] sCached = new Builder[3];
+ }
+
public StaticLayout(CharSequence source, TextPaint paint,
int width,
Alignment align, float spacingmult, float spacingadd,
@@ -110,6 +284,17 @@
: new Ellipsizer(source),
paint, outerwidth, align, textDir, spacingmult, spacingadd);
+ Builder b = Builder.obtain();
+ b.setText(source, bufstart, bufend)
+ .setPaint(paint)
+ .setWidth(outerwidth)
+ .setTextDir(textDir)
+ .setSpacingMult(spacingmult)
+ .setSpacingAdd(spacingadd)
+ .setIncludePad(includepad)
+ .setEllipsizedWidth(ellipsizedWidth)
+ .setEllipsize(ellipsize)
+ .setMaxLines(maxLines);
/*
* This is annoying, but we can't refer to the layout until
* superclass construction is finished, and the superclass
@@ -136,14 +321,9 @@
mLines = new int[mLineDirections.length];
mMaximumVisibleLineCount = maxLines;
- mMeasured = MeasuredText.obtain();
+ initFromBuilder(b);
- generate(source, bufstart, bufend, paint, outerwidth, textDir, spacingmult,
- spacingadd, includepad, includepad, ellipsizedWidth,
- ellipsize);
-
- mMeasured = MeasuredText.recycle(mMeasured);
- mFontMetricsInt = null;
+ Builder.recycle(b);
}
/* package */ StaticLayout(CharSequence text) {
@@ -152,33 +332,40 @@
mColumns = COLUMNS_ELLIPSIZE;
mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
mLines = new int[mLineDirections.length];
- // FIXME This is never recycled
- mMeasured = MeasuredText.obtain();
}
- /* package */ void generate(CharSequence source, int bufStart, int bufEnd,
- TextPaint paint, int outerWidth,
- TextDirectionHeuristic textDir, float spacingmult,
- float spacingadd, boolean includepad,
- boolean trackpad, float ellipsizedWidth,
- TextUtils.TruncateAt ellipsize) {
- LineBreaks lineBreaks = new LineBreaks();
+ private void initFromBuilder(Builder b) {
+ generate(b, b.mIncludePad, b.mIncludePad);
+ }
+
+ /* package */ void generate(Builder b, boolean includepad, boolean trackpad) {
+ CharSequence source = b.mText;
+ int bufStart = b.mStart;
+ int bufEnd = b.mEnd;
+ TextPaint paint = b.mPaint;
+ int outerWidth = b.mWidth;
+ TextDirectionHeuristic textDir = b.mTextDir;
+ float spacingmult = b.mSpacingMult;
+ float spacingadd = b.mSpacingAdd;
+ float ellipsizedWidth = b.mEllipsizedWidth;
+ TextUtils.TruncateAt ellipsize = b.mEllipsize;
+ LineBreaks lineBreaks = new LineBreaks(); // TODO: move to builder to avoid allocation costs
// store span end locations
int[] spanEndCache = new int[4];
// store fontMetrics per span range
// must be a multiple of 4 (and > 0) (store top, bottom, ascent, and descent per range)
int[] fmCache = new int[4 * 4];
- final String localeLanguageTag = paint.getTextLocale().toLanguageTag();
+ b.setLocale(paint.getTextLocale()); // TODO: also respect LocaleSpan within the text
mLineCount = 0;
int v = 0;
boolean needMultiply = (spacingmult != 1 || spacingadd != 0);
- Paint.FontMetricsInt fm = mFontMetricsInt;
+ Paint.FontMetricsInt fm = b.mFontMetricsInt;
int[] chooseHtv = null;
- MeasuredText measured = mMeasured;
+ MeasuredText measured = b.mMeasuredText;
Spanned spanned = null;
if (source instanceof Spanned)
@@ -306,7 +493,7 @@
}
}
- int breakCount = nComputeLineBreaks(localeLanguageTag, chs, widths, paraEnd - paraStart, firstWidth,
+ int breakCount = nComputeLineBreaks(b.mNativePtr, chs, widths, paraEnd - paraStart, firstWidth,
firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, false, lineBreaks,
lineBreaks.breaks, lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length);
@@ -746,24 +933,21 @@
return mEllipsizedWidth;
}
- void prepare() {
- mMeasured = MeasuredText.obtain();
- }
-
- void finish() {
- mMeasured = MeasuredText.recycle(mMeasured);
- }
-
// populates LineBreaks and returns the number of breaks found
//
// the arrays inside the LineBreaks objects are passed in as well
// to reduce the number of JNI calls in the common case where the
// arrays do not have to be resized
- private static native int nComputeLineBreaks(String locale, char[] text, float[] widths,
+ private static native int nComputeLineBreaks(long nativePtr, char[] text, float[] widths,
int length, float firstWidth, int firstWidthLineCount, float restWidth,
int[] variableTabStops, int defaultTabStop, boolean optimize, LineBreaks recycle,
int[] recycleBreaks, float[] recycleWidths, boolean[] recycleFlags, int recycleLength);
+ private static native long nNewBuilder();
+ private static native void nFreeBuilder(long nativePtr);
+ private static native void nFinishBuilder(long nativePtr);
+ private static native void nBuilderSetLocale(long nativePtr, String locale);
+
private int mLineCount;
private int mTopPadding, mBottomPadding;
private int mColumns;
@@ -793,12 +977,6 @@
private static final double EXTRA_ROUNDING = 0.5;
- /*
- * This is reused across calls to generate()
- */
- private MeasuredText mMeasured;
- private Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
-
// This is used to return three arrays from a single JNI call when
// performing line breaking
/*package*/ static class LineBreaks {
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 80245ef..0b70fdb 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -181,24 +181,27 @@
private static void changeScene(Scene scene, Transition transition) {
final ViewGroup sceneRoot = scene.getSceneRoot();
+ if (!sPendingTransitions.contains(sceneRoot)) {
+ sPendingTransitions.add(sceneRoot);
- Transition transitionClone = null;
- if (transition != null) {
- transitionClone = transition.clone();
- transitionClone.setSceneRoot(sceneRoot);
+ Transition transitionClone = null;
+ if (transition != null) {
+ transitionClone = transition.clone();
+ transitionClone.setSceneRoot(sceneRoot);
+ }
+
+ Scene oldScene = Scene.getCurrentScene(sceneRoot);
+ if (oldScene != null && transitionClone != null &&
+ oldScene.isCreatedFromLayoutResource()) {
+ transitionClone.setCanRemoveViews(true);
+ }
+
+ sceneChangeSetup(sceneRoot, transitionClone);
+
+ scene.enter();
+
+ sceneChangeRunTransition(sceneRoot, transitionClone);
}
-
- Scene oldScene = Scene.getCurrentScene(sceneRoot);
- if (oldScene != null && transitionClone != null &&
- oldScene.isCreatedFromLayoutResource()) {
- transitionClone.setCanRemoveViews(true);
- }
-
- sceneChangeSetup(sceneRoot, transitionClone);
-
- scene.enter();
-
- sceneChangeRunTransition(sceneRoot, transitionClone);
}
private static ArrayMap<ViewGroup, ArrayList<Transition>> getRunningTransitions() {
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 68f725e..7da3941 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -475,6 +475,26 @@
}
/**
+ * Perform a {@link #remove(Object)} of all values in <var>array</var>
+ * @param array The array whose contents are to be removed.
+ */
+ public boolean removeAll(ArraySet<? extends E> array) {
+ // TODO: If array is sufficiently large, a marking approach might be beneficial. In a first
+ // pass, use the property that the sets are sorted by hash to make this linear passes
+ // (except for hash collisions, which means worst case still n*m), then do one
+ // collection pass into a new array. This avoids binary searches and excessive memcpy.
+ final int N = array.mSize;
+
+ // Note: ArraySet does not make thread-safety guarantees. So instead of OR-ing together all
+ // the single results, compare size before and after.
+ final int originalSize = mSize;
+ for (int i = 0; i < N; i++) {
+ remove(array.valueAt(i));
+ }
+ return originalSize != mSize;
+ }
+
+ /**
* Return the number of items in this array map.
*/
@Override
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 0d36949..06e196d 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -204,7 +204,7 @@
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
- nDrawPatch(mNativeCanvasWrapper, bitmap.mNativeBitmap, patch.mNativeChunk,
+ nDrawPatch(mNativeCanvasWrapper, bitmap.getSkBitmap(), patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
@@ -214,7 +214,7 @@
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
- nDrawPatch(mNativeCanvasWrapper, bitmap.mNativeBitmap, patch.mNativeChunk,
+ nDrawPatch(mNativeCanvasWrapper, bitmap.getSkBitmap(), patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index df0838f..69b4c47 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -364,7 +364,7 @@
@Override
boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
return nCopyLayerInto(mNativeProxy,
- layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
+ layer.getDeferredLayerUpdater(), bitmap.getSkBitmap());
}
@Override
@@ -465,7 +465,7 @@
for (int i = 0; i < count; i++) {
drawables.valueAt(i).addAtlasableBitmaps(tmpList);
for (int j = 0; j < tmpList.size(); j++) {
- preloadedPointers.add(tmpList.get(j).mNativeBitmap);
+ preloadedPointers.add(tmpList.get(j).getSkBitmap());
}
tmpList.clear();
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index f8e207f..5d519ed 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -217,6 +217,12 @@
WordIterator mWordIterator;
SpellChecker mSpellChecker;
+ // This word iterator is set with text and used to determine word boundaries
+ // when a user is selecting text.
+ private WordIterator mWordIteratorWithText;
+ // Indicate that the text in the word iterator needs to be updated.
+ private boolean mUpdateWordIteratorText;
+
private Rect mTempRect;
private TextView mTextView;
@@ -689,9 +695,52 @@
return mTextView.getTransformationMethod() instanceof PasswordTransformationMethod;
}
+ private int getWordStart(int offset) {
+ // FIXME - For this and similar methods we're not doing anything to check if there's
+ // a LocaleSpan in the text, this may be something we should try handling or checking for.
+ int retOffset = getWordIteratorWithText().getBeginning(offset);
+ if (retOffset == BreakIterator.DONE) retOffset = offset;
+ return retOffset;
+ }
+
+ private int getWordEnd(int offset, boolean includePunctuation) {
+ int retOffset = getWordIteratorWithText().getEnd(offset);
+ if (retOffset == BreakIterator.DONE) {
+ retOffset = offset;
+ } else if (includePunctuation) {
+ retOffset = handlePunctuation(retOffset);
+ }
+ return retOffset;
+ }
+
+ private boolean isEndBoundary(int offset) {
+ int thisEnd = getWordEnd(offset, false);
+ return offset == thisEnd;
+ }
+
+ private boolean isStartBoundary(int offset) {
+ int thisStart = getWordStart(offset);
+ return thisStart == offset;
+ }
+
+ private int handlePunctuation(int offset) {
+ // FIXME - Check with UX how repeated ending punctuation should be handled.
+ // FIXME - Check with UX if / how we would handle non sentence ending characters.
+ // FIXME - Consider punctuation in different languages.
+ CharSequence text = mTextView.getText();
+ if (offset < text.length()) {
+ int c = Character.codePointAt(text, offset);
+ if (c == 0x002e /* period */|| c == 0x003f /* question mark */
+ || c == 0x0021 /* exclamation mark */) {
+ offset = Character.offsetByCodePoints(text, offset, 1);
+ }
+ }
+ return offset;
+ }
+
/**
- * Adjusts selection to the word under last touch offset.
- * Return true if the operation was successfully performed.
+ * Adjusts selection to the word under last touch offset. Return true if the operation was
+ * successfully performed.
*/
private boolean selectCurrentWord() {
if (!canSelectText()) {
@@ -738,6 +787,8 @@
selectionStart = ((Spanned) mTextView.getText()).getSpanStart(urlSpan);
selectionEnd = ((Spanned) mTextView.getText()).getSpanEnd(urlSpan);
} else {
+ // FIXME - We should check if there's a LocaleSpan in the text, this may be
+ // something we should try handling or checking for.
final WordIterator wordIterator = getWordIterator();
wordIterator.setCharSequence(mTextView.getText(), minOffset, maxOffset);
@@ -760,6 +811,7 @@
void onLocaleChanged() {
// Will be re-created on demand in getWordIterator with the proper new locale
mWordIterator = null;
+ mWordIteratorWithText = null;
}
/**
@@ -772,6 +824,23 @@
return mWordIterator;
}
+ private WordIterator getWordIteratorWithText() {
+ if (mWordIteratorWithText == null) {
+ mWordIteratorWithText = new WordIterator(mTextView.getTextServicesLocale());
+ mUpdateWordIteratorText = true;
+ }
+ if (mUpdateWordIteratorText) {
+ // FIXME - Shouldn't copy all of the text as only the area of the text relevant
+ // to the user's selection is needed. A possible solution would be to
+ // copy some number N of characters near the selection and then when the
+ // user approaches N then we'd do another copy of the next N characters.
+ CharSequence text = mTextView.getText();
+ mWordIteratorWithText.setCharSequence(text, 0, text.length());
+ mUpdateWordIteratorText = false;
+ }
+ return mWordIteratorWithText;
+ }
+
private long getCharRange(int offset) {
final int textLength = mTextView.getText().length();
if (offset + 1 < textLength) {
@@ -920,9 +989,8 @@
mTextView.startDrag(data, getTextThumbnailBuilder(selectedText), localState, 0);
stopSelectionActionMode();
} else {
- getSelectionController().hide();
- selectCurrentWord();
- getSelectionController().show();
+ stopSelectionActionMode();
+ startSelectionActionMode();
}
handled = true;
}
@@ -1058,6 +1126,9 @@
void sendOnTextChanged(int start, int after) {
updateSpellCheckSpans(start, start + after, false);
+ // Flip flag to indicate the word iterator needs to have the text reset.
+ mUpdateWordIteratorText = true;
+
// Hide the controllers as soon as text is modified (typing, procedural...)
// We do not hide the span controllers, since they can be added when a new text is
// inserted into the text view (voice IME).
@@ -1613,6 +1684,9 @@
}
}
+ if (selectionStarted) {
+ getSelectionController().enterDrag();
+ }
return selectionStarted;
}
@@ -2894,7 +2968,6 @@
}
if (menu.hasVisibleItems() || mode.getCustomView() != null) {
- getSelectionController().show();
mTextView.setHasTransientState(true);
return true;
} else {
@@ -3232,6 +3305,8 @@
private Runnable mActionPopupShower;
// Minimum touch target size for handles
private int mMinSize;
+ // Indicates the line of text that the handle is on.
+ protected int mLine = -1;
public HandleView(Drawable drawableLtr, Drawable drawableRtl) {
super(mTextView.getContext());
@@ -3407,6 +3482,7 @@
addPositionToTouchUpFilter(offset);
}
final int line = layout.getLineForOffset(offset);
+ mLine = line;
mPositionX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f - mHotspotX -
getHorizontalOffset() + getCursorOffset());
@@ -3456,6 +3532,30 @@
}
}
+ public void showAtLocation(int offset) {
+ // TODO - investigate if there's a better way to show the handles
+ // after the drag accelerator has occured.
+ int[] tmpCords = new int[2];
+ mTextView.getLocationInWindow(tmpCords);
+
+ Layout layout = mTextView.getLayout();
+ int posX = tmpCords[0];
+ int posY = tmpCords[1];
+
+ final int line = layout.getLineForOffset(offset);
+
+ int startX = (int) (layout.getPrimaryHorizontal(offset) - 0.5f
+ - mHotspotX - getHorizontalOffset() + getCursorOffset());
+ int startY = layout.getLineBottom(line);
+
+ // Take TextView's padding and scroll into account.
+ startX += mTextView.viewportToContentHorizontalOffset();
+ startY += mTextView.viewportToContentVerticalOffset();
+
+ mContainer.showAtLocation(mTextView, Gravity.NO_GRAVITY,
+ startX + posX, startY + posY);
+ }
+
@Override
protected void onDraw(Canvas c) {
final int drawWidth = mDrawable.getIntrinsicWidth();
@@ -3694,6 +3794,12 @@
}
private class SelectionStartHandleView extends HandleView {
+ // The previous offset this handle was at.
+ private int mPrevOffset;
+ // Indicates whether the cursor is making adjustments within a word.
+ private boolean mInWord = false;
+ // Offset to track difference between touch and word boundary.
+ protected int mTouchWordOffset;
public SelectionStartHandleView(Drawable drawableLtr, Drawable drawableRtl) {
super(drawableLtr, drawableRtl);
@@ -3701,11 +3807,7 @@
@Override
protected int getHotspotX(Drawable drawable, boolean isRtlRun) {
- if (isRtlRun) {
- return drawable.getIntrinsicWidth() / 4;
- } else {
- return (drawable.getIntrinsicWidth() * 3) / 4;
- }
+ return isRtlRun ? 0 : drawable.getIntrinsicWidth();
}
@Override
@@ -3727,21 +3829,81 @@
@Override
public void updatePosition(float x, float y) {
- int offset = mTextView.getOffsetForPosition(x, y);
+ final int trueOffset = mTextView.getOffsetForPosition(x, y);
+ final int currLine = mTextView.getLineAtCoordinate(y);
+ int offset = trueOffset;
+ boolean positionCursor = false;
- // Handles can not cross and selection is at least one character
- final int selectionEnd = mTextView.getSelectionEnd();
- if (offset >= selectionEnd) offset = Math.max(0, selectionEnd - 1);
+ int end = getWordEnd(offset, true);
+ int start = getWordStart(offset);
- positionAtCursorOffset(offset, false);
+ if (offset < mPrevOffset) {
+ // User is increasing the selection.
+ if (!mInWord || currLine < mLine) {
+ // We're not in a word, or we're on a different line so we'll expand by
+ // word. First ensure the user has at least entered the next word.
+ int offsetToWord = Math.min((end - start) / 2, 2);
+ if (offset <= end - offsetToWord || currLine < mLine) {
+ offset = start;
+ } else {
+ offset = mPrevOffset;
+ }
+ }
+ mPrevOffset = offset;
+ mTouchWordOffset = trueOffset - offset;
+ mInWord = !isStartBoundary(offset);
+ positionCursor = true;
+ } else if (offset - mTouchWordOffset > mPrevOffset) {
+ // User is shrinking the selection.
+ if (currLine > mLine) {
+ // We're on a different line, so we'll snap to word boundaries.
+ offset = end;
+ }
+ offset -= mTouchWordOffset;
+ mPrevOffset = offset;
+ mInWord = !isEndBoundary(offset);
+ positionCursor = true;
+ }
+
+ // Handles can not cross and selection is at least one character.
+ if (positionCursor) {
+ final int selectionEnd = mTextView.getSelectionEnd();
+ if (offset >= selectionEnd) {
+ // We can't cross the handles so let's just constrain the Y value.
+ int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x);
+ if (alteredOffset >= selectionEnd) {
+ // Can't pass the other drag handle.
+ offset = Math.max(0, selectionEnd - 1);
+ } else {
+ offset = alteredOffset;
+ }
+ }
+ positionAtCursorOffset(offset, false);
+ }
}
public ActionPopupWindow getActionPopupWindow() {
return mActionPopupWindow;
}
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean superResult = super.onTouchEvent(event);
+ if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ // Reset the touch word offset when the user has lifted their finger.
+ mTouchWordOffset = 0;
+ }
+ return superResult;
+ }
}
private class SelectionEndHandleView extends HandleView {
+ // The previous offset this handle was at.
+ private int mPrevOffset;
+ // Indicates whether the cursor is making adjustments within a word.
+ private boolean mInWord = false;
+ // Offset to track difference between touch and word boundary.
+ protected int mTouchWordOffset;
public SelectionEndHandleView(Drawable drawableLtr, Drawable drawableRtl) {
super(drawableLtr, drawableRtl);
@@ -3749,11 +3911,7 @@
@Override
protected int getHotspotX(Drawable drawable, boolean isRtlRun) {
- if (isRtlRun) {
- return (drawable.getIntrinsicWidth() * 3) / 4;
- } else {
- return drawable.getIntrinsicWidth() / 4;
- }
+ return isRtlRun ? drawable.getIntrinsicWidth() : 0;
}
@Override
@@ -3775,20 +3933,72 @@
@Override
public void updatePosition(float x, float y) {
- int offset = mTextView.getOffsetForPosition(x, y);
+ final int trueOffset = mTextView.getOffsetForPosition(x, y);
+ final int currLine = mTextView.getLineAtCoordinate(y);
+ int offset = trueOffset;
+ boolean positionCursor = false;
- // Handles can not cross and selection is at least one character
- final int selectionStart = mTextView.getSelectionStart();
- if (offset <= selectionStart) {
- offset = Math.min(selectionStart + 1, mTextView.getText().length());
+ int end = getWordEnd(offset, true);
+ int start = getWordStart(offset);
+
+ if (offset > mPrevOffset) {
+ // User is increasing the selection.
+ if (!mInWord || currLine > mLine) {
+ // We're not in a word, or we're on a different line so we'll expand by
+ // word. First ensure the user has at least entered the next word.
+ int midPoint = Math.min((end - start) / 2, 2);
+ if (offset >= start + midPoint || currLine > mLine) {
+ offset = end;
+ } else {
+ offset = mPrevOffset;
+ }
+ }
+ mPrevOffset = offset;
+ mTouchWordOffset = offset - trueOffset;
+ mInWord = !isEndBoundary(offset);
+ positionCursor = true;
+ } else if (offset + mTouchWordOffset < mPrevOffset) {
+ // User is shrinking the selection.
+ if (currLine > mLine) {
+ // We're on a different line, so we'll snap to word boundaries.
+ offset = getWordStart(offset);
+ }
+ offset += mTouchWordOffset;
+ mPrevOffset = offset;
+ positionCursor = true;
+ mInWord = !isStartBoundary(offset);
}
- positionAtCursorOffset(offset, false);
+ if (positionCursor) {
+ final int selectionStart = mTextView.getSelectionStart();
+ if (offset <= selectionStart) {
+ // We can't cross the handles so let's just constrain the Y value.
+ int alteredOffset = mTextView.getOffsetAtCoordinate(mLine, x);
+ int length = mTextView.getText().length();
+ if (alteredOffset <= selectionStart) {
+ // Can't pass the other drag handle.
+ offset = Math.min(selectionStart + 1, length);
+ } else {
+ offset = Math.min(alteredOffset, length);
+ }
+ }
+ positionAtCursorOffset(offset, false);
+ }
}
public void setActionPopupWindow(ActionPopupWindow actionPopupWindow) {
mActionPopupWindow = actionPopupWindow;
}
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean superResult = super.onTouchEvent(event);
+ if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ // Reset the touch word offset when the user has lifted their finger.
+ mTouchWordOffset = 0;
+ }
+ return superResult;
+ }
}
/**
@@ -3871,6 +4081,11 @@
private float mDownPositionX, mDownPositionY;
private boolean mGestureStayedInTapRegion;
+ // Where the user first starts the drag motion.
+ private int mStartOffset = -1;
+ // Indicates whether the user is selecting text and using the drag accelerator.
+ private boolean mDragAcceleratorActive;
+
SelectionModifierCursorController() {
resetTouchOffsets();
}
@@ -3920,6 +4135,22 @@
if (mEndHandle != null) mEndHandle.hide();
}
+ public void enterDrag() {
+ // Just need to init the handles / hide insertion cursor.
+ show();
+ mDragAcceleratorActive = true;
+ // Start location of selection.
+ mStartOffset = mTextView.getOffsetForPosition(mLastDownPositionX,
+ mLastDownPositionY);
+ // Don't show the handles until user has lifted finger.
+ hide();
+
+ // This stops scrolling parents from intercepting the touch event, allowing
+ // the user to continue dragging across the screen to select text; TextView will
+ // scroll as necessary.
+ mTextView.getParent().requestDisallowInterceptTouchEvent(true);
+ }
+
public void onTouchEvent(MotionEvent event) {
// This is done even when the View does not have focus, so that long presses can start
// selection and tap can move cursor from this tap position.
@@ -3928,7 +4159,7 @@
final float x = event.getX();
final float y = event.getY();
- // Remember finger down position, to be able to start selection from there
+ // Remember finger down position, to be able to start selection from there.
mMinTouchOffset = mMaxTouchOffset = mTextView.getOffsetForPosition(x, y);
// Double tap detection
@@ -3967,23 +4198,112 @@
break;
case MotionEvent.ACTION_MOVE:
+ final ViewConfiguration viewConfiguration = ViewConfiguration.get(
+ mTextView.getContext());
+
if (mGestureStayedInTapRegion) {
final float deltaX = event.getX() - mDownPositionX;
final float deltaY = event.getY() - mDownPositionY;
final float distanceSquared = deltaX * deltaX + deltaY * deltaY;
- final ViewConfiguration viewConfiguration = ViewConfiguration.get(
- mTextView.getContext());
int doubleTapTouchSlop = viewConfiguration.getScaledDoubleTapTouchSlop();
if (distanceSquared > doubleTapTouchSlop * doubleTapTouchSlop) {
mGestureStayedInTapRegion = false;
}
}
+
+ if (mStartHandle != null && mStartHandle.isShowing()) {
+ // Don't do the drag if the handles are showing already.
+ break;
+ }
+
+ if (mStartOffset != -1) {
+ final int rawOffset = mTextView.getOffsetForPosition(event.getX(),
+ event.getY());
+ int offset = rawOffset;
+
+ // We don't start "dragging" until the user is past the initial word that
+ // gets selected on long press.
+ int firstWordStart = getWordStart(mStartOffset);
+ int firstWordEnd = getWordEnd(mStartOffset, false);
+ if (offset > firstWordEnd || offset < firstWordStart) {
+
+ // Basically the goal in the below code is to have the highlight be
+ // offset so that your finger isn't covering the end point.
+ int fingerOffset = viewConfiguration.getScaledTouchSlop();
+ float mx = event.getX();
+ float my = event.getY();
+ if (mx > fingerOffset) mx -= fingerOffset;
+ if (my > fingerOffset) my -= fingerOffset;
+ offset = mTextView.getOffsetForPosition(mx, my);
+
+ // Perform the check for closeness at edge of view, if we're very close
+ // don't adjust the offset to be in front of the finger - otherwise the
+ // user can't select words at the edge.
+ if (mTextView.getWidth() - fingerOffset > mx) {
+ // We're going by word, so we need to make sure that the offset
+ // that we get is within this, so we'll get the previous boundary.
+ final WordIterator wordIterator = getWordIteratorWithText();
+
+ final int precedingOffset = wordIterator.preceding(offset);
+ if (mStartOffset < offset) {
+ // Expanding with bottom handle, in this case the selection end
+ // is before the finger.
+ offset = Math.max(precedingOffset - 1, 0);
+ } else {
+ // Expand with the start handle, in this case the selection
+ // start is before the finger.
+ if (precedingOffset == WordIterator.DONE) {
+ offset = 0;
+ } else {
+ offset = wordIterator.preceding(precedingOffset);
+ }
+ }
+ }
+ if (offset == WordIterator.DONE)
+ offset = rawOffset;
+
+ // Need to adjust start offset based on direction of movement.
+ int newStart = mStartOffset < offset ? getWordStart(mStartOffset)
+ : getWordEnd(mStartOffset, true);
+ Selection.setSelection((Spannable) mTextView.getText(), newStart,
+ offset);
+ }
+ }
break;
case MotionEvent.ACTION_UP:
mPreviousTapUpTime = SystemClock.uptimeMillis();
+ if (mDragAcceleratorActive) {
+ // No longer dragging to select text, let the parent intercept events.
+ mTextView.getParent().requestDisallowInterceptTouchEvent(false);
+
+ show();
+ int startOffset = mTextView.getSelectionStart();
+ int endOffset = mTextView.getSelectionEnd();
+
+ // Since we don't let drag handles pass once they're visible, we need to
+ // make sure the start / end locations are correct because the user *can*
+ // switch directions during the initial drag.
+ if (endOffset < startOffset) {
+ int tmp = endOffset;
+ endOffset = startOffset;
+ startOffset = tmp;
+
+ // Also update the selection with the right offsets in this case.
+ Selection.setSelection((Spannable) mTextView.getText(),
+ startOffset, endOffset);
+ }
+
+ // Need to do this to display the handles.
+ mStartHandle.showAtLocation(startOffset);
+ mEndHandle.showAtLocation(endOffset);
+
+ // No longer the first dragging motion, reset.
+ mDragAcceleratorActive = false;
+ mStartOffset = -1;
+ }
break;
}
}
@@ -4010,6 +4330,8 @@
public void resetTouchOffsets() {
mMinTouchOffset = mMaxTouchOffset = -1;
+ mStartOffset = -1;
+ mDragAcceleratorActive = false;
}
/**
@@ -4019,6 +4341,13 @@
return mStartHandle != null && mStartHandle.isDragging();
}
+ /**
+ * @return true if the user is selecting text using the drag accelerator.
+ */
+ public boolean isDragAcceleratorActive() {
+ return mDragAcceleratorActive;
+ }
+
public void onTouchModeChanged(boolean isInTouchMode) {
if (!isInTouchMode) {
hide();
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index e8fe191..c748e00 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -141,7 +141,9 @@
* view was alone in a column, that column would itself collapse to zero width if and only if
* no gravity was defined on the view. If gravity was defined, then the gone-marked
* view has no effect on the layout and the container should be laid out as if the view
- * had never been added to it.
+ * had never been added to it. GONE views are taken to have zero weight during excess space
+ * distribution.
+ * <p>
* These statements apply equally to rows as well as columns, and to groups of rows or columns.
*
* <p>
@@ -1015,7 +1017,7 @@
} else {
boolean horizontal = (mOrientation == HORIZONTAL);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
- if (spec.alignment == FILL) {
+ if (spec.getAbsoluteAlignment(horizontal) == FILL) {
Interval span = spec.span;
Axis axis = horizontal ? mHorizontalAxis : mVerticalAxis;
int[] locations = axis.getLocations();
@@ -1091,11 +1093,6 @@
invalidateValues();
}
- final Alignment getAlignment(Alignment alignment, boolean horizontal) {
- return (alignment != UNDEFINED_ALIGNMENT) ? alignment :
- (horizontal ? START : BASELINE);
- }
-
// Layout container
/**
@@ -1150,8 +1147,8 @@
int pWidth = getMeasurement(c, true);
int pHeight = getMeasurement(c, false);
- Alignment hAlign = getAlignment(columnSpec.alignment, true);
- Alignment vAlign = getAlignment(rowSpec.alignment, false);
+ Alignment hAlign = columnSpec.getAbsoluteAlignment(true);
+ Alignment vAlign = rowSpec.getAbsoluteAlignment(false);
Bounds boundsX = mHorizontalAxis.getGroupBounds().getValue(i);
Bounds boundsY = mVerticalAxis.getGroupBounds().getValue(i);
@@ -1297,7 +1294,7 @@
// we must include views that are GONE here, see introductory javadoc
LayoutParams lp = getLayoutParams(c);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
- Bounds bounds = getAlignment(spec.alignment, horizontal).getBounds();
+ Bounds bounds = spec.getAbsoluteAlignment(horizontal).getBounds();
assoc.put(spec, bounds);
}
return assoc.pack();
@@ -1703,7 +1700,11 @@
private boolean computeHasWeights() {
for (int i = 0, N = getChildCount(); i < N; i++) {
- LayoutParams lp = getLayoutParams(getChildAt(i));
+ final View child = getChildAt(i);
+ if (child.getVisibility() == View.GONE) {
+ continue;
+ }
+ LayoutParams lp = getLayoutParams(child);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
if (spec.weight != 0) {
return true;
@@ -1743,7 +1744,10 @@
private void shareOutDelta(int totalDelta, float totalWeight) {
Arrays.fill(deltas, 0);
for (int i = 0, N = getChildCount(); i < N; i++) {
- View c = getChildAt(i);
+ final View c = getChildAt(i);
+ if (c.getVisibility() == View.GONE) {
+ continue;
+ }
LayoutParams lp = getLayoutParams(c);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
float weight = spec.weight;
@@ -1796,6 +1800,9 @@
float totalWeight = 0f;
for (int i = 0, N = getChildCount(); i < N; i++) {
View c = getChildAt(i);
+ if (c.getVisibility() == View.GONE) {
+ continue;
+ }
LayoutParams lp = getLayoutParams(c);
Spec spec = horizontal ? lp.columnSpec : lp.rowSpec;
totalWeight += spec.weight;
@@ -2011,7 +2018,6 @@
R.styleable.ViewGroup_MarginLayout_layout_marginRight;
private static final int BOTTOM_MARGIN =
R.styleable.ViewGroup_MarginLayout_layout_marginBottom;
-
private static final int COLUMN = R.styleable.GridLayout_Layout_layout_column;
private static final int COLUMN_SPAN = R.styleable.GridLayout_Layout_layout_columnSpan;
private static final int COLUMN_WEIGHT = R.styleable.GridLayout_Layout_layout_columnWeight;
@@ -2405,7 +2411,7 @@
protected final void include(GridLayout gl, View c, Spec spec, Axis axis, int size) {
this.flexibility &= spec.getFlexibility();
boolean horizontal = axis.horizontal;
- Alignment alignment = gl.getAlignment(spec.alignment, horizontal);
+ Alignment alignment = spec.getAbsoluteAlignment(axis.horizontal);
// todo test this works correctly when the returned value is UNDEFINED
int before = alignment.getAlignmentValue(c, size, gl.getLayoutMode());
include(before, size - before);
@@ -2556,6 +2562,16 @@
this(startDefined, new Interval(start, start + size), alignment, weight);
}
+ private Alignment getAbsoluteAlignment(boolean horizontal) {
+ if (alignment != UNDEFINED_ALIGNMENT) {
+ return alignment;
+ }
+ if (weight == 0f) {
+ return horizontal ? START : BASELINE;
+ }
+ return FILL;
+ }
+
final Spec copyWriteSpan(Interval span) {
return new Spec(startDefined, span, alignment, weight);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 632f5c7..9bef1fe 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8098,7 +8098,14 @@
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
- if (mEditor != null) mEditor.onTouchEvent(event);
+ if (mEditor != null) {
+ mEditor.onTouchEvent(event);
+
+ if (mEditor.mSelectionModifierCursorController != null &&
+ mEditor.mSelectionModifierCursorController.isDragAcceleratorActive()) {
+ return true;
+ }
+ }
final boolean superResult = super.onTouchEvent(event);
@@ -9104,7 +9111,7 @@
return getLayout().getLineForVertical((int) y);
}
- private int getOffsetAtCoordinate(int line, float x) {
+ int getOffsetAtCoordinate(int line, float x) {
x = convertToLocalHorizontalCoordinate(x);
return getLayout().getOffsetForHorizontal(line, x);
}
@@ -9726,4 +9733,4 @@
TextView.this.spanChange(buf, what, s, -1, e, -1);
}
}
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index d0c7f8c..f6c5dc7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -56,20 +56,29 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
+import android.util.Xml;
import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.JournaledFile;
+import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -94,7 +103,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 118 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 119 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -111,6 +120,7 @@
private final JournaledFile mFile;
public final AtomicFile mCheckinFile;
+ public final AtomicFile mDailyFile;
static final int MSG_UPDATE_WAKELOCKS = 1;
static final int MSG_REPORT_POWER_CHANGE = 2;
@@ -386,16 +396,22 @@
int mModStepMode = 0;
int mLastDischargeStepLevel;
- long mLastDischargeStepTime;
int mMinDischargeStepLevel;
- int mNumDischargeStepDurations;
- final long[] mDischargeStepDurations = new long[MAX_LEVEL_STEPS];
+ final LevelStepTracker mDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
+ final LevelStepTracker mDailyDischargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
int mLastChargeStepLevel;
- long mLastChargeStepTime;
int mMaxChargeStepLevel;
- int mNumChargeStepDurations;
- final long[] mChargeStepDurations = new long[MAX_LEVEL_STEPS];
+ final LevelStepTracker mChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS);
+ final LevelStepTracker mDailyChargeStepTracker = new LevelStepTracker(MAX_LEVEL_STEPS*2);
+
+ static final int MAX_DAILY_ITEMS = 10;
+
+ long mDailyStartTime = 0;
+ long mNextMinDailyDeadline = 0;
+ long mNextMaxDailyDeadline = 0;
+
+ final ArrayList<DailyItem> mDailyItems = new ArrayList<>();
long mLastWriteTime = 0; // Milliseconds
@@ -478,6 +494,7 @@
public BatteryStatsImpl() {
mFile = null;
mCheckinFile = null;
+ mDailyFile = null;
mHandler = null;
clearHistoryLocked();
}
@@ -3199,6 +3216,7 @@
public void noteScreenStateLocked(int state) {
if (mScreenState != state) {
+ recordDailyStatsIfNeededLocked(true);
final int oldState = mScreenState;
mScreenState = state;
if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
@@ -6594,6 +6612,7 @@
mFile = null;
}
mCheckinFile = new AtomicFile(new File(systemDir, "batterystats-checkin.bin"));
+ mDailyFile = new AtomicFile(new File(systemDir, "batterystats-daily.xml"));
mHandler = new MyHandler(handler.getLooper());
mStartCount++;
mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase);
@@ -6652,11 +6671,13 @@
mCurrentBatteryLevel = 0;
initDischarge();
clearHistoryLocked();
+ updateDailyDeadlineLocked();
}
public BatteryStatsImpl(Parcel p) {
mFile = null;
mCheckinFile = null;
+ mDailyFile = null;
mHandler = null;
clearHistoryLocked();
readFromParcel(p);
@@ -6676,6 +6697,286 @@
}
}
+ public void updateDailyDeadlineLocked() {
+ // Get the current time.
+ long currentTime = mDailyStartTime = System.currentTimeMillis();
+ Calendar calDeadline = Calendar.getInstance();
+ calDeadline.setTimeInMillis(currentTime);
+
+ // Move time up to the next day, ranging from 1am to 3pm.
+ calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1);
+ calDeadline.set(Calendar.MILLISECOND, 0);
+ calDeadline.set(Calendar.SECOND, 0);
+ calDeadline.set(Calendar.MINUTE, 0);
+ calDeadline.set(Calendar.HOUR_OF_DAY, 1);
+ mNextMinDailyDeadline = calDeadline.getTimeInMillis();
+ calDeadline.set(Calendar.HOUR_OF_DAY, 3);
+ mNextMaxDailyDeadline = calDeadline.getTimeInMillis();
+ }
+
+ public void recordDailyStatsIfNeededLocked(boolean settled) {
+ long currentTime = System.currentTimeMillis();
+ if (currentTime >= mNextMaxDailyDeadline) {
+ recordDailyStatsLocked();
+ } else if (settled && currentTime >= mNextMinDailyDeadline) {
+ recordDailyStatsLocked();
+ } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) {
+ recordDailyStatsLocked();
+ }
+ }
+
+ public void recordDailyStatsLocked() {
+ DailyItem item = new DailyItem();
+ item.mStartTime = mDailyStartTime;
+ item.mEndTime = System.currentTimeMillis();
+ boolean hasData = false;
+ if (mDailyDischargeStepTracker.mNumStepDurations > 0) {
+ hasData = true;
+ item.mDischargeSteps = new LevelStepTracker(
+ mDailyDischargeStepTracker.mNumStepDurations,
+ mDailyDischargeStepTracker.mStepDurations);
+ }
+ if (mDailyChargeStepTracker.mNumStepDurations > 0) {
+ hasData = true;
+ item.mChargeSteps = new LevelStepTracker(
+ mDailyChargeStepTracker.mNumStepDurations,
+ mDailyChargeStepTracker.mStepDurations);
+ }
+ mDailyDischargeStepTracker.init();
+ mDailyChargeStepTracker.init();
+ updateDailyDeadlineLocked();
+
+ if (hasData) {
+ mDailyItems.add(item);
+ while (mDailyItems.size() > MAX_DAILY_ITEMS) {
+ mDailyItems.remove(0);
+ }
+ final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
+ try {
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(memStream, "utf-8");
+ writeDailyItemsLocked(out);
+ BackgroundThread.getHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mCheckinFile) {
+ FileOutputStream stream = null;
+ try {
+ stream = mDailyFile.startWrite();
+ memStream.writeTo(stream);
+ stream.flush();
+ FileUtils.sync(stream);
+ stream.close();
+ mDailyFile.finishWrite(stream);
+ } catch (IOException e) {
+ Slog.w("BatteryStats",
+ "Error writing battery daily items", e);
+ mDailyFile.failWrite(stream);
+ }
+ }
+ }
+ });
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ private void writeDailyItemsLocked(XmlSerializer out) throws IOException {
+ StringBuilder sb = new StringBuilder(64);
+ out.startDocument(null, true);
+ out.startTag(null, "daily-items");
+ for (int i=0; i<mDailyItems.size(); i++) {
+ final DailyItem dit = mDailyItems.get(i);
+ out.startTag(null, "item");
+ out.attribute(null, "start", Long.toString(dit.mStartTime));
+ out.attribute(null, "end", Long.toString(dit.mEndTime));
+ writeDailyLevelSteps(out, "dis", dit.mDischargeSteps, sb);
+ writeDailyLevelSteps(out, "chg", dit.mChargeSteps, sb);
+ out.endTag(null, "item");
+ }
+ out.endTag(null, "daily-items");
+ out.endDocument();
+ }
+
+ private void writeDailyLevelSteps(XmlSerializer out, String tag, LevelStepTracker steps,
+ StringBuilder tmpBuilder) throws IOException {
+ if (steps != null) {
+ out.startTag(null, tag);
+ out.attribute(null, "n", Integer.toString(steps.mNumStepDurations));
+ for (int i=0; i<steps.mNumStepDurations; i++) {
+ out.startTag(null, "s");
+ tmpBuilder.setLength(0);
+ steps.encodeEntryAt(i, tmpBuilder);
+ out.attribute(null, "v", tmpBuilder.toString());
+ out.endTag(null, "s");
+ }
+ out.endTag(null, tag);
+ }
+ }
+
+ public void readDailyStatsLocked() {
+ Slog.d(TAG, "Reading daily items from " + mDailyFile.getBaseFile());
+ mDailyItems.clear();
+ FileInputStream stream;
+ try {
+ stream = mDailyFile.openRead();
+ } catch (FileNotFoundException e) {
+ return;
+ }
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, null);
+ readDailyItemsLocked(parser);
+ } catch (XmlPullParserException e) {
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+
+ private void readDailyItemsLocked(XmlPullParser parser) {
+ try {
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ ;
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new IllegalStateException("no start tag found");
+ }
+
+ 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("item")) {
+ readDailyItemTagLocked(parser);
+ } else {
+ Slog.w(TAG, "Unknown element under <daily-items>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+
+ } catch (IllegalStateException e) {
+ Slog.w(TAG, "Failed parsing daily " + e);
+ } catch (NullPointerException e) {
+ Slog.w(TAG, "Failed parsing daily " + e);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Failed parsing daily " + e);
+ } catch (XmlPullParserException e) {
+ Slog.w(TAG, "Failed parsing daily " + e);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed parsing daily " + e);
+ } catch (IndexOutOfBoundsException e) {
+ Slog.w(TAG, "Failed parsing daily " + e);
+ }
+ }
+
+ void readDailyItemTagLocked(XmlPullParser parser) throws NumberFormatException,
+ XmlPullParserException, IOException {
+ DailyItem dit = new DailyItem();
+ String attr = parser.getAttributeValue(null, "start");
+ if (attr != null) {
+ dit.mStartTime = Long.parseLong(attr);
+ }
+ attr = parser.getAttributeValue(null, "end");
+ if (attr != null) {
+ dit.mEndTime = Long.parseLong(attr);
+ }
+ int outerDepth = parser.getDepth();
+ int type;
+ 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("dis")) {
+ readDailyItemTagDetailsLocked(parser, dit, false, "dis");
+ } else if (tagName.equals("chg")) {
+ readDailyItemTagDetailsLocked(parser, dit, true, "chg");
+ } else {
+ Slog.w(TAG, "Unknown element under <item>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ mDailyItems.add(dit);
+ }
+
+ void readDailyItemTagDetailsLocked(XmlPullParser parser, DailyItem dit, boolean isCharge,
+ String tag)
+ throws NumberFormatException, XmlPullParserException, IOException {
+ final String numAttr = parser.getAttributeValue(null, "n");
+ if (numAttr == null) {
+ Slog.w(TAG, "Missing 'n' attribute at " + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ return;
+ }
+ final int num = Integer.parseInt(numAttr);
+ LevelStepTracker steps = new LevelStepTracker(num);
+ if (isCharge) {
+ dit.mChargeSteps = steps;
+ } else {
+ dit.mDischargeSteps = steps;
+ }
+ int i = 0;
+ int outerDepth = parser.getDepth();
+ int type;
+ 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 ("s".equals(tagName)) {
+ if (i < num) {
+ String valueAttr = parser.getAttributeValue(null, "v");
+ if (valueAttr != null) {
+ steps.decodeEntryAt(i, valueAttr);
+ i++;
+ }
+ }
+ } else {
+ Slog.w(TAG, "Unknown element under <" + tag + ">: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ steps.mNumStepDurations = i;
+ }
+
+ @Override
+ public DailyItem getDailyItemLocked(int daysAgo) {
+ int index = mDailyItems.size()-1-daysAgo;
+ return index >= 0 ? mDailyItems.get(index) : null;
+ }
+
+ @Override
+ public long getCurrentDailyStartTime() {
+ return mDailyStartTime;
+ }
+
+ @Override
+ public long getNextMinDailyDeadline() {
+ return mNextMinDailyDeadline;
+ }
+
+ @Override
+ public long getNextMaxDailyDeadline() {
+ return mNextMaxDailyDeadline;
+ }
+
@Override
public boolean startIteratingOldHistoryLocked() {
if (DEBUG_HISTORY) Slog.i(TAG, "ITERATING: buff size=" + mHistoryBuffer.dataSize()
@@ -6846,10 +7147,8 @@
mDischargeAmountScreenOnSinceCharge = 0;
mDischargeAmountScreenOff = 0;
mDischargeAmountScreenOffSinceCharge = 0;
- mLastDischargeStepTime = -1;
- mNumDischargeStepDurations = 0;
- mLastChargeStepTime = -1;
- mNumChargeStepDurations = 0;
+ mDischargeStepTracker.init();
+ mChargeStepTracker.init();
}
public void resetAllStatsCmdLocked() {
@@ -7072,12 +7371,13 @@
resetAllStatsLocked();
mDischargeStartLevel = level;
reset = true;
- mNumDischargeStepDurations = 0;
+ mDischargeStepTracker.init();
}
mOnBattery = mOnBatteryInternal = true;
mLastDischargeStepLevel = level;
mMinDischargeStepLevel = level;
- mLastDischargeStepTime = -1;
+ mDischargeStepTracker.clearTime();
+ mDailyDischargeStepTracker.clearTime();
mInitStepMode = mCurStepMode;
mModStepMode = 0;
pullPendingStateUpdatesLocked();
@@ -7116,10 +7416,9 @@
}
updateDischargeScreenLevelsLocked(screenOn, screenOn);
updateTimeBasesLocked(false, !screenOn, uptime, realtime);
- mNumChargeStepDurations = 0;
+ mChargeStepTracker.init();
mLastChargeStepLevel = level;
mMaxChargeStepLevel = level;
- mLastChargeStepTime = -1;
mInitStepMode = mCurStepMode;
mModStepMode = 0;
}
@@ -7171,34 +7470,12 @@
// This should probably be exposed in the API, though it's not critical
private static final int BATTERY_PLUGGED_NONE = 0;
- private static int addLevelSteps(long[] steps, int stepCount, long lastStepTime,
- int numStepLevels, long modeBits, long elapsedRealtime) {
- if (lastStepTime >= 0 && numStepLevels > 0) {
- long duration = elapsedRealtime - lastStepTime;
- for (int i=0; i<numStepLevels; i++) {
- System.arraycopy(steps, 0, steps, 1, steps.length-1);
- long thisDuration = duration / (numStepLevels-i);
- duration -= thisDuration;
- if (thisDuration > STEP_LEVEL_TIME_MASK) {
- thisDuration = STEP_LEVEL_TIME_MASK;
- }
- steps[0] = thisDuration | modeBits;
- }
- stepCount += numStepLevels;
- if (stepCount > steps.length) {
- stepCount = steps.length;
- }
- }
- return stepCount;
- }
-
public void setBatteryState(int status, int health, int plugType, int level,
int temp, int volt) {
synchronized(this) {
final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
final long uptime = SystemClock.uptimeMillis();
final long elapsedRealtime = SystemClock.elapsedRealtime();
- int oldStatus = mHistoryCur.batteryStatus;
if (!mHaveBatteryLevel) {
mHaveBatteryLevel = true;
// We start out assuming that the device is plugged in (not
@@ -7212,8 +7489,14 @@
mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
}
}
- oldStatus = status;
+ mHistoryCur.batteryStatus = (byte)status;
+ mHistoryCur.batteryLevel = (byte)level;
+ mMaxChargeStepLevel = mMinDischargeStepLevel =
+ mLastChargeStepLevel = mLastDischargeStepLevel = level;
+ } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) {
+ recordDailyStatsIfNeededLocked(level >= 100 && onBattery);
}
+ int oldStatus = mHistoryCur.batteryStatus;
if (onBattery) {
mDischargeCurrentLevel = level;
if (!mRecordingHistory) {
@@ -7274,23 +7557,23 @@
| (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
if (onBattery) {
if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) {
- mNumDischargeStepDurations = addLevelSteps(mDischargeStepDurations,
- mNumDischargeStepDurations, mLastDischargeStepTime,
- mLastDischargeStepLevel - level, modeBits, elapsedRealtime);
+ mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
+ modeBits, elapsedRealtime);
+ mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level,
+ modeBits, elapsedRealtime);
mLastDischargeStepLevel = level;
mMinDischargeStepLevel = level;
- mLastDischargeStepTime = elapsedRealtime;
mInitStepMode = mCurStepMode;
mModStepMode = 0;
}
} else {
if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) {
- mNumChargeStepDurations = addLevelSteps(mChargeStepDurations,
- mNumChargeStepDurations, mLastChargeStepTime,
- level - mLastChargeStepLevel, modeBits, elapsedRealtime);
+ mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
+ modeBits, elapsedRealtime);
+ mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel,
+ modeBits, elapsedRealtime);
mLastChargeStepLevel = level;
mMaxChargeStepLevel = level;
- mLastChargeStepTime = elapsedRealtime;
mInitStepMode = mCurStepMode;
mModStepMode = 0;
}
@@ -7565,22 +7848,24 @@
long usPerLevel = duration/discharge;
return usPerLevel * mCurrentBatteryLevel;
*/
- if (mNumDischargeStepDurations < 1) {
+ if (mDischargeStepTracker.mNumStepDurations < 1) {
return -1;
}
- long msPerLevel = computeTimePerLevel(mDischargeStepDurations, mNumDischargeStepDurations);
+ long msPerLevel = mDischargeStepTracker.computeTimePerLevel();
if (msPerLevel <= 0) {
return -1;
}
return (msPerLevel * mCurrentBatteryLevel) * 1000;
}
- public int getNumDischargeStepDurations() {
- return mNumDischargeStepDurations;
+ @Override
+ public LevelStepTracker getDischargeLevelStepTracker() {
+ return mDischargeStepTracker;
}
- public long[] getDischargeStepDurationsArray() {
- return mDischargeStepDurations;
+ @Override
+ public LevelStepTracker getDailyDischargeLevelStepTracker() {
+ return mDailyDischargeStepTracker;
}
@Override
@@ -7602,22 +7887,24 @@
long usPerLevel = duration/(curLevel-plugLevel);
return usPerLevel * (100-curLevel);
*/
- if (mNumChargeStepDurations < 1) {
+ if (mChargeStepTracker.mNumStepDurations < 1) {
return -1;
}
- long msPerLevel = computeTimePerLevel(mChargeStepDurations, mNumChargeStepDurations);
+ long msPerLevel = mChargeStepTracker.computeTimePerLevel();
if (msPerLevel <= 0) {
return -1;
}
return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
}
- public int getNumChargeStepDurations() {
- return mNumChargeStepDurations;
+ @Override
+ public LevelStepTracker getChargeLevelStepTracker() {
+ return mChargeStepTracker;
}
- public long[] getChargeStepDurationsArray() {
- return mChargeStepDurations;
+ @Override
+ public LevelStepTracker getDailyChargeLevelStepTracker() {
+ return mDailyChargeStepTracker;
}
long getBatteryUptimeLocked() {
@@ -7915,6 +8202,10 @@
}
public void readLocked() {
+ if (mDailyFile != null) {
+ readDailyStatsLocked();
+ }
+
if (mFile == null) {
Slog.w("BatteryStats", "readLocked: no file associated with this instance");
return;
@@ -7952,6 +8243,8 @@
addHistoryBufferLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur);
startRecordingHistory(elapsedRealtime, uptime, false);
}
+
+ recordDailyStatsIfNeededLocked(false);
}
public int describeContents() {
@@ -8110,10 +8403,13 @@
mHighDischargeAmountSinceCharge = in.readInt();
mDischargeAmountScreenOnSinceCharge = in.readInt();
mDischargeAmountScreenOffSinceCharge = in.readInt();
- mNumDischargeStepDurations = in.readInt();
- in.readLongArray(mDischargeStepDurations);
- mNumChargeStepDurations = in.readInt();
- in.readLongArray(mChargeStepDurations);
+ mDischargeStepTracker.readFromParcel(in);
+ mChargeStepTracker.readFromParcel(in);
+ mDailyDischargeStepTracker.readFromParcel(in);
+ mDailyChargeStepTracker.readFromParcel(in);
+ mDailyStartTime = in.readLong();
+ mNextMinDailyDeadline = in.readLong();
+ mNextMaxDailyDeadline = in.readLong();
mStartCount++;
@@ -8404,10 +8700,13 @@
out.writeInt(getHighDischargeAmountSinceCharge());
out.writeInt(getDischargeAmountScreenOnSinceCharge());
out.writeInt(getDischargeAmountScreenOffSinceCharge());
- out.writeInt(mNumDischargeStepDurations);
- out.writeLongArray(mDischargeStepDurations);
- out.writeInt(mNumChargeStepDurations);
- out.writeLongArray(mChargeStepDurations);
+ mDischargeStepTracker.writeToParcel(out);
+ mChargeStepTracker.writeToParcel(out);
+ mDailyDischargeStepTracker.writeToParcel(out);
+ mDailyChargeStepTracker.writeToParcel(out);
+ out.writeLong(mDailyStartTime);
+ out.writeLong(mNextMinDailyDeadline);
+ out.writeLong(mNextMaxDailyDeadline);
mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
@@ -8770,10 +9069,8 @@
mDischargeAmountScreenOnSinceCharge = in.readInt();
mDischargeAmountScreenOff = in.readInt();
mDischargeAmountScreenOffSinceCharge = in.readInt();
- mNumDischargeStepDurations = in.readInt();
- in.readLongArray(mDischargeStepDurations);
- mNumChargeStepDurations = in.readInt();
- in.readLongArray(mChargeStepDurations);
+ mDischargeStepTracker.readFromParcel(in);
+ mChargeStepTracker.readFromParcel(in);
mLastWriteTime = in.readLong();
mBluetoothPingCount = in.readInt();
@@ -8912,10 +9209,8 @@
out.writeInt(mDischargeAmountScreenOnSinceCharge);
out.writeInt(mDischargeAmountScreenOff);
out.writeInt(mDischargeAmountScreenOffSinceCharge);
- out.writeInt(mNumDischargeStepDurations);
- out.writeLongArray(mDischargeStepDurations);
- out.writeInt(mNumChargeStepDurations);
- out.writeLongArray(mChargeStepDurations);
+ mDischargeStepTracker.writeToParcel(out);
+ mChargeStepTracker.writeToParcel(out);
out.writeLong(mLastWriteTime);
out.writeInt(getBluetoothPingCount());
diff --git a/core/java/com/android/internal/transition/EpicenterClipReveal.java b/core/java/com/android/internal/transition/EpicenterClipReveal.java
index d8a7f16..abb50c1 100644
--- a/core/java/com/android/internal/transition/EpicenterClipReveal.java
+++ b/core/java/com/android/internal/transition/EpicenterClipReveal.java
@@ -16,6 +16,7 @@
package com.android.internal.transition;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.RectEvaluator;
import android.content.Context;
@@ -75,13 +76,13 @@
return null;
}
- final Rect start = getEpicenter();
final Rect end = getBestRect(endValues);
+ final Rect start = getEpicenterOrCenter(end);
// Prepare the view.
view.setClipBounds(start);
- return createRectAnimator(view, start, end);
+ return createRectAnimator(view, start, end, endValues);
}
@Override
@@ -92,12 +93,23 @@
}
final Rect start = getBestRect(startValues);
- final Rect end = getEpicenter();
+ final Rect end = getEpicenterOrCenter(start);
// Prepare the view.
view.setClipBounds(start);
- return createRectAnimator(view, start, end);
+ return createRectAnimator(view, start, end, endValues);
+ }
+
+ private Rect getEpicenterOrCenter(Rect bestRect) {
+ final Rect epicenter = getEpicenter();
+ if (epicenter != null) {
+ return epicenter;
+ }
+
+ int centerX = bestRect.centerX();
+ int centerY = bestRect.centerY();
+ return new Rect(centerX, centerY, centerX, centerY);
}
private Rect getBestRect(TransitionValues values) {
@@ -108,8 +120,17 @@
return clipRect;
}
- private Animator createRectAnimator(View view, Rect start, Rect end) {
+ private Animator createRectAnimator(final View view, Rect start, Rect end,
+ TransitionValues endValues) {
+ final Rect terminalClip = (Rect) endValues.values.get(PROPNAME_CLIP);
final RectEvaluator evaluator = new RectEvaluator(new Rect());
- return ObjectAnimator.ofObject(view, "clipBounds", evaluator, start, end);
+ ObjectAnimator anim = ObjectAnimator.ofObject(view, "clipBounds", evaluator, start, end);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ view.setClipBounds(terminalClip);
+ }
+ });
+ return anim;
}
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 28f1a3a..97744ea 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -147,7 +147,7 @@
android_hardware_location_ActivityRecognitionHardware.cpp \
android_util_FileObserver.cpp \
android/opengl/poly_clip.cpp.arm \
- android/opengl/util.cpp.arm \
+ android/opengl/util.cpp \
android_server_FingerprintManager.cpp \
android_server_NetworkManagementSocketTagger.cpp \
android_server_Watchdog.cpp \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 672008d..6a50b52 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -41,7 +41,6 @@
jfieldID gOptions_mCancelID;
jfieldID gOptions_bitmapFieldID;
-jfieldID gBitmap_nativeBitmapFieldID;
jfieldID gBitmap_ninePatchInsetsFieldID;
jclass gInsetStruct_class;
@@ -262,7 +261,7 @@
SkBitmap* outputBitmap = NULL;
unsigned int existingBufferSize = 0;
if (javaBitmap != NULL) {
- outputBitmap = (SkBitmap*) env->GetLongField(javaBitmap, gBitmap_nativeBitmapFieldID);
+ outputBitmap = GraphicsJNI::getSkBitmap(env, javaBitmap);
if (outputBitmap->isImmutable()) {
ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
javaBitmap = NULL;
@@ -601,7 +600,6 @@
gOptions_mCancelID = GetFieldIDOrDie(env, options_class, "mCancel", "Z");
jclass bitmap_class = FindClassOrDie(env, "android/graphics/Bitmap");
- gBitmap_nativeBitmapFieldID = GetFieldIDOrDie(env, bitmap_class, "mNativeBitmap", "J");
gBitmap_ninePatchInsetsFieldID = GetFieldIDOrDie(env, bitmap_class, "mNinePatchInsets",
"Landroid/graphics/NinePatch$InsetStruct;");
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 90a7f69..04afe3e 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -213,7 +213,7 @@
if (tileBitmap != NULL) {
// Re-use bitmap.
- bitmap = GraphicsJNI::getNativeBitmap(env, tileBitmap);
+ bitmap = GraphicsJNI::getSkBitmap(env, tileBitmap);
}
if (bitmap == NULL) {
bitmap = new SkBitmap;
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 026cbee..d03bcf0 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -21,7 +21,7 @@
#include "SkColorFilter.h"
#include "SkColorMatrixFilter.h"
-#include "SkPorterDuff.h"
+#include "SkXfermode.h"
#include <Caches.h>
@@ -36,10 +36,9 @@
if (filter) SkSafeUnref(filter);
}
- static jlong CreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor,
- jint modeHandle) {
- SkPorterDuff::Mode mode = (SkPorterDuff::Mode) modeHandle;
- return reinterpret_cast<jlong>(SkColorFilter::CreateModeFilter(srcColor, SkPorterDuff::ToXfermodeMode(mode)));
+ static jlong CreatePorterDuffFilter(JNIEnv* env, jobject, jint srcColor, jint modeHandle) {
+ SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
+ return reinterpret_cast<jlong>(SkColorFilter::CreateModeFilter(srcColor, mode));
}
static jlong CreateLightingFilter(JNIEnv* env, jobject, jint mul, jint add) {
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index dde1393..0747969 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -154,7 +154,7 @@
static jfieldID gPointF_yFieldID;
static jclass gBitmap_class;
-static jfieldID gBitmap_nativeInstanceID;
+static jfieldID gBitmap_skBitmapPtr;
static jmethodID gBitmap_constructorMethodID;
static jmethodID gBitmap_reinitMethodID;
static jmethodID gBitmap_getAllocationByteCountMethodID;
@@ -338,11 +338,11 @@
return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
}
-SkBitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
+SkBitmap* GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap) {
SkASSERT(env);
SkASSERT(bitmap);
SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
- jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativeInstanceID);
+ jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_skBitmapPtr);
SkBitmap* b = reinterpret_cast<SkBitmap*>(bitmapHandle);
SkASSERT(b);
return b;
@@ -676,7 +676,7 @@
gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F");
gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
- gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "J");
+ gBitmap_skBitmapPtr = getFieldIDCheck(env, gBitmap_class, "mSkBitmapPtr", "J");
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");
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index a202c38..422d3f1 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -48,7 +48,7 @@
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas);
- static SkBitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
+ static SkBitmap* getSkBitmap(JNIEnv*, jobject bitmap);
static SkRegion* getNativeRegion(JNIEnv*, jobject region);
// Given the 'native' long held by the Rasterizer.java object, return a
diff --git a/core/jni/android/graphics/PorterDuff.cpp b/core/jni/android/graphics/PorterDuff.cpp
index 73b1691..d65864d 100644
--- a/core/jni/android/graphics/PorterDuff.cpp
+++ b/core/jni/android/graphics/PorterDuff.cpp
@@ -24,7 +24,7 @@
#include "GraphicsJNI.h"
#include "core_jni_helpers.h"
-#include "SkPorterDuff.h"
+#include "SkXfermode.h"
namespace android {
@@ -32,8 +32,28 @@
public:
static jlong CreateXfermode(JNIEnv* env, jobject, jint modeHandle) {
- SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
- return reinterpret_cast<jlong>(SkPorterDuff::CreateXfermode(mode));
+ // validate that the Java enum values match our expectations
+ SK_COMPILE_ASSERT(0 == SkXfermode::kClear_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(1 == SkXfermode::kSrc_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(2 == SkXfermode::kDst_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(3 == SkXfermode::kSrcOver_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(4 == SkXfermode::kDstOver_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(5 == SkXfermode::kSrcIn_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(6 == SkXfermode::kDstIn_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(7 == SkXfermode::kSrcOut_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(8 == SkXfermode::kDstOut_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(9 == SkXfermode::kSrcATop_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(10 == SkXfermode::kDstATop_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(11 == SkXfermode::kXor_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(16 == SkXfermode::kDarken_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(17 == SkXfermode::kLighten_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(13 == SkXfermode::kModulate_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(14 == SkXfermode::kScreen_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(12 == SkXfermode::kPlus_Mode, xfermode_mismatch);
+ SK_COMPILE_ASSERT(15 == SkXfermode::kOverlay_Mode, xfermode_mismatch);
+
+ SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
+ return reinterpret_cast<jlong>(SkXfermode::Create(mode));
}
};
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index 3f47a72..6591d29 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -3,7 +3,6 @@
#include "SkShader.h"
#include "SkGradientShader.h"
-#include "SkPorterDuff.h"
#include "SkComposeShader.h"
#include "SkTemplates.h"
#include "SkXfermode.h"
@@ -227,14 +226,13 @@
}
static jlong ComposeShader_create2(JNIEnv* env, jobject o,
- jlong shaderAHandle, jlong shaderBHandle, jint porterDuffModeHandle)
+ jlong shaderAHandle, jlong shaderBHandle, jint xfermodeHandle)
{
SkShader* shaderA = reinterpret_cast<SkShader *>(shaderAHandle);
SkShader* shaderB = reinterpret_cast<SkShader *>(shaderBHandle);
- SkPorterDuff::Mode porterDuffMode = static_cast<SkPorterDuff::Mode>(porterDuffModeHandle);
- SkAutoUnref au(SkPorterDuff::CreateXfermode(porterDuffMode));
- SkXfermode* mode = (SkXfermode*) au.get();
- SkShader* shader = new SkComposeShader(shaderA, shaderB, mode);
+ SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(xfermodeHandle);
+ SkAutoTUnref<SkXfermode> xfermode(SkXfermode::Create(mode));
+ SkShader* shader = new SkComposeShader(shaderA, shaderB, xfermode.get());
return reinterpret_cast<jlong>(shader);
}
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 461507f..5c2d0d0 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -16,6 +16,7 @@
#include "jni.h"
#include "JNIHelp.h"
+#include "GraphicsJNI.h"
#include <math.h>
#include <stdio.h>
@@ -149,10 +150,6 @@
return result;
}
-static void doThrowIAE(JNIEnv* env, const char* msg) {
- jniThrowException(env, "java/lang/IllegalArgumentException", msg);
-}
-
template<class JArray, class T>
class ArrayHelper {
public:
@@ -548,14 +545,6 @@
// ---------------------------------------------------------------------------
-static jfieldID nativeBitmapID = 0;
-
-void nativeUtilsClassInit(JNIEnv *env, jclass clazz)
-{
- jclass bitmapClass = env->FindClass("android/graphics/Bitmap");
- nativeBitmapID = env->GetFieldID(bitmapClass, "mNativeBitmap", "J");
-}
-
extern void setGLDebugLevel(int level);
void setTracingLevel(JNIEnv *env, jclass clazz, jint level)
{
@@ -629,16 +618,14 @@
static jint util_getInternalFormat(JNIEnv *env, jclass clazz,
jobject jbitmap)
{
- SkBitmap const * nativeBitmap =
- (SkBitmap const *)env->GetLongField(jbitmap, nativeBitmapID);
+ SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
return getInternalFormat(nativeBitmap->colorType());
}
static jint util_getType(JNIEnv *env, jclass clazz,
jobject jbitmap)
{
- SkBitmap const * nativeBitmap =
- (SkBitmap const *)env->GetLongField(jbitmap, nativeBitmapID);
+ SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
return getType(nativeBitmap->colorType());
}
@@ -646,8 +633,7 @@
jint target, jint level, jint internalformat,
jobject jbitmap, jint type, jint border)
{
- SkBitmap const * nativeBitmap =
- (SkBitmap const *)env->GetLongField(jbitmap, nativeBitmapID);
+ SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
const SkBitmap& bitmap(*nativeBitmap);
SkColorType colorType = bitmap.colorType();
if (internalformat < 0) {
@@ -694,8 +680,7 @@
jint target, jint level, jint xoffset, jint yoffset,
jobject jbitmap, jint format, jint type)
{
- SkBitmap const * nativeBitmap =
- (SkBitmap const *)env->GetLongField(jbitmap, nativeBitmapID);
+ SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(env, jbitmap);
const SkBitmap& bitmap(*nativeBitmap);
SkColorType colorType = bitmap.colorType();
if (format < 0) {
@@ -1014,7 +999,6 @@
};
static JNINativeMethod gUtilsMethods[] = {
- {"nativeClassInit", "()V", (void*)nativeUtilsClassInit },
{ "native_getInternalFormat", "(Landroid/graphics/Bitmap;)I", (void*) util_getInternalFormat },
{ "native_getType", "(Landroid/graphics/Bitmap;)I", (void*) util_getType },
{ "native_texImage2D", "(IIILandroid/graphics/Bitmap;II)I", (void*)util_texImage2D },
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 7d5ca8d..c337a9f 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -21,7 +21,6 @@
#include <Canvas.h>
#include "SkDrawFilter.h"
#include "SkGraphics.h"
-#include "SkPorterDuff.h"
#include "Paint.h"
#include "TypefaceImpl.h"
@@ -186,8 +185,8 @@
}
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));
+ SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle);
+ get_canvas(canvasHandle)->drawColor(color, mode);
}
static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index db73e69d..a6f19b1 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -29,6 +29,7 @@
#include <list>
#include <algorithm>
+
namespace android {
struct JLineBreaksID {
@@ -40,6 +41,53 @@
static jclass gLineBreaks_class;
static JLineBreaksID gLineBreaks_fieldID;
+class Builder {
+ public:
+ ~Builder() {
+ utext_close(&mUText);
+ delete mBreakIterator;
+ }
+
+ void setLocale(const Locale& locale) {
+ delete mBreakIterator;
+ UErrorCode status = U_ZERO_ERROR;
+ mBreakIterator = BreakIterator::createLineInstance(locale, status);
+ // TODO: check status
+ }
+
+ void resize(size_t size) {
+ mTextBuf.resize(size);
+ }
+
+ uint16_t* buffer() {
+ return mTextBuf.data();
+ }
+
+ // set text to current contents of buffer
+ void setText() {
+ UErrorCode status = U_ZERO_ERROR;
+ utext_openUChars(&mUText, mTextBuf.data(), mTextBuf.size(), &status);
+ mBreakIterator->setText(&mUText, status);
+ }
+
+ void finish() {
+ if (mTextBuf.size() > MAX_TEXT_BUF_RETAIN) {
+ mTextBuf.clear();
+ mTextBuf.shrink_to_fit();
+ }
+ }
+
+ BreakIterator* breakIterator() const {
+ return mBreakIterator;
+ }
+
+ private:
+ const size_t MAX_TEXT_BUF_RETAIN = 32678;
+ BreakIterator* mBreakIterator = nullptr;
+ UText mUText = UTEXT_INITIALIZER;
+ std::vector<uint16_t>mTextBuf;
+};
+
static const int CHAR_SPACE = 0x20;
static const int CHAR_TAB = 0x09;
static const int CHAR_NEWLINE = 0x0a;
@@ -50,7 +98,7 @@
// specified stops must be a sorted array (allowed to be null)
TabStops(JNIEnv* env, jintArray stops, jint defaultTabWidth) :
mStops(env), mTabWidth(defaultTabWidth) {
- if (stops != NULL) {
+ if (stops != nullptr) {
mStops.reset(stops);
mNumStops = mStops.size();
} else {
@@ -430,37 +478,6 @@
}
};
-class ScopedBreakIterator {
- public:
- ScopedBreakIterator(JNIEnv* env, BreakIterator* breakIterator, const jchar* inputText,
- jint length) : mBreakIterator(breakIterator), mChars(inputText) {
- UErrorCode status = U_ZERO_ERROR;
- mUText = utext_openUChars(NULL, mChars, length, &status);
- if (mUText == NULL) {
- return;
- }
-
- mBreakIterator->setText(mUText, status);
- }
-
- inline BreakIterator* operator->() {
- return mBreakIterator;
- }
-
- ~ScopedBreakIterator() {
- utext_close(mUText);
- delete mBreakIterator;
- }
- private:
- BreakIterator* mBreakIterator;
- const jchar* mChars;
- UText* mUText;
-
- // disable copying and assignment
- ScopedBreakIterator(const ScopedBreakIterator&);
- void operator=(const ScopedBreakIterator&);
-};
-
static jint recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,
jfloatArray recycleWidths, jbooleanArray recycleFlags,
jint recycleLength, const std::vector<jint>& breaks,
@@ -526,7 +543,7 @@
primitives->push_back(p);
}
-static jint nComputeLineBreaks(JNIEnv* env, jclass, jstring javaLocaleName,
+static jint nComputeLineBreaks(JNIEnv* env, jclass, jlong nativePtr,
jcharArray inputText, jfloatArray widths, jint length,
jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth,
jintArray variableTabStops, jint defaultTabStop, jboolean optimize,
@@ -535,29 +552,24 @@
jint recycleLength) {
std::vector<int> breaks;
- ScopedCharArrayRO textScopedArr(env, inputText);
+ Builder* b = reinterpret_cast<Builder*>(nativePtr);
+ b->resize(length);
+ env->GetCharArrayRegion(inputText, 0, length, b->buffer());
+ b->setText();
+
+ // TODO: this array access is pretty inefficient, but we'll replace it anyway
ScopedFloatArrayRO widthsScopedArr(env, widths);
- ScopedIcuLocale icuLocale(env, javaLocaleName);
- if (icuLocale.valid()) {
- UErrorCode status = U_ZERO_ERROR;
- BreakIterator* it = BreakIterator::createLineInstance(icuLocale.locale(), status);
- if (!U_SUCCESS(status) || it == NULL) {
- if (it) {
- delete it;
- }
- } else {
- ScopedBreakIterator breakIterator(env, it, textScopedArr.get(), length);
- int loc = breakIterator->first();
- while ((loc = breakIterator->next()) != BreakIterator::DONE) {
- breaks.push_back(loc);
- }
- }
+ BreakIterator* breakIterator = b->breakIterator();
+ int loc = breakIterator->first();
+ while ((loc = breakIterator->next()) != BreakIterator::DONE) {
+ breaks.push_back(loc);
}
+ // TODO: all these allocations can be moved into the builder
std::vector<Primitive> primitives;
TabStops tabStops(env, variableTabStops, defaultTabStop);
- computePrimitives(textScopedArr.get(), widthsScopedArr.get(), length, breaks, tabStops, &primitives);
+ computePrimitives(b->buffer(), widthsScopedArr.get(), length, breaks, tabStops, &primitives);
LineWidth lineWidth(firstWidth, firstWidthLineLimit, restWidth);
std::vector<int> computedBreaks;
@@ -571,13 +583,41 @@
GreedyLineBreaker breaker(primitives, lineWidth);
breaker.computeBreaks(&computedBreaks, &computedWidths, &computedFlags);
}
+ b->finish();
return recycleCopy(env, recycle, recycleBreaks, recycleWidths, recycleFlags, recycleLength,
computedBreaks, computedWidths, computedFlags);
}
+static jlong nNewBuilder(JNIEnv*, jclass) {
+ return reinterpret_cast<jlong>(new Builder);
+}
+
+static void nFreeBuilder(JNIEnv*, jclass, jlong nativePtr) {
+ delete reinterpret_cast<Builder*>(nativePtr);
+}
+
+static void nFinishBuilder(JNIEnv*, jclass, jlong nativePtr) {
+ Builder* b = reinterpret_cast<Builder*>(nativePtr);
+ b->finish();
+}
+
+static void nBuilderSetLocale(JNIEnv* env, jclass, jlong nativePtr, jstring javaLocaleName) {
+ ScopedIcuLocale icuLocale(env, javaLocaleName);
+ Builder* b = reinterpret_cast<Builder*>(nativePtr);
+
+ if (icuLocale.valid()) {
+ b->setLocale(icuLocale.locale());
+ }
+}
+
static JNINativeMethod gMethods[] = {
- {"nComputeLineBreaks", "(Ljava/lang/String;[C[FIFIF[IIZLandroid/text/StaticLayout$LineBreaks;[I[F[ZI)I", (void*) nComputeLineBreaks}
+ {"nNewBuilder", "()J", (void*) nNewBuilder},
+ {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
+ {"nFinishBuilder", "(J)V", (void*) nFinishBuilder},
+ {"nBuilderSetLocale", "(JLjava/lang/String;)V", (void*) nBuilderSetLocale},
+ {"nComputeLineBreaks", "(J[C[FIFIF[IIZLandroid/text/StaticLayout$LineBreaks;[I[F[ZI)I",
+ (void*) nComputeLineBreaks}
};
int register_android_text_StaticLayout(JNIEnv* env)
diff --git a/core/jni/android_view_PointerIcon.cpp b/core/jni/android_view_PointerIcon.cpp
index bbd031e..f6d9a1a 100644
--- a/core/jni/android_view_PointerIcon.cpp
+++ b/core/jni/android_view_PointerIcon.cpp
@@ -80,7 +80,7 @@
jobject bitmapObj = env->GetObjectField(loadedPointerIconObj, gPointerIconClassInfo.mBitmap);
if (bitmapObj) {
- SkBitmap* bitmap = GraphicsJNI::getNativeBitmap(env, bitmapObj);
+ SkBitmap* bitmap = GraphicsJNI::getSkBitmap(env, bitmapObj);
if (bitmap) {
outPointerIcon->bitmap = *bitmap; // use a shared pixel ref
}
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 6c21bab..7080e2a 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -30,6 +30,7 @@
#include <gui/GLConsumer.h>
#include <gui/Surface.h>
+#include <GraphicsJNI.h>
#include <SkBitmap.h>
#include <SkPixelRef.h>
@@ -46,7 +47,6 @@
static jfieldID gSurface_EGLSurfaceFieldID;
static jfieldID gSurface_NativePixelRefFieldID;
static jfieldID gConfig_EGLConfigFieldID;
-static jfieldID gBitmap_NativeBitmapFieldID;
static inline EGLDisplay getDisplay(JNIEnv* env, jobject o) {
if (!o) return EGL_NO_DISPLAY;
@@ -85,9 +85,6 @@
jclass surface_class = _env->FindClass("com/google/android/gles_jni/EGLSurfaceImpl");
gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "J");
gSurface_NativePixelRefFieldID = _env->GetFieldID(surface_class, "mNativePixelRef", "J");
-
- jclass bitmap_class = _env->FindClass("android/graphics/Bitmap");
- gBitmap_NativeBitmapFieldID = _env->GetFieldID(bitmap_class, "mNativeBitmap", "J");
}
static const jint gNull_attrib_base[] = {EGL_NONE};
@@ -280,9 +277,7 @@
EGLConfig cnf = getConfig(_env, config);
jint* base = 0;
- SkBitmap const * nativeBitmap =
- (SkBitmap const *)_env->GetLongField(native_pixmap,
- gBitmap_NativeBitmapFieldID);
+ SkBitmap const * nativeBitmap = GraphicsJNI::getSkBitmap(_env, native_pixmap);
SkPixelRef* ref = nativeBitmap ? nativeBitmap->pixelRef() : 0;
if (ref == NULL) {
jniThrowException(_env, "java/lang/IllegalArgumentException", "Bitmap has no PixelRef");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b550558..2ce5bb3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2892,6 +2892,14 @@
android:description="@string/permdesc_bindNotificationListenerService"
android:protectionLevel="signature" />
+ <!-- Must be required by a {@link
+ android.service.chooser.ChooserTargetService}, to ensure that
+ only the system can bind to it. -->
+ <permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE"
+ android:label="@string/permlab_bindChooserTargetService"
+ android:description="@string/permdesc_bindChooserTargetService"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Must be required by a {@link
android.service.notification.ConditionProviderService},
to ensure that only the system can bind to it.
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png
index 9cdc25b..1550b44 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png
index 276d480..b309dfd 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png
index 95c0168..b36a413 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png
index 569332a..afd0bd2 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png
index a01ac10..58f8c43 100644
--- a/core/res/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png
index d3602d9..42a893d 100644
--- a/core/res/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-xhdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png
index 75085ce..d0f274a 100644
--- a/core/res/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png
index e2eb5be..f1f637a 100644
--- a/core/res/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/text_select_handle_left_mtrl_alpha.png b/core/res/res/drawable-xxxhdpi/text_select_handle_left_mtrl_alpha.png
new file mode 100644
index 0000000..643168f
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/text_select_handle_left_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/text_select_handle_right_mtrl_alpha.png b/core/res/res/drawable-xxxhdpi/text_select_handle_right_mtrl_alpha.png
new file mode 100644
index 0000000..e8f3aad
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/text_select_handle_right_mtrl_alpha.png
Binary files differ
diff --git a/core/res/res/drawable/ic_expand_more_48dp.xml b/core/res/res/drawable/ic_expand_more_48dp.xml
new file mode 100644
index 0000000..11323e3
--- /dev/null
+++ b/core/res/res/drawable/ic_expand_more_48dp.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48.0dp"
+ android:height="48.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M33.17,17.17L24.0,26.34l-9.17,-9.17L12.0,20.0l12.0,12.0 12.0,-12.0z"/>
+ <path
+ android:pathData="M0 0h48v48H0z"
+ android:fillColor="#00000000"/>
+</vector>
diff --git a/core/res/res/drawable/immersive_cling_bg_circ.xml b/core/res/res/drawable/immersive_cling_bg_circ.xml
new file mode 100644
index 0000000..4731bbd
--- /dev/null
+++ b/core/res/res/drawable/immersive_cling_bg_circ.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval" >
+
+ <solid android:color="@color/white" />
+
+ <size
+ android:height="56dp"
+ android:width="56dp" />
+
+</shape>
diff --git a/core/res/res/drawable/immersive_cling_light_bg_circ.xml b/core/res/res/drawable/immersive_cling_light_bg_circ.xml
new file mode 100644
index 0000000..df5d5ad
--- /dev/null
+++ b/core/res/res/drawable/immersive_cling_light_bg_circ.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval" >
+
+ <solid android:color="#80ffffff" />
+
+ <size
+ android:height="76dp"
+ android:width="76dp" />
+
+</shape>
diff --git a/core/res/res/layout-television/user_switching_dialog.xml b/core/res/res/layout-television/user_switching_dialog.xml
new file mode 100644
index 0000000..72150e3
--- /dev/null
+++ b/core/res/res/layout-television/user_switching_dialog.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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/message"
+ style="?attr/textAppearanceListItem"
+ android:layout_width="match_parent"
+ android:background="@color/background_leanback_dark"
+ android:textColor="@color/primary_text_leanback_dark"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:paddingStart="?attr/dialogPreferredPadding"
+ android:paddingEnd="?attr/dialogPreferredPadding"
+ android:paddingTop="24dp"
+ android:paddingBottom="24dp" />
diff --git a/core/res/res/layout/immersive_mode_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
index c0cd93d..28fbea5 100644
--- a/core/res/res/layout/immersive_mode_cling.xml
+++ b/core/res/res/layout/immersive_mode_cling.xml
@@ -13,55 +13,80 @@
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="wrap_content"
- android:orientation="vertical"
- android:padding="12dp"
- >
- <LinearLayout
- android:id="@+id/text"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_marginTop="4dp"
- android:padding="1dp"
- >
+ android:background="#ff009688"
+ android:gravity="center_vertical"
+ android:paddingBottom="24dp">
+
+ <FrameLayout
+ android:id="@+id/immersive_cling_chevron"
+ android:layout_width="76dp"
+ android:layout_height="76dp"
+ android:layout_marginTop="-24dp"
+ android:layout_centerHorizontal="true">
+
<ImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:src="@drawable/cling_arrow_up"
- />
- <FrameLayout
+ android:id="@+id/immersive_cling_back_bg_light"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="center"
+ android:src="@drawable/immersive_cling_light_bg_circ" />
+
+ <ImageView
+ android:id="@+id/immersive_cling_back_bg"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="center"
+ android:src="@drawable/immersive_cling_bg_circ" />
+
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="8dp"
+ android:scaleType="center"
+ android:src="@drawable/ic_expand_more_48dp"
+ android:tint="#ff009688"/>
+ </FrameLayout>
+
+ <TextView
+ android:id="@+id/immersive_cling_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@drawable/cling_bg"
- android:paddingStart="14dp"
- android:paddingEnd="14dp"
- android:paddingTop="24dp"
- android:paddingBottom="24dp">
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/immersive_mode_confirmation"
- android:textColor="#80000000"
- android:textSize="16sp"
- />
- </FrameLayout>
- </LinearLayout>
+ android:layout_below="@id/immersive_cling_chevron"
+ android:paddingEnd="48dp"
+ android:paddingStart="48dp"
+ android:paddingTop="40dp"
+ android:text="@string/immersive_cling_title"
+ android:textColor="@color/primary_text_default_material_light"
+ android:textSize="24sp" />
+
+ <TextView
+ android:id="@+id/immersive_cling_description"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/immersive_cling_title"
+ android:paddingEnd="48dp"
+ android:paddingStart="48dp"
+ android:paddingTop="12.6dp"
+ android:text="@string/immersive_cling_description"
+ android:textColor="@color/primary_text_default_material_light"
+ android:textSize="16sp" />
<Button
- android:id="@+id/ok"
- android:layout_width="160sp"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:layout_marginTop="18dp"
- android:gravity="center"
- android:text="@string/ok"
- android:background="@drawable/cling_button"
- />
+ android:id="@+id/ok"
+ style="@style/Widget.Material.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_below="@+id/immersive_cling_description"
+ android:layout_marginEnd="40dp"
+ android:layout_marginTop="18dp"
+ android:paddingEnd="8dp"
+ android:paddingStart="8dp"
+ android:text="@string/immersive_cling_positive"
+ android:textColor="@android:color/white"
+ android:textSize="14sp" />
-</LinearLayout>
-
-
+</RelativeLayout>
\ No newline at end of file
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 961ccc8..4d93a83 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Laat die program toe om met kortveldkommunikasie- (NFC) merkers, kaarte en lesers te kommunikeer."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktiveer jou skermslot"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Laat die program toe om die sleutelslot en enige verwante wagwoordsekuriteit te deaktiveer. Byvoorbeeld, die foon deaktiveer die sleutelslot wanneer ’n oproep inkom, en atkiveer dit dan weer wanneer die oproep eindig."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"bestuur vingerafdrukhardeware"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Laat die program toe om metodes te benut om vingerafdruksjablone vir gebruik by te voeg en uit te vee."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"gebruik vingerafdrukhardeware"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Laat die program toe om vingerafdrukhardeware vir stawing te gebruik"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lees sinkroniseer-instellings"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Laat die program toe om die sinkroniseringinstellings van \'n rekening te lees. Byvoorbeeld, dit kan bepaal of die People-program met \'n rekening gesinkroniseer is."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"wissel tussen sinkronisasie aan en af"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 9aadcec..05818bc 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"ከቅርብ ግኑኙነት መስክ (NFC) መለያዎች፣ ካርዶች እና አንባቢ ጋር ለማገናኘት ለመተግበሪያው ይፈቅዳሉ።"</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"የማያ ገጽዎን መቆለፊያ ያሰናክሉ"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"መተግበሪያው መቆለፊያውና ማንኛውም የተጎዳኘ የይለፍ ቃል ደህንነት እንዲያሰናክል ይፈቅድለታል። ለምሳሌ ስልኩ ገቢ የስልክ ጥሪ በሚቀበልበት ጊዜ መቆለፊያውን ያሰናክልና ከዚያም ጥሪው ሲጠናቀቅ መቆለፊያውን በድጋሚ ያነቃዋል።"</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"የጣት አሻራ ሃርድዌርን አስተዳድር"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"መተግበሪያው ጥቅም ላይ እንዲውሉ የጣት አሻራ ቅንብር ደንቦችን ለማከል እና ለመሰረዝ የሚያስችሉ ስልቶችን እንዲያስጀምር ያስችለዋል።"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"የጣት አሻራ ሃርድዌርን ተጠቀም"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"መተግበሪያው የጣት አሻራ ሃርድዌር ለማረጋገጥ ስራ እንዲጠቀም ያስችለዋል"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"የሥምሪያ ቅንብሮች አንብብ"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"መተግበሪያው የአንድ መለያ የማመሳሰል ቅንብሮችን እንዲያነብ ይፈቅድለታል። ለምሳሌ ይህ የሰዎች መተግበሪያ ከመለያ ጋር መመሳሰሉን አለመመሳሰሉን ሊወስን ይችላል።"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ማመሳሰያ በማብራትና በማጥፋት መካከል ቀያይር"</string>
@@ -827,7 +823,7 @@
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ ቴሌዚዥኑን ቆልፍ ወይም ሁሉንም የቴሌቪዥን ውሂብ ደምስስ።"</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"የተተየቡ ልክ ያልሆኑ የይለፍ ቃሎችን ቁጥር ተቆጣጠር፡፡ማሳያውን በምትከፍትበት ጊዜ፤ እና በጣም ብዙ ልክ ያልሆኑ የይለፍ ቃሎች ከተተየቡ ስልኩን ቆልፈው ወይም ሁሉንም የስልኩን ውሂብ ደምስሰው፡፡"</string>
<string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ ጡባዊውን ቆልፍ ወይም ሁሉንም የዚህን ተጠቃሚ ውሂብ ደምስስ።."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ ቴሌዚዥኑን ቆልፍ ወይም ሁሉንም የዚህን ተጠቃሚ ውሂብ ደምስስ።"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ ቴሌቪዥኑን ቆልፍ ወይም ሁሉንም የዚህን ተጠቃሚ ውሂብ ደምስስ።"</string>
<string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"ማያ ገጹን ሲያስከፍቱ በትክክል ያልተተየቡ የይለፍ ቃላት ብዛት ተከታተል፣ እና በጣም ብዙ ትክክል ያልሆኑ የይለፍ ቃላት ከተተየቡ ስልኩን ቆልፍ ወይም ሁሉንም የዚህን ተጠቃሚ ውሂብ ደምስስ።"</string>
<string name="policylab_resetPassword" msgid="4934707632423915395">"የማያ ገጹን መቆለፊያ ለውጥ"</string>
<string name="policydesc_resetPassword" msgid="1278323891710619128">"የማያ ገጽ መቆለፊያውን ለውጥ።"</string>
@@ -839,10 +835,10 @@
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"የፋብሪካ ውሂብ ድጋሚ አስጀምር በማከናወን ያለ ማሰጠንቀቂያ የስልኩን ውሂብ ደምስስ።"</string>
<string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"የተጠቃሚ ውሂብ ደምስስ"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"ያለምንም ማስጠንቀቂያ የዚህን ጡባዊ የተጠቃሚ ውሂብ ደምስስ።"</string>
- <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"ያለምንም ማስጠንቀቂያ የዚህን ቲቪ የተጠቃሚ ውሂብ ደምስስ።"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"ያለምንም ማስጠንቀቂያ የዚህን ቴቪ የተጠቃሚ ውሂብ ደምስስ።"</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"ያለምንም ማስጠንቀቂያ የዚህን ስልክ የተጠቃሚ ውሂብ ደምስስ።"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"የመሣሪያውን ሁሉንም ፕሮክሲ አዘጋጅ"</string>
- <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"መመሪያ እስኪነቃ ድረስ ለመጠቀም የመሣሪያውን ሁሉንተናዊ ተኪ አዘጋጅ። የመጀመሪያው የመሣሪያ ባለቤት ብቻ የሁሉንተናዊ ተኪውን ማዘጋጀት ይችላል።"</string>
+ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"መመሪያ ነቅቶ እያለ ጥቅም ላይ ሊውል የሚችለውን የመሣሪያውን ሁሉንተናዊ ተኪ አዘጋጅ። የመሣሪያ ባለቤት ብቻ የሁሉንተናዊ ተኪውን ማዘጋጀት ይችላል።"</string>
<string name="policylab_expirePassword" msgid="5610055012328825874">"የማያ ገጽ መቆለፊያ የአገልግሎት ማብቂያ ጊዜን አዘጋጅ"</string>
<string name="policydesc_expirePassword" msgid="5367525762204416046">"የማያ ገጽ መቆለፊያ የይለፍ ቃል፣ ፒን፣ ወይም ስርዓተ ጥለት በምን ያህል ጊዜ ተደጋግሞ መለወጥ እንዳለበት ለውጥ።"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"ማከማቻ ማመስጠር አዘጋጅ"</string>
@@ -850,7 +846,7 @@
<string name="policylab_disableCamera" msgid="6395301023152297826">"ካሜራዎችን አቦዝን"</string>
<string name="policydesc_disableCamera" msgid="2306349042834754597">"የሁሉንም መሣሪያ ካሜራዎች መጠቀም ከልክል።"</string>
<string name="policylab_disableKeyguardFeatures" msgid="3565888260412415862">"የማያ ገጽ መቆለፊያ የተሰናከሉ ባህሪዎች"</string>
- <string name="policydesc_disableKeyguardFeatures" msgid="3980868516629887575">"የማያ ገጽ መቆለፊያ ላይ ያሉ አንዳንድ ባህሪዎችን አጠቃቀም ተከላከል።"</string>
+ <string name="policydesc_disableKeyguardFeatures" msgid="3980868516629887575">"የማያ ገጽ መቆለፊያ ላይ ያሉ አንዳንድ ባህሪዎችን መጠቀምን ተከላከል።"</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"መነሻ"</item>
<item msgid="869923650527136615">"ተንቀሳቃሽ"</item>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 05731e3..8021de0 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -742,14 +742,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"للسماح للتطبيق بالاتصال بعلامات الاتصال قريب المدى (NFC)، والبطاقات وبرامج القراءة."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"تعطيل قفل الشاشة"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"للسماح للتطبيق بتعطيل تأمين المفاتيح وأي أمان لكلمة مرور مرتبطة. على سبيل المثال، يعطل الهاتف تأمين المفاتيح عند استقبال مكالمة هاتفية واردة، ثم يعيد تمكين تأمين المفاتيح عند انتهاء المكالمة."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"لإدارة أجهزة بصمة الإصبع"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"للسماح للتطبيق باستدعاء طرق لإضافة نماذج من بصمات الأصابع وحذفها."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"لاستخدام أجهزة بصمة الإصبع"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"للسماح للتطبيق باستخدام أجهزة بصمة الإصبع للمصادقة"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"قراءة إعدادات المزامنة"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"للسماح للتطبيق بقراءة الإعدادات المتزامنة لحساب ما. على سبيل المثال، يمكن أن يؤدي هذا إلى تحديد ما إذا تمت مزامنة تطبيق \"الأشخاص\" مع حساب ما."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"التبديل بين تشغيل المزامنة وإيقافها"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index bc9b984..125611f 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Разрешава на приложението да комуникира с маркери, карти и четци, ползващи комуникация в близкото поле (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"деактивиране на заключването на екрана ви"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Разрешава на приложението да деактивира заключването на клавиатурата и свързаната защита с парола. Например телефонът деактивира заключването при получаване на входящо обаждане и после го активира отново, когато обаждането завърши."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"управление на хардуера за отпечатъци"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Разрешава на приложението да извиква начини за добавяне и изтриване на шаблони за отпечатъци, които да се използват."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"използване на хардуера за отпечатъци"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Разрешава на приложението да използва хардуера за отпечатъци с цел удостоверяване"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"четене на настройките за синхронизиране"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Разрешава на приложението да чете настройките за синхронизиране на профил. Например това може да определи дали приложението Хора е синхронизирано с даден профил."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"включване и изключване на синхронизирането"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index 7fcda77e..f9ebf28 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"অ্যাপ্লিকেশানকে নিয়ার ফিল্ড কমিউনিকেশন (NFC) ট্যাগ, কার্ড এবং রিডারগুলির সাথে যোগাযোগ করতে দেয়৷"</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"আপনার স্ক্রীন লক অক্ষম করুন"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"কী-লক এবং যেকোনো সংশ্লিষ্ট পাসওয়ার্ড সুরক্ষা অক্ষম করতে অ্যাপ্লিকেশানটিকে মঞ্জুর করে৷ উদাহরণস্বরূপ, একটি ইনকামিং ফোন কল গ্রহণ করার সময়ে ফোনটি কী-লক অক্ষম করে, তারপরে কল শেষ হয়ে গেলে কী-লকটিকে পুনরায় সক্ষম করে৷"</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার পরিচালনা করুন"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ব্যবহার করার জন্য আঙ্গুলের ছাপের টেম্প্লেটগুলি যোগ করা এবং মোছার পদ্ধতিগুলি গ্রহন করতে অ্যাপ্লিকেশানটিতে অমুমতি দেয়৷"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার ব্যবহার করুন"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"অনুমোদনের জন্য আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার ব্যবহার করতে অ্যাপ্লিকেশানটিতে অনুমতি দেয়"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"সিঙ্ক সেটিংস পড়ে"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"অ্যাপ্লিকেশানটিকে একটি অ্যাকাউন্টের জন্য সিঙ্ক সেটিংস পড়ার অনুমতি দেয়৷ উদাহরণস্বরূপ, \'পিপল\' অ্যাপ্লিকেশানটি কোনো অ্যাকাউন্টের সাথে সিঙ্ক করা আছে কিনা তা নির্ধারণ করতে পারে৷"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"সমন্বয় চালু এবং বন্ধ করা টগল করুন"</string>
@@ -843,7 +839,7 @@
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"সতর্কীকরণ ছাড়াই এই ফোনে থাকা ব্যাবহারকার্রী ডেটা মুছে ফেলে৷"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ডিভাইসের বৈশ্বিক প্রক্সী সেট করে"</string>
<string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"নীতিযখন নীতি সক্ষম করা হয় তখন ডিভাইসের বৈশ্বিক প্রক্সী ব্যবহার করা হবে সেই হিসাবে সেট করে৷ শুধুমাত্র ডিভাইসের মালিক বৈশ্বিক প্রক্সী সেট করতে পারেন৷"</string>
- <string name="policylab_expirePassword" msgid="5610055012328825874">"স্ক্রীন লকের পাসওয়ার্ডের মেয়াদ শেষ হওয়ার সময়কাল সেট করে"</string>
+ <string name="policylab_expirePassword" msgid="5610055012328825874">"স্ক্রীন লক করার জন্য পাসওয়ার্ডের মেয়াদ শেষ হওয়ার সময় সেট করে"</string>
<string name="policydesc_expirePassword" msgid="5367525762204416046">"স্ক্রীন লক করার পাসওয়ার্ড কত ঘন ঘন পরিবর্তন করা আবশ্যক তা পরিবর্তন করুন৷"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"সঞ্চয়স্থানের এনক্রিপশান সেট করে"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"এই সঞ্চিত অ্যাপ্লিকেশান ডেটা এনক্রিপ্ট করা দরকার৷"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e80c269..68768d4 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Permet que l\'aplicació es comuniqui amb les etiquetes, les targetes i els lectors de Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"desactivació del bloqueig de pantalla"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permet que l\'aplicació desactivi el bloqueig del teclat i qualsevol element de seguretat de contrasenyes associat. Per exemple, el telèfon desactiva el bloqueig del teclat en rebre una trucada telefònica entrant i, a continuació, reactiva el bloqueig del teclat quan finalitza la trucada."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"Gestionar el maquinari d\'empremtes digitals"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permet que l\'aplicació invoqui mètodes per afegir i suprimir plantilles d\'empremtes digitals que es puguin fer servir."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"Utilitzar el maquinari d\'empremtes digitals"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permet que l\'aplicació faci servir maquinari d\'empremtes digitals per a l\'autenticació"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"llegir la configuració de sincronització"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permet que l\'aplicació llegeixi la configuració de sincronització d\'un compte. Per exemple, això pot determinar que l\'aplicació Persones estigui sincronitzada amb un compte."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar o desactivar la sincronització"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index e4eab08..253f35c 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -740,14 +740,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikaci komunikovat se štítky, kartami a čtečkami s podporou technologie NFC."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"vypnutí zámku obrazovky"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Umožňuje aplikaci vypnout zámek kláves a související zabezpečení heslem. Telefon například vypne zámek klávesnice při příchozím hovoru a po skončení hovoru jej zase zapne."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"správa hardwaru na čtení otisků prstů"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikaci volat metody k přidání a smazání šablon otisků prstů, které budou použity."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"použití hardwaru na čtení otisků prstů"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Umožňuje aplikaci použít k ověření hardware na čtení otisků prstů"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"čtení nastavení synchronizace"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Umožňuje aplikaci číst nastavení synchronizace v účtu. Může například určit, zda je s účtem synchronizována aplikace Lidé."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"vypnutí nebo zapnutí synchronizace"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 48de516..59c276f 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Tillader, at appen kan kommunikere med NFC-tags (Near Field Communication), -kort og -læsere."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivere din skærmlås"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Tillader, at appen kan deaktivere tastaturlåsen og anden form for tilknyttet adgangskodesikkerhed. Telefonen deaktiverer f.eks. tastaturlåsen ved indgående telefonopkald og aktiverer tastaturlåsen igen, når opkaldet er afsluttet."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"administrer fingeraftrykhardware"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Tillader, at appen kan køre metoder til at tilføje og slette fingeraftryksskabeloner"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"brug fingeraftrykhardware"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillader, at appen kan bruge fingeraftrykhardware til godkendelse"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"læse indstillinger for synkronisering"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Tillader, at appen kan læse synkroniseringsindstillingerne for en konto. Denne tilladelse kan f.eks. fastslå, om appen Personer er synkroniseret med en konto."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"slå synkronisering til og fra"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 1e71a4f..0779d06 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Επιτρέπει στην εφαρμογή την επικοινωνία με ετικέτες, κάρτες και αναγνώστες της Επικοινωνίας κοντινού πεδίου (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"απενεργοποίηση κλειδώματος οθόνης"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Επιτρέπει στην εφαρμογή την απενεργοποίηση του κλειδώματος πληκτρολογίου και άλλης σχετικής ασφάλειας με κωδικό πρόσβασης. Για παράδειγμα, το κλείδωμα πληκτρολογίου στο τηλέφωνο απενεργοποιείται όταν λαμβάνεται εισερχόμενη τηλεφωνική κλήση και ενεργοποιείται ξανά όταν η κλήση τερματιστεί."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"διαχείριση εξοπλισμού μοναδικού χαρακτηριστικού"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Επιτρέπει στην εφαρμογή να επικαλείται μεθόδους για την προσθήκη και τη διαγραφή προτύπων μοναδικού χαρακτηριστικού για χρήση."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"χρήση εξοπλισμού μοναδικού χαρακτηριστικού"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Επιτρέπει στην εφαρμογή να χρησιμοποιεί εξοπλισμό μοναδικού χαρακτηριστικού για έλεγχο ταυτότητας"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ανάγνωση ρυθμίσεων συγχρονισμού"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Επιτρέπει στην εφαρμογή την ανάγνωση των ρυθμίσεων συγχρονισμού για έναν λογαριασμό. Για παράδειγμα, αυτό μπορεί να καθορίσει εάν η εφαρμογή \"Άτομα\" είναι συγχρονισμένη με έναν λογαριασμό."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"εναλλαγή ενεργοποίησης και απενεργοποίησης συγχρονισμού"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 75ef4ad..c7a07b8 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Võimaldab rakendusel suhelda lähiväljaside (NFC) märgendite, kaartide ja lugeritega."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"keelake ekraanilukk"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Võimaldab rakendusel keelata klahviluku ja muu seotud parooli turvalisuse. Näiteks keelab telefon klahviluku sissetuleva kõne vastuvõtmisel ja lubab klahviluku uuesti, kui kõne on lõpetatud."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"sõrmejälje riistvara haldamine"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Võimaldab rakendusel tühistada meetodid kasutatavate sõrmejäljemallide lisamiseks ja kustutamiseks."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"sõrmejälje riistvara kasutamine"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Võimaldab rakendusel autentimiseks kasutada sõrmejälje riistvara"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"loe sünkroonimisseadeid"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Võimaldab rakendusel lugeda konto sünkroonimisseadeid. Näiteks võib see määrata, kas rakendus Inimesed on kontoga sünkroonitud."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"lülitage sünkroonimine sisse ja välja"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index e482f99..90b9a62 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Near Field Communication (NFC) etiketekin, txartelekin eta irakurgailuekin komunikatzea baimentzen die aplikazioei."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"pantailaren blokeoa desgaitzea"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Teklen blokeoa eta erlazionatutako pasahitz-segurtasuna desgaitzeko baimena ematen die aplikazioei. Adibidez, telefonoak teklen blokeoa desgaitzen du telefono-deiak jasotzen dituenean, eta berriro gaitzen du deiak amaitzean."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"Kudeatu hatz-marka digitalen hardwarea"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Hatz-marka digitalen txantiloiak gehitzeko eta ezabatzeko metodoei dei egitea baimentzen die aplikazioei."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"Erabili hatz-marka digitalen hardwarea"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Autentifikatzeko hatz-marka digitalen hardwarea erabiltzea baimentzen die aplikazioei."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"Irakurri sinkronizazio-ezarpenak"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Kontu baten sinkronizazio-ezarpenak irakurtzeko baimena ematen die aplikazioei. Adibidez, Jendea aplikazioa konturen batekin sinkronizatuta dagoen zehatz dezake."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"sinkronizazioa aktibatzea eta desaktibatzea"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c393f1c..36246cc 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Antaa sovelluksen kommunikoida NFC (Near Field Communication) -tagien, -korttien ja -lukijoiden kanssa."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"poista ruudun lukitus käytöstä"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Antaa sovelluksen ottaa näppäinlukon ja siihen liittyvän salasanasuojauksen pois käytöstä. Esimerkki: puhelin poistaa näppäinlukon käytöstä puhelun saapuessa ja asettaa lukon takaisin käyttöön puhelun päättyessä."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"sormenjälkilaitteiston hallinnointi"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Sallii sovelluksen käyttää menetelmiä, joilla voidaan lisätä tai poistaa sormenjälkimalleja."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"sormenjälkilaitteiston käyttö"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Sallii sovelluksen käyttää sormenjälkilaitteistoa todennukseen."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lue synkronointiasetuksia"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Antaa sovelluksen lukea tilien synkronointiasetuksia. Sovellus voi esimerkiksi määrittää, onko Henkilöt-sovellus synkronoitu tilin kanssa."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ota synkronointi käyttöön tai poista se käytöstä"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index ae61e0e..03f1d87 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Permite á aplicación comunicarse con etiquetas, tarxetas e lectores Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"desactivar o bloqueo da pantalla"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite á aplicación desactivar o bloqueo do teclado e calquera seguridade dos contrasinais asociada. Por exemplo, o teléfono desactiva o bloqueo do teclado ao recibir unha chamada telefónica entrante e, a continuación, volve activar o bloqueo do teclado unha vez finalizada a chamada."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"xestionar hardware de identificación dixital"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que a aplicación invoque métodos para engadir e eliminar modelos de uso de identificación dixital."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"usar hardware de identificación dixital"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que a aplicación utilice hardware de identificación dixital para a autenticación"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler a configuración de sincronización"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite á aplicación ler a configuración de sincronización dunha conta. Por exemplo, esta acción pode determinar se a aplicación Contactos se sincroniza cunha conta."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar e desactivar a sincronización"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 7495676..1505fa9 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"ऐप्स को नियर फ़ील्ड कम्यूनिकेशन (NFC) टैग, कार्ड, और रीडर के साथ संचार करने देता है."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"अपना स्क्रीन लॉक अक्षम करें"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"ऐप्स को कीलॉक और कोई भी संबद्ध पासवर्ड सुरक्षा अक्षम करने देता है. उदाहरण के लिए, इनकमिंग फ़ोन कॉल प्राप्त करते समय फ़ोन, कीलॉक को अक्षम कर देता है, फिर कॉल समाप्त होने पर कीलॉक को पुन: सक्षम कर देता है."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"फ़िंगरप्रिंट हार्डवेयर को प्रबंधित करें"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"फ़िंगरप्रिंट टेम्पलेट का उपयोग करने के लिए जोड़ने और हटाने हेतु ऐप को विधियां प्रारंभ करने देती है."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"फ़िंगरप्रिंट हार्डवेयर का उपयोग करें"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ऐप के प्रमाणीकरण के लिए फ़िंगरप्रिंट हार्डवेयर का उपयोग करने देती है"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"समन्वयन सेटिंग पढ़ें"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ऐप्स को किसी खाते की समन्वयन सेटिंग पढ़ने देता है. उदाहरण के लिए, इससे यह निर्धारित किया जा सकता है कि लोग ऐप्स किसी खाते के साथ समन्वयित है या नहीं."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"समन्वयन बंद या चालू टॉगल करें"</string>
@@ -826,9 +822,9 @@
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"स्क्रीन को अनलॉक करते समय गलत लिखे गए पासवर्ड की संख्या पर निगरानी करें, और बहुत अधिक बार गलत पासवर्ड लिखे जाने पर टेबलेट लॉक करें या टेबलेट का संपूर्ण डेटा मिटाएं."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बहुत अधिक गलत पासवर्ड लिखे जाते हैं तो टीवी को लॉक करें या टीवी का सभी डेटा मिटा दें."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"गलत लिखे गए पासवर्ड की संख्या पर निगरानी करें. स्क्रीन अनलॉक करते समय, बहुत अधिक बार गलत पासवर्ड लिखे जाने पर फ़ोन लॉक करें या फ़ोन का संपूर्ण डेटा मिटाएं."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बहुत अधिक गलत पासवर्ड लिखे जाते हैं तो टैबलेट को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बहुत अधिक गलत पासवर्ड लिखे जाते हैं तो टीवी को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बहुत अधिक गलत पासवर्ड लिखे जाते हैं तो फ़ोन को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बार बार अधिक पासवर्ड लिखे जाते हैं तो टैबलेट को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें यदि बार बार गलत पासवर्ड लिखे जाने पर टीवी को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"स्क्रीन को अनलॉक करते समय गलत तरीके से लिखे गए पासवर्ड पर नज़र रखें और यदि बार बार गलत पासवर्ड लिखे जाते हैं तो फ़ोन को लॉक करें या इस उपयोगकर्ता का सभी डेटा मिटा दें."</string>
<string name="policylab_resetPassword" msgid="4934707632423915395">"स्क्रीन लॉक बदलें"</string>
<string name="policydesc_resetPassword" msgid="1278323891710619128">"स्क्रीन लॉक को बदलें."</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"स्क्रीन लॉक करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 8098e2c..d5a4a0d 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -739,14 +739,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Aplikaciji omogućuje komunikaciju s oznakama, karticama i čitačima komunikacije kratkog dometa (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"onemogućavanje zaključavanja zaslona"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Aplikaciji omogućuje onemogućavanje zaključavanja tipkovnice i svih pripadajućih sigurnosnih zaporki. Na primjer, telefon onemogućuje zaključavanje tipkovnice kod primanja dolaznog telefonskog poziva, nakon kojeg se zaključavanje tipkovnice ponovo omogućuje."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"upravljanje hardverom za čitanje otisaka prstiju"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Aplikaciji omogućuje pozivanje načina za dodavanje i brisanje predložaka otisaka prstiju koji će se upotrijebiti."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"upotreba hardvera za čitanje otisaka prstiju"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Aplikaciji omogućuje upotrebu hardvera za čitanje otisaka prstiju radi autentifikacije."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"čitanje postavki sinkronizacije"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Aplikaciji omogućuje čitanje postavki sinkronizacije za račun. Time se, primjerice, može utvrditi je li aplikacija Osobe sinkronizirana s računom."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"uključivanje/isključivanje sinkronizacije"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 9292408..2960784 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Lehetővé teszi az alkalmazás számára, hogy NFC (Near Field Communication - kis hatósugarú vezeték nélküli kommunikáció) technológiát használó címkékkel, kártyákkal és leolvasókkal kommunikáljon."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"képernyőzár kikapcsolása"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Lehetővé teszi az alkalmazás számára a billentyűzár és bármely kapcsolódó jelszavas védelem kikapcsolását. Például a telefon feloldja a billentyűzárat bejövő hívás esetén, majd újra bekapcsolja azt a hívás végeztével."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ujjlenyomat-olvasó hardver kezelése"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Lehetővé teszi az alkalmazás számára a használni kívánt ujjlenyomatsablonok hozzáadására és törlésére szolgáló metódusok indítását."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"ujjlenyomat-olvasó hardver használata"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Lehetővé teszi az alkalmazás számára az ujjlenyomat-olvasó hardver hitelesítésre való használatát"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"szinkronizálási beállítások olvasása"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Lehetővé teszi az alkalmazás számára egy fiók szinkronizálási beállításainak beolvasását. Például ellenőrizheti, hogy a Személyek alkalmazás szinkronizálva van-e egy fiókkal."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"szinkronizálás be-és kikapcsolása"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 620ea8e..3fe2833 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Թույլ է տալիս հավելվածին հաղորդակցվել Մոտ տարածությամբ հաղորդակցման (NFC) պիտակների, քարտերի և ընթերցիչների հետ:"</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"անջատել ձեր էկրանի կողպեքը"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Թույլ է տալիս հավելվածին անջատել ստեղնաշարի կողպումը և ցանկացած համակցված գաղտնաբառի պաշտպանվածությունը: Սրա ճիշտ օրինակն է, երբ հեռախոսը անջատում է ստեղնաշարի կողպումը մուտքային զանգ ստանալիս, հետո այն կրկին միացնում է, երբ զանգը ավարտվում է:"</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"կառավարել մատնահետքերի գրանցման սարքը"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Հավելվածին թույլ է տալիս կատարել այնպիսի գործառույթներ, որոնց միջոցով կարելի է օգտագործման համար ավելացնել և հեռացնել մատնահետքերի նմուշներ:"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"օգտագործել մատնահետքերի գրանցման սարքը"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Հավելվածին թույլ է տալիս նույնականացման համար օգտագործել մատնահետքերի գրանցման սարքը"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"կարդալ համաժամեցման կարգավորումները"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Թույլ է տալիս հավելվածին կարդալ համաժամեցման կարգավորումները հաշվի համար: Օրինակ` այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամեցված է հաշվի հետ:"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"համաժամեցումը փոխարկել միացվածի և անջատվածի"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 1a813c9..96d65aec 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Mengizinkan apl berkomunikasi dengan tag, kartu, dan alat pembaca Komunikasi Nirkabel Jarak Dekat (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"nonaktifkan kunci layar Anda"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Memungkinkan aplikasi menonaktifkan kunci tombol dan keamanan sandi apa pun yang terkait. Misalnya, ponsel menonaktifkan kunci tombol saat menerima panggilan telepon masuk, kemudian mengaktifkan kembali kunci tombol ketika panggilan selesai."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"kelola perangkat keras sidik jari"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Mengizinkan aplikasi memanggil metode untuk menambahkan dan menghapus template sidik jari untuk digunakan."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"gunakan perangkat keras sidik jari"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Mengizinkan aplikasi untuk menggunakan perangkat keras sidik jari untuk otentikasi"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"baca setelan sinkron"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Memungkinkan aplikasi membaca setelan sinkronisasi untuk sebuah akun. Misalnya, izin ini dapat menentukan apakah aplikasi Orang disinkronkan dengan sebuah akun."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"nyalakan dan matikan sinkronisasi"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index 8a76da7..355becb 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Leyfir forriti að eiga samskipti við NFC-merki, -spjöld og -lesara (nándarsamskipti)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"slökkva á skjálásnum"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Leyfir forriti að slökkva á símalásnum og öðrum öryggisaðgerðum tengdum aðgangsorði. Til dæmis gerir síminn lásinn óvirkan þegar símtal berst og læsist svo aftur að símtali loknu."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"stjórna fingrafarabúnaði"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Gerir forritinu kleift að beita aðferðum til að bæta við og eyða fingrafarasniðmátum til notkunar."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"nota fingrafarabúnað"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Leyfir forritinu að nota fingrafarabúnað til auðkenningar"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lesa samstillingar"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Leyfir forriti að lesa kosti samstillingar fyrir reikning. Þetta er til dæmis hægt að nota til að komast að því hvort forritið Fólk er samstillt við reikning."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"kveikja og slökkva á samstillingu"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bfd48b4..9b57ad8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -764,7 +764,7 @@
<string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"lettura contenuti scheda SD"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"L\'app può leggere i contenuti dell\'archivio USB."</string>
<string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Consente all\'applicazione di leggere i contenuti della scheda SD."</string>
- <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"Modifica/eliminazione contenuti USB"</string>
+ <string name="permlab_sdcardWrite" product="nosdcard" msgid="8485979062254666748">"modifica/eliminazione contenuti USB"</string>
<string name="permlab_sdcardWrite" product="default" msgid="8805693630050458763">"modifica o eliminazione dei contenuti della scheda SD"</string>
<string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Consente all\'applicazione di scrivere nell\'archivio USB."</string>
<string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Consente all\'applicazione di scrivere sulla scheda SD."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 5db76bc..9f0540f 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -740,14 +740,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"מאפשר לאפליקציה נהל תקשורת עם תגים, כרטיסים וקוראים מסוג \'תקשורת מטווח קצר\'."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"ביטול נעילת המסך שלך"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"מאפשר לאפליקציה להשבית את נעילת המקשים וכל אמצעי אבטחה משויך המבוסס על סיסמה. לדוגמה, הטלפון משבית את נעילת המקשים בעת קבלה של שיחת טלפון נכנסת, ולאחר מכן מפעיל מחדש את נעילת המקשים עם סיום השיחה."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ניהול חומרה של טביעות אצבעות"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"מאפשר לאפליקציה להפעיל שיטות להוספה ומחיקה של תבניות טביעות אצבעות שבהן ייעשה שימוש."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"שימוש בחומרה של טביעות אצבעות"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"מאפשר לאפליקציה להשתמש בחומרה של טביעות אצבעות לצורך אימות"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"קרא את הגדרות הסינכרון"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"מאפשר לאפליקציה לקרוא את הגדרות הסנכרון של חשבון. לדוגמה, ניתן לגלות כך האם האפליקציה \'אנשים\' מסונכרן עם חשבון כלשהו."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"הפעלת וכיבוי סנכרון"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index da03db6..f642062 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"აპს შეეძლება ახლო მოქმედების რადიოკავშირის (NFC) მეშვეობით ტეგების, ბარათებისა და წამკითხველების შემცველი მონაცემების მიმოცვლა."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"თქვენი ეკრანის ბლოკის გათიშვა"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"შეეძლება კლავიატურის დაბლოკვისა და პაროლით უზრუნველყოფილი ნებისმიერი უსაფრთხოების ფუნქციის დეაქტივაცია. მაგალითად, ტელეფონი შემომავალი ზარის დროს აუქმებს კლავიატურის დაბლოკვას და კვლავ ააქტიურებს მას, როგორც კი ზარი დასრულდება."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"თითის ანაბეჭდის აპარატის მართვა"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"საშუალებას აძლევს აპლიკაციას დაამატოს ან ამოშალოს გამოსაყენებელი თითის ანაბეჭდის ნიმუშები,"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"თითის ანაბეჭდის აპარატის გამოყენება"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"საშუალებას აძლევს აპლიკაციას გამოიყენოს ავტენთიფიკაციისათვის თითის ანაბეჭდის აპარატი"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"სინქრონიზაციის პარამეტრების წაკითხვა"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"აპს შეეძლება, წაიკითხოს ანგარიშის სინქრონიზაციის პარამეტრები. მაგალითად, მას შეეძლება განსაზღვროს, არის თუ არა People აპი სინქრონიზებული ანგარიშთან."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"სინქრონიზაციის ჩართვა და გამორთვა"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index a3003780..7ce44de 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Қолданбаға NFC белгілерімен, карталармен және оқу құралдарымен байланысуға рұқсат береді."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"экран бекітпесін істен шығару"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Қолданбаларға кілтперне және басқа кілтсөзге қатысты қауіпсіздік шараларын өшіру мүмкіндігін береді. Мысалы, телефон кіріс қоңырауларын алғанда кілтпернені өшіреді және қоңырау аяқталғанда қайта қосады."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"саусақ ізі жабдығын басқару"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Қолданбаға пайдаланатын саусақ ізі үлгілерін қосу және жою әдістерін шақыруға мүмкіндік береді."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"саусақ ізі жабдығын пайдалану"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Қолданбаға аутентификацияалу үшін саусақ ізі жабдығын пайдалануға мүмкіндік береді"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"синх параметрлерін оқу"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Қолданбаға есептік жазба синхрондау параметрлерін оқу мүмкіндігін береді. Мысалы, бұл арқылы People қолданбасының есептік жазбамен сихрондалғаны анықталуы мүмкін."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"синх қосу және өшіру арасында ауысу"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 16a7901..16f3da2 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"ឲ្យកម្មវិធីទាក់ទងជាមួយស្លាក (NFC) កាត និងកម្មវិធីអាន។"</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"បិទការចាក់សោអេក្រង់របស់អ្នក"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"ឲ្យកម្មវិធីបិទការចាក់សោសុវត្ថិភាពពាក្យសម្ងាត់ដែលបានភ្ជាប់ណាមួយ។ ឧទាហរណ៍ត្រឹមត្រូវនៃការបិទទូរស័ព្ទពេលទទួលការហៅចូល បន្ទាប់មបើកសោពេលការហៅបានបញ្ចប់។"</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"គ្រប់គ្រងផ្នែករឹងស្នាមម្រាមដៃ"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"អនុញ្ញាតឲ្យកម្មវិធីប្រើវិធីសាស្ត្របន្ថែម និងលុបពុម្ពម្រាមដៃសម្រាប់ប្រើប្រាស់។"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"ប្រើផ្នែករឹងស្នាមម្រាមដៃ"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"អនុញ្ញាតឲ្យកម្មវិធីប្រើផ្នែករឹងស្នាមម្រាមដៃសម្រាប់ការផ្ទៀងផ្ទាត់"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"អានការកំណត់ធ្វើសមកាលកម្ម"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ឲ្យកម្មវិធីអានការកំណត់ធ្វើសមកាលកម្មសម្រាប់គណនី។ ឧទាហរណ៍ វាអាចកំណត់ថាតើកម្មវិធីត្រូវបានបើកជាមួយគណនីដែរឬទេ។"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"បិទ/បើកការធ្វើសមកាលកម្ម"</string>
@@ -821,51 +817,36 @@
<string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"ភ្ជាប់ទៅសេវាកម្មសារអ្នកផ្តល់សេវាកម្មទូរស័ព្ទ"</string>
<string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"អនុញ្ញាតឲ្យអ្នកប្រើភ្ជាប់ទៅអ៊ីនធឺហ្វេសកម្រិតខ្ពស់នៃសេវាកម្មសារអ្នកផ្តល់សេវាកម្មទូរស័ព្ទ។ មិនគួរចាំបាច់សម្រាប់កម្មវិធីធម្មតាទេ។"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"កំណត់ក្បួនពាក្យសម្ងាត់"</string>
- <!-- no translation found for policydesc_limitPassword (2502021457917874968) -->
- <skip />
+ <string name="policydesc_limitPassword" msgid="2502021457917874968">"គ្រប់គ្រងប្រវែង និងតួអក្សរដែលអនុញ្ញាតឲ្យប្រើក្នុងពាក្យសម្ងាត់ និងលេខសម្ងាត់ចាក់សោអេក្រង់។"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ពិនិត្យការព្យាយាមដោះសោអេក្រង់"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"ពិនិត្យចំនួនបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវ។ ពេលដោះសោអេក្រង់ និងចាក់សោទូរស័ព្ទ ឬលុបទិន្នន័យទូរស័ព្ទទាំងអស់ ប្រសិនបើមានពាក្យសម្ងាត់បញ្ចូលមិនត្រឹមត្រូវច្រើនដងពេក។"</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"ត្រួតពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោទូរទស្សន៍ ឬលុបទិន្នន័យទូរទស្សន៍ទាំង ប្រសិនបើមានការវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"ពិនិត្យចំនួនបញ្ចូលពាក្យសម្ងាត់មិនត្រឹមត្រូវ។ ពេលដោះសោអេក្រង់ និងចាក់សោទូរស័ព្ទ ឬលុបទិន្នន័យទូរស័ព្ទទាំងអស់ ប្រសិនបើមានពាក្យសម្ងាត់បញ្ចូលមិនត្រឹមត្រូវច្រើនដងពេក។"</string>
- <!-- no translation found for policydesc_watchLogin_secondaryUser (4280246270601044505) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin_secondaryUser (3484832653564483250) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin_secondaryUser (2185480427217127147) -->
- <skip />
- <!-- no translation found for policylab_resetPassword (4934707632423915395) -->
- <skip />
- <!-- no translation found for policydesc_resetPassword (1278323891710619128) -->
- <skip />
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"ត្រួតពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោថេប្លេត ឬលុបទិន្នន័យអ្នកប្រើនេះទាំងអស់ ប្រសិនបើមានការវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"ត្រួតពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោទូរទស្សន៍ ឬលុបទិន្នន័យអ្នកប្រើនេះទាំងអស់ ប្រសិនបើមានការវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"ត្រួតពិនិត្យចំនួននៃការវាយបញ្ចូលពាក្យសម្ងាត់ដែលមិនត្រឹមត្រូវ នៅពេលដោះសោអេក្រង់ និងចាក់សោទូរស័ព្ទ ឬលុបទិន្នន័យអ្នកប្រើនេះទាំងអស់ ប្រសិនបើមានការវាយបញ្ចូលពាក្យសម្ងាត់ខុសច្រើនដងពេក។"</string>
+ <string name="policylab_resetPassword" msgid="4934707632423915395">"ប្តូរការចាក់សោអេក្រង់"</string>
+ <string name="policydesc_resetPassword" msgid="1278323891710619128">"ប្តូរការចាក់សោអេក្រង់។"</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="tv" msgid="5816221315214527028">"លុបទិន្នន័យរបស់ទូរទស្សន៍ដោយមិនចាំបាច់ព្រមានដោយការប្រតិបត្តិការកំណត់ឡើងវិញទាំងស្រុង។"</string>
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"លុបទិន្នន័យទូរស័ព្ទដោយមិនព្រមាន ដោយអនុវត្តការកំណត់ទិន្នន័យដូចចេញពីរោងចក្រ ។"</string>
- <!-- no translation found for policylab_wipeData_secondaryUser (8362863289455531813) -->
- <skip />
- <!-- no translation found for policydesc_wipeData_secondaryUser (6336255514635308054) -->
- <skip />
- <!-- no translation found for policydesc_wipeData_secondaryUser (2086473496848351810) -->
- <skip />
- <!-- no translation found for policydesc_wipeData_secondaryUser (6787904546711590238) -->
- <skip />
+ <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"លុបទិន្នន័យរបស់អ្នកប្រើ"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"លុបទិន្នន័យរបស់អ្នកប្រើនេះនៅលើថេប្លេតនេះដោយគ្មានការព្រមាន។"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"លុបទិន្នន័យរបស់អ្នកប្រើនេះនៅលើទូរទស្សន៍នេះដោយគ្មានការព្រមាន។"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"លុបទិន្នន័យរបស់អ្នកប្រើនេះនៅលើទូរស័ព្ទនេះដោយគ្មានការព្រមាន។"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"កំណត់ប្រូកស៊ីសកលរបស់ឧបករណ៍"</string>
- <!-- no translation found for policydesc_setGlobalProxy (8459859731153370499) -->
- <skip />
- <!-- no translation found for policylab_expirePassword (5610055012328825874) -->
- <skip />
- <!-- no translation found for policydesc_expirePassword (5367525762204416046) -->
- <skip />
+ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"កំណត់ប្រូកស៊ីសកលឧបករណ៍ដើម្បីប្រើប្រាស់ ខណៈពេលដែលគោលការណ៍បើកដំណើរការ។ មានតែឧបករណ៍ម្ចាស់ប៉ុណ្ណោះអាចកំណត់ប្រូកស៊ីសកលនេះបាន។"</string>
+ <string name="policylab_expirePassword" msgid="5610055012328825874">"កំណត់ពេលផុតកំណត់ពាក្យសម្ងាត់ចាក់សោអេក្រង់"</string>
+ <string name="policydesc_expirePassword" msgid="5367525762204416046">"ប្តូរពីភាពញឹកញាប់ដែលពាក្យសម្ងាត់ លេខសម្ងាត់ និងគំរូចាក់សោអេក្រង់ត្រូវផ្លាស់ប្តូរ។"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"កំណត់ការដាក់លេខកូដការផ្ទុក"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"តម្រូវឲ្យដាក់លេខកូដទិន្នន័យកម្មវិធីបានរក្សាទុក។"</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"បិទម៉ាស៊ីនថត"</string>
<string name="policydesc_disableCamera" msgid="2306349042834754597">"ការពារការប្រើម៉ាស៊ីនថតឧបករណ៍ទាំងអស់។"</string>
- <!-- no translation found for policylab_disableKeyguardFeatures (3565888260412415862) -->
- <skip />
- <!-- no translation found for policydesc_disableKeyguardFeatures (3980868516629887575) -->
- <skip />
+ <string name="policylab_disableKeyguardFeatures" msgid="3565888260412415862">"បិទលក្ខណៈពិសេសចាក់សោអេក្រង់"</string>
+ <string name="policydesc_disableKeyguardFeatures" msgid="3980868516629887575">"រារាំងអ្នកប្រើពីការប្រើលក្ខណៈពិសេសនៃការចាក់សោអេក្រង់មួយចំនួន។"</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"ផ្ទះ"</item>
<item msgid="869923650527136615">"ចល័ត"</item>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 0bb2e50..ec24705 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"ಸಮೀಪದ ಕ್ಷೇತ್ರ ಸಂವಹನ (NFC) ಟ್ಯಾಗ್ಗಳು, ಕಾರ್ಡ್ಗಳು, ಮತ್ತು ಓದುಗರನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"ನಿಮ್ಮ ಪರದೆ ಲಾಕ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"ಕೀಲಾಕ್ ಮತ್ತು ಯಾವುದೇ ಸಂಬಂಧಿತ ಭದ್ರತಾ ಪಾಸ್ವರ್ಡ್ ಭದ್ರತೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ಒಳಬರುವ ಕರೆಯನ್ನು ಸ್ವೀಕರಿಸುವಾಗ ಕೀಲಾಕ್ ಅನ್ನು ಫೋನ್ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ, ನಂತರ ಕರೆಯು ಅಂತ್ಯಗೊಂಡಾಗ ಕೀಲಾಕ್ ಅನ್ನು ಮರು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಹಾರ್ಡ್ವೇರ್ ನಿರ್ವಹಿಸಿ"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ಬಳಕೆಗೆ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಟೆಂಪ್ಲೇಟ್ಗಳನ್ನು ಸೇರಿಸಲು ಮತ್ತು ಅಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಮನವಿ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಹಾರ್ಡ್ವೇರ್ ಬಳಸಿ"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಹಾರ್ಡ್ವೇರ್ ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ರೀಡ್ ಮಾಡು"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ಒಂದು ಖಾತೆಯ ಸಿಂಕ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ನೀಡುತ್ತದೆ. ಉದಾಹರಣೆಗೆ, ಖಾತೆಯೊಂದಿಗೆ ಜನರ ಅಪ್ಲಿಕೇಶನ್ ಸಿಂಕ್ ಮಾಡಲಾಗಿದೆಯೇ ಎಂಬುದನ್ನು ಇದು ನಿರ್ಧರಿಸಬಹುದು."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ಸಿಂಕ್ ಆನ್ ಮತ್ತು ಸಿಂಕ್ ಆಫ್ ಟಾಗಲ್ ಮಾಡಿ"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 2836671..faa69e6 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -940,14 +940,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Колдонмого Жакынкы аралыкта байланышуу (NFC) белгилери, карталары жана окугучтары менен байланышуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"экранды бөгөттөөнү өчүрүү"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Колдонмого экрандын бөгөттөөчү жана ага байланыштуу сырсөз коргоосун өчүрүү уруксатын берет. Мисалы, чалуу келгенде экрандын бөгөтүн алып салат, чалуу бүткөндө кайрадан орнотот."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"манжа изинин аппараттык камсыздоосун башкаруу"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Колдонмого пайдалануу үчүн манжа изинин үлгүлөрүн кошуу жана жок кылуу мүмкүндүгүн берет."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"манжа изинин аппараттык камсыздоосун колдонуу"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Колдонмого аныктыгын текшерүү үчүн манжа изинин аппараттык камсыздоосун пайдалануу мүмкүндүгүн берет"</string>
<!-- no translation found for permlab_readSyncSettings (6201810008230503052) -->
<skip />
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Колдонмого эсеп менен синхрондошуу тууралоолорун окуганга уруксат берет. Мисалы, Кишилер колдонмосу эсеп менен синхрондошкондугун аныктай алат."</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index ca4e2fe..80025e6 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"ອະນຸຍາດໃຫ້ແອັບຯຕິດຕໍ່ສື່ສານກັບປ້າຍກຳກັບ, ບັດ ແລະໂຕອ່ານຂອງການສື່ສານໄລຍະສັ້ນ (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"ປິດການລັອກໜ້າຈໍ"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"ອະນຸຍາດໃຫ້ແອັບຯປິດການເຮັດວຽກຂອງປຸ່ມລັອກ ແລະລະບົບຄວາມປອດໄພຂອງລະຫັດຜ່ານທີ່ເຊື່ອມໂຍງກັນ. ໂຕຢ່າງ: ໂທລະສັບຈະປິດການເຮັດວຽກຂອງປຸ່ມລັອກເມື່ອມີສາຍໂທເຂົ້າ ຈາກນັ້ນຈຶ່ງເປີດໃຊ້ໄດ້ອີກເມື່ອວາງສາຍແລ້ວ."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ຈັດການຮາດແວລາຍນີ້ວມື"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ອະນຸຍາດໃຫ້ແອັບເຮັດໃຫ້ວິທີການຕ່າງໆເພີ່ມ ແລະລຶບແມ່ແບບລາຍນີ້ວມືສຳລັບການໃຊ້."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"ໃຊ້ຮາດແວລາຍນີ້ວມື"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ອະນຸຍາດໃຫ້ແອັບນຳໃຊ້ຮາດແວລາຍນີ້ວມືສຳລັບການຮັບຮອງ"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ອ່ານການຕັ້ງຄ່າຊິ້ງຂໍ້ມູນ"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານການຕັ້ງຄ່າການຊິ້ງຂໍ້ມູນຂອງບັນຊີໄດ້. ຕົວຢ່າງເຊັ່ນ: ມັນຈະສາມາດກວດສອບໄດ້ແອັບຯ People ຖືກຊິ້ງຂໍ້ມູນກັບບັນຊີໃດນຶ່ງແລ້ວຫຼືຍັງ."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ສະລັບການເປີດ ແລະປິດການຊິ້ງຂໍ້ມູນ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 5c81e71..d1c2f9a 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -740,14 +740,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Leidžiama programai perduoti artimojo lauko ryšių technologijos (ALR) žymas, korteles ir skaitymo programas."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"išjungti ekrano užraktą"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Leidžiama programai neleisti klavišo užrakto ir visos susijusios slaptažodžio apsaugos. Pvz., telefonas neleidžia klavišo užrakto priimant gaunamąjį skambutį ir pakartotinai jį įgalina, kai skambutis baigiamas."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"tvarkyti kontrolinio kodo aparatinę įrangą"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Leidžiama programai aktyvinti metodus, norint pridėti ir ištrinti naudojamus kontrolinių kodų šablonus."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"naudoti kontrolinio kodo aparatinę įrangą"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Leidžiama programai naudoti kontrolinio kodo aparatinę įrangą tapatybei nustatyti"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"skaityti sinchronizavimo nustatymus"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Leidžiama programai skaityti ir sinchronizuoti paskyros nustatymus. Pvz., taip gali būti nustatoma, ar su paskyra sinchronizuota Žmonių programa."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"įjungti arba išjungti sinchronizavimą"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index f27832f..1f48ecf 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -739,14 +739,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Ļauj lietotnei sazināties ar tuva darbības lauka sakaru (Near Field Communication — NFC) atzīmēm, kartēm un lasītājiem."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"atspējot ekrāna bloķēšanu"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Ļauj lietotnei atspējot taustiņslēgu un visu saistīto paroļu drošību. Piemēram, tālrunis atspējo taustiņslēgu, saņemot ienākošu zvanu, un pēc zvana pabeigšanas atkārtoti iespējo taustiņslēgu."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"pārvaldīt pirkstu nospiedumu aparatūru"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Atļauj lietotnei izsaukt metodes izmantojamo pirkstu nospiedumu veidņu pievienošanai un dzēšanai."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"lietot pirkstu nospiedumu aparatūru"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Atļauj lietotnei izmantot pirkstu nospiedumu aparatūru autentificēšanai."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lasīt sinhronizācijas iestatījumus"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ļauj lietotnei lasīt konta sinhronizācijas iestatījumus. Piemēram, šādi var noteikt, vai lietotne Personas ir sinhronizēta ar kontu."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ieslēgt un izslēgt sinhronizāciju"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index f23cb42..4ee7a81 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Дозволува апликацијата да комуницира со ознаки, картички и читачи за Комуникација при непосредна близина (НФЦ)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"оневозможи заклучување на екран"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Овозможува апликацијата да го оневозможи заклучувањето и каква било безбедност поврзана со лозинка. На пример, телефонот го оневозможува заклучувањето при прием на телефонски повик, а потоа повторно го овозможува заклучувањето кога повикот ќе заврши."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"управувај хардвер за отпечатоци"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дозволува апликацијата да повика начини за додавање и бришење шаблони на отпечатоци за користење."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"користи хардвер за отпечатоци"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволува апликацијата да користи хардвер за отпечатоци за проверка"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"прочитај синхронизирани подесувања"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Овозможува апликацијата да ги чита подесувањата за синхронизирање на сметка. На пример, така може да се утврди дали апликацијата „Луѓе“ е синхронизирана со сметка."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"вклучи и исклучи синхронизација"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index 2a8b249..db538cd 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"നിയർ ഫീൽഡ് കമ്മ്യൂണിക്കേഷൻ (NFC) ടാഗുകളുമായും കാർഡുകളുമായും റീഡറുകളുമായുള്ള ആശയവിനിമയത്തിന് അപ്ലിക്കേഷനുകളെ അനുവദിക്കുന്നു."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"നിങ്ങളുടെ സ്ക്രീൻ ലോക്ക് പ്രവർത്തനരഹിതമാക്കുക"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"കീലോക്കും ഏതെങ്കിലും അനുബന്ധ പാസ്വേഡ് സുരക്ഷയും പ്രവർത്തനരഹിതമാക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഉദാഹരണത്തിന്, ഒരു ഇൻകമിംഗ് കോൾ സ്വീകരിക്കുമ്പോൾ ഫോൺ കീലോക്ക് പ്രവർത്തനരഹിതമാക്കുന്നു, കോൾ അവസാനിക്കുമ്പോൾ കീലോക്ക് വീണ്ടും പ്രവർത്തനക്ഷമമാകുന്നു."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"വിരലടയാള ഹാർഡ്വെയർ നിയന്ത്രിക്കുക"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ഉപയോഗിക്കാനായി വിരലടയാള ടെംപ്ലേറ്റുകൾ ചേർക്കാനും ഇല്ലാതാക്കാനുമുള്ള രീതികൾ അഭ്യർത്ഥിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"വിരലടയാള ഹാർഡ്വെയർ ഉപയോഗിക്കുക"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"പ്രാമാണീകരണത്തിനായി വിരലടയാളം ഉപയോഗിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യുക"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ഒരു അക്കൗണ്ടിനായി സമന്വയ ക്രമീകരണങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഉദാഹരണത്തിന്, ആളുകൾ അപ്ലിക്കേഷൻ ഒരു അക്കൗണ്ടിൽ സമന്വയിപ്പിച്ചിട്ടുണ്ടോയെന്നത് നിർണ്ണയിക്കാൻ ഇതിനാകും."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"സമന്വയം ഓണാക്കുക, ഓഫാക്കുക ടോഗിൾചെയ്യുക"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 6b2e3e8..9839ff1 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Апп нь Ойролцоо Талбарын Холболт(NFC) таг, карт, болон уншигчтай холбогдох боломжтой."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"дэлгэцний түгжээг идэвхгүй болгох"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Апп нь түгжээ болон бусад холбоотой нууц үгийн аюулгүй байдлыг идэвхгүй болгох боломжтой. Жишээ нь бол утас нь дуудлага ирэх үед түгжээг идэвхгүй болгох ба дуудлага дуусахад буцаан идэвхтэй болгодог."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"хурууны хээний програм хангамжийг удирдах"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Хурууны хээний загварыг нэмэх эсвэл усгтах үйлдлийг хийх зөвшөөрлийг програмд олгодог."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"хурууны хээний програм хангамжийг ашиглах"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Баталгаажуулалт хийх зорилгоор хурууны хээний програм хамгамжийг ашиглах зөвшөөрлийг програмд олгодог"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"синк тохиргоог унших"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Апп нь акаунтын синк тохиргоог унших боломжтой. Жишээ нь энэ нь Хүмүүс апп акаунттай синк хийгдсэн эсэхийг тодорхойлох боломжтой."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"синкийг унтрааж асаах тохиргоо"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index 4b1b4f33..493ae99 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"फील्ड जवळील संप्रेषण (NFC) टॅग, कार्ड आणि वाचक यांच्यासह संप्रेषण करण्यासाठी अॅप ला अनुमती देते."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"आपले स्क्रीन लॉक अक्षम करा"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"कीलॉक आणि कोणतीही संबद्ध संकेतशब्द सुरक्षितता अक्षम करण्यासाठी अॅप ला अनुमती देते. उदाहरणार्थ, येणारा फोन कॉल प्राप्त करताना फोन कीलॉक अक्षम करतो, नंतर जेव्हा कॉल समाप्त होतो तेव्हा तो कीलॉक पुन्हा-सक्षम करतो."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"फिंगरप्रिंट हार्डवेअर व्यवस्थापित करा"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"वापर करण्याकरिता फिंगरप्रिंट टेम्पलेट जोडण्यासाठी आणि हटविण्यासाठी पद्धती रद्द करण्यास अॅपला अनुमती देते."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"फिंगरप्रिंट हार्डवेअर वापरा"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"प्रमाणीकरणाकरिता फिंगरप्रिंट हार्डवेअरचा वापर करण्यासाठी अॅपला अनुमती देते"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"संकालन सेटिंग्ज वाचा"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"खात्याच्या संकालन सेटिंग्ज वाचण्यासाठी अॅप ला अनुमती देते. उदाहरणार्थ, हे खात्यासह लोकांचा अॅप संकालित केला आहे किंवा नाही हे निर्धारित करू शकते."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"संकालन चालू आणि बंद करा टॉगल करा"</string>
@@ -821,7 +817,7 @@
<string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"एका वाहक संदेशन सेवेसाठी प्रतिबद्ध"</string>
<string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"वाहक संदेशन सेवेचा शीर्ष-स्तर इंटरफेस प्रतिबद्ध करण्यासाठी होल्डरला अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यक नसते."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"संकेतशब्द नियम सेट करा"</string>
- <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रीन लॉक संकेतशब्द आणि PIN मध्ये अनुमती दिलेली लांबी आणि वर्ण नियंत्रित करा."</string>
+ <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रीन लॉक संकेतशब्द आणि पिन मध्ये अनुमती दिलेली लांबी आणि वर्ण नियंत्रित करा."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"स्क्रीन-अनलॉक प्रयत्नांचे परीक्षण करा"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"टाइप केलेल्या अयोग्य संकेतशब्दांच्या अंकांचे परीक्षण करा. स्क्रीन अनलॉक केली जाते, तेव्हा टॅब्लेट लॉक करा किंवा बरेच संकेतशब्द टाइप केले असल्यास टॅब्लेटचा सर्व डेटा मिटवा."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"स्क्रीन अनलॉक करताना टाइप केलेल्या चुकीच्या संकेतशब्दांच्या संख्येचे परीक्षण करा आणि टीव्ही लॉक करा किंवा अनेक चुकीचे संकेतशब्द टाइप केले असल्यास टीव्हीचा सर्व डेटा मिटवा."</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 1630868..7ed089c 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"appအား တာတို စက်ကွင်း ဆက်သွယ်ရေး (NFC) တဲဂ်များ၊ ကဒ်များ နှင့် ဖတ်ကြသူတို့နှင့် ဆက်သွယ်ပြောဆိုခွင့် ပြုသည်။"</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"ဖန်သားပြင် သော့ချခြင်းအား မလုပ်နိုင်အောင် ပိတ်ရန်"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"အပလီကေးရှင်းအား သော့ချခြင်းနှင့် သက်ဆိုင်ရာ စကားဝှက်သတ်မှတ်ခြင်းများအား မသုံးနိုင်အောင် ပိတ်ခြင်းကို ခွင့်ပြုရန်။ ဥပမာ ဖုန်းလာလျှင် သော့ပိတ်ခြင်း ပယ်ဖျက်ခြင်း၊ ဖုန်းပြောပြီးလျှင် သော့ကို အလိုအလျောက် ပြန်ပိတ်ခြင်း"</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"လက်ဗွေရာပစ္စည်းကို စီမံမည်"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"အသုံးပြုရန်အတွက် လက်ဗွေရာပုံစံများကို ပေါင်းထည့်ရန် သို့မဟုတ် ဖျက်ရန်နည်းလမ်းများကို အပ်ဖ်အား အသုံးပြုခွင့်ပြုသည်။"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"လက်ဗွေရာပစ္စည်းကို အသုံးပြုမည်"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"စစ်မှန်ကြောင်းအထောက်အထားပြသခြင်းအတွက် လက်ဗွေရာပစ္စည်းကို အသုံးပြုရန် အပ်ဖ်အားခွင့်ပြုသည်။"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ထပ်တူပြုအဆင်အပြင်အားဖတ်ခြင်း"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"အပလီကေးရှင်းအား အကောင့်တစ်ခုအတွက် ထပ်တူညီအောင် လုပ်ဆောင်မှု ဆက်တင်အား ကြည့်ခွင့် ပြုပါ။ ဥပမာ People app က အကောင့်တစ်ခုနဲ့ ထပ်တူညီအောင် လုပ်ရန် ဆက်သွယ်ထားမှု ရှိမရှိ သိရှိနိုင်ခြင်း"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ထပ်တူညီအောင် လုပ်ခြင်းအား ပြုနိုင်၊ မပြုနိုင် အပြောင်းအလဲလုပ်ခြင်း"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 4c9c1c4..f466da0 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Lar appen kommunisere med etiketter, kort og lesere som benytter NFC-teknologi."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivere skjermlåsen"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Lar appen deaktivere tastelåsen og eventuell tilknyttet passordsikkerhet. Et eksempel er at telefonen deaktiverer tastelåsen når du mottar et innkommende anrop, og deretter aktiverer tastelåsen igjen når samtalen er ferdig."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"administrere fingeravtrykkmaskinvare"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Lar appen fremkalle metoder for å legge til og slette fingeravtrykkmaler for bruk."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"bruke fingeravtrykkmaskinvare"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Lar appen bruke fingeravtrykkmaskinvare til godkjenning"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Lar appen lese synkroniseringsinnstillingene for en konto. For eksempel kan den finne ut om Personer-appen er synkronisert med en konto."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"slå synkronisering av og på"</string>
@@ -821,16 +817,16 @@
<string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"bind til en operatørmeldingstjeneste"</string>
<string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Tillater at innehaveren binder seg til det øverste nivået av grensesnittet til en operatørtjeneste. Dette skal aldri være nødvendig for vanlige apper."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
- <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollér tillatt lengde og tillatte tegn i passord og PIN-koder for opplåsing av skjermen."</string>
+ <string name="policydesc_limitPassword" msgid="2502021457917874968">"Kontrollerer tillatt lengde og tillatte tegn i passord og PIN-koder for opplåsing av skjermen."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Overvåk antall feil passordforsøk ved opplåsing av skjerm, og lås nettbrettet eller slett alle data fra nettbrettet ved for mange feil passordforsøk."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Overvåk antall feilaktige passord som er skrevet inn ved opplåsing av skjermen, og lås TV-en eller slett alle TV-data hvis feil passord skrives inn for mange ganger."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Overvåk antall feil passordforsøk ved opplåsing av skjerm, og lås telefonen eller slett alle data fra telefonen ved for mange feil passordforsøk."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Overvåk antallet feil passord skrevet inn ved opplåsing av skjermen, og lås nettbrettet eller slett denne brukerens data når for mange feil passord er skrevet inn."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Overvåk antallet feil passord skrevet inn ved opplåsing av skjermen, og lås TV-en eller slett denne brukerens data når for mange feil passord er skrevet inn."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Overvåk antallet feil passord skrevet inn ved opplåsing av skjermen, og lås telefonen eller slett denne brukerens data når for mange feil passord er skrevet inn."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Overvåker antallet feil passord som er skrevet inn når skjermen låses opp, og låser nettbrettet eller sletter denne brukerens data når for mange feil passord er skrevet inn."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Overvåker antallet feil passord som er skrevet inn når skjermen låses opp, og låser TV-en eller sletter denne brukerens data når for mange feil passord er skrevet inn."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Overvåker antallet feil passord som er skrevet inn når skjermen låses opp, og låser telefonen eller sletter denne brukerens data når for mange feil passord er skrevet inn."</string>
<string name="policylab_resetPassword" msgid="4934707632423915395">"Endre skjermlåsen"</string>
- <string name="policydesc_resetPassword" msgid="1278323891710619128">"Endre skjermlåsen."</string>
+ <string name="policydesc_resetPassword" msgid="1278323891710619128">"Endrer skjermlåsen."</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Lås skjermen"</string>
<string name="policydesc_forceLock" msgid="1141797588403827138">"Kontroller hvordan og når skjermen låses."</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"Slett alle data"</string>
@@ -838,19 +834,19 @@
<string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Slett TV-ens data uten advarsel ved å tilbakestille til fabrikkstandard."</string>
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Tilbakestill telefonens data uten advarsel, ved å tilbakestille til fabrikkstandard."</string>
<string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Slett brukerdataene"</string>
- <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"Slett denne brukerens data på dette nettbrettet uten advarsel."</string>
- <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"Slett denne brukerens data på denne TV-en uten advarsel."</string>
- <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"Slett denne brukerens data på denne telefonen uten advarsel."</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"Sletter denne brukerens data på dette nettbrettet uten advarsel."</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"Sletter denne brukerens data på denne TV-en uten advarsel."</string>
+ <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"Sletter denne brukerens data på denne telefonen uten advarsel."</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Angi enhetens globale mellomtjener"</string>
- <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Angi den globale proxy-tjeneren på enheten som skal brukes når regelen er aktivert. Bare eieren av enheten kan angi den globale proxy-tjeneren."</string>
+ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Angir den globale proxy-tjeneren på enheten som skal brukes når regelen er aktivert. Bare eieren av enheten kan angi den globale proxy-tjeneren."</string>
<string name="policylab_expirePassword" msgid="5610055012328825874">"Angi utløpstid for skjermlås"</string>
- <string name="policydesc_expirePassword" msgid="5367525762204416046">"Endre hvor lenge det skal gå før PIN-koden, passordet eller mønsteret til skjermlåsen må byttes."</string>
+ <string name="policydesc_expirePassword" msgid="5367525762204416046">"Endrer hvor ofte PIN-koden, passordet eller mønsteret til skjermlåsen skal byttes."</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Angi lagringskryptering"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Krev at lagrede appdata krypteres."</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"Deaktiver kameraer"</string>
<string name="policydesc_disableCamera" msgid="2306349042834754597">"Hindre bruk av alle kameraer på enheten."</string>
<string name="policylab_disableKeyguardFeatures" msgid="3565888260412415862">"Deaktiver skjermlåsfunksjoner"</string>
- <string name="policydesc_disableKeyguardFeatures" msgid="3980868516629887575">"Forhindre bruk av enkelte skjermlåsfunksjoner."</string>
+ <string name="policydesc_disableKeyguardFeatures" msgid="3980868516629887575">"Forhindrer bruk av enkelte skjermlåsfunksjoner."</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"Hjemmenummer"</item>
<item msgid="869923650527136615">"Mobil"</item>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 6ba83df..1d2e442 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -817,14 +817,14 @@
<string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"वाहक मेसेजिङ सेवामा आबद्ध हुनुहोस्"</string>
<string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"धारकलाई वाहक मेसेजिङ सेवाको उच्च-स्तरको इन्टरफेसमा आबद्ध हुन अनुमति दिनुहोस्। सामान्य एपहरूको लागि कहिल्यै आवश्यकता पर्दैन।"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
- <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाई र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
+ <string name="policydesc_limitPassword" msgid="2502021457917874968">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाइ र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"मोनिटर स्क्रिन-अनलक प्रयत्नहरू"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप भएको संख्या निरीक्षण गर्नुहोस् र यदि निकै धेरै गलत पासवर्डहरू टाइप भएका छन भने ट्याब्लेट लक गर्नुहोस् वा ट्याब्लेटका सबै डेटा मेट्नुहोस्।"</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"स्क्रिन अनलक गर्दा गलत पासवर्डका संख्या अनुगमन गर्नुहोस् र TV लक गर्नुहोस् वा TV को सबै डेटा मेट्नुहोस् यदि ज्यादै धेरै गलत पासवर्ड टाइप गरिएका छन् भने।"</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"स्क्रिनअनलक गर्दा गलत पासवर्ड टाइप भएको संख्या निरीक्षण गर्नुहोस् र यदि निकै धेरै गलत पासवर्डहरू टाइप भएका छन भने फोन लक गर्नुहोस् वा फोनका सबै डेटा मेट्नुहोस्।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरेमा ट्याब्लेट लक हुने वा प्रयोगकर्ताको डेटा मेटाउने निरीक्षण गर्नुहोस्।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरेमा टिभी लक हुने वा प्रयोगकर्ताको डेटा मेटाउने निरीक्षण गर्नुहोस्।"</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरेमा फोन लक हुने वा प्रयोगकर्ताको डेटा मेटाउने निरीक्षण गर्नुहोस्।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा ट्याब्लेट लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा TV लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा फोन लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
<string name="policylab_resetPassword" msgid="4934707632423915395">"स्क्रिन लक परिवर्तन गर्नुहोस्"</string>
<string name="policydesc_resetPassword" msgid="1278323891710619128">"स्क्रिन लक परिवर्तन गर्नुहोस्।"</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"स्क्रिन लक गर्नुहोस्।"</string>
@@ -835,12 +835,12 @@
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"एउटा फ्याक्ट्रि डेटा पुनःसेट गरेर चेतावनी नआउँदै फोनको डेटा मेट्नुहोस्।"</string>
<string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"प्रयोगकर्ता डेटा मेट्नुहोस्"</string>
<string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"चेतावनी बिना यो ट्याब्लेटमा यस प्रयोगकर्ताको डेटा मेट्नुहोस्।"</string>
- <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"चेतावनी बिना यो टिभीमा यो प्रयोगकर्ताको डेटा मेट्नुहोस्।"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"चेतावनी बिना यो TV मा यो प्रयोगकर्ताको डेटा मेट्नुहोस्।"</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"चेतावनी बिना यो फोनमा यस प्रयोगकर्ताको डेटा मेट्नुहोस्।"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"उपकरण विश्वव्यापी प्रोक्सी मिलाउनुहोस्"</string>
- <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"नीति सक्षम हुँदा प्रयोग हुनको लागि यन्त्र ग्लोवल प्रोक्सी सेट गर्नुहोस्। केवल यन्त्र मालिकले ग्लोवल प्रोक्सी सेट गर्न सक्नुहुन्छ।"</string>
- <string name="policylab_expirePassword" msgid="5610055012328825874">"स्क्रिन लक पासवर्ड समाप्ति सेट गर्नुहोस्"</string>
- <string name="policydesc_expirePassword" msgid="5367525762204416046">"स्क्रिन लक पासवर्ड, PIN, वा प्याटर्न परिवर्तन कसरी बारम्बार परिवर्तन हुनुपर्छ परिवर्तन गर्नुहोस्।"</string>
+ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"नीति सक्षम हुँदा प्रयोग गरिनको लागि यन्त्र ग्लोवल प्रोक्सी सेट गर्नुहोस्। केवल यन्त्र मालिकले ग्लोवल प्रोक्सी सेट गर्न सक्नुहुन्छ।"</string>
+ <string name="policylab_expirePassword" msgid="5610055012328825874">"स्क्रिन लक पासवर्ड म्याद समाप्ति सेट गर्नुहोस्"</string>
+ <string name="policydesc_expirePassword" msgid="5367525762204416046">"स्क्रिन लक पासवर्ड, PIN, वा ढाँचा परिवर्तन कसरी बारम्बार परिवर्तन हुनुपर्छ परिवर्तन गर्नुहोस्।"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"भण्डारण इन्क्रिप्सन मिलाउनुहोस्"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"भण्डार गरिएको डेटा इन्क्रिप्ट हुनु आवश्यक छ।"</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"क्यामेरालाई असक्षम गराउनुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index c98c484..2b4fe56 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Hiermee kan de app communiceren met NFC-tags (Near Field Communication), kaarten en lezers."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"uw schermvergrendeling uitschakelen"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Hiermee kan de app de toetsenblokkering en bijbehorende wachtwoordbeveiliging uitschakelen. Zo kan de telefoon de toetsenblokkering uitschakelen wanneer er een oproep binnenkomt en de toetsenblokkering weer inschakelen als de oproep is beëindigd."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"vingerafdrukhardware beheren"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Hiermee kan de app methoden aanroepen om vingerafdruksjablonen toe te voegen en te verwijderen voor gebruik."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"vingerafdrukhardware gebruiken"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Hiermee kan de app vingerafdrukhardware gebruiken voor verificatie"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"synchronisatie-instellingen lezen"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Hiermee kan de app de synchronisatie-instellingen voor een account lezen. Dit kan bijvoorbeeld bepalen of de app Personen wordt gesynchroniseerd met een account."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"synchronisatie in- en uitschakelen"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 7660342..feebdba 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -740,14 +740,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Pozwala aplikacji na komunikowanie się z tagami, kartami i czytnikami NFC (Near Field Communication)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"wyłączanie blokady ekranu"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Pozwala aplikacji na wyłączenie blokady klawiatury i wszystkich związanych z tym haseł zabezpieczających. Na przykład telefon wyłącza blokadę klawiatury, gdy odbiera połączenie przychodzące, a następnie włącza ją ponownie po zakończeniu połączenia."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"zarządzanie czytnikiem linii papilarnych"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Zezwala aplikacji aktywować metody dodawania i usuwania szablonów odcisków palców."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"używanie czytnika linii papilarnych"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Zezwala aplikacji na używanie czytnika linii papilarnych na potrzeby autoryzacji"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"czytanie ustawień synchronizacji"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Zezwala aplikacji na odczyt ustawień synchronizacji konta. Pozwala to na przykład określić, czy aplikacja Ludzie jest zsynchronizowana z kontem."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"włączanie i wyłączanie synchronizacji"</string>
@@ -904,7 +900,7 @@
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"Faks domowy"</string>
<string name="phoneTypePager" msgid="7582359955394921732">"Pager"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"Inny"</string>
- <string name="phoneTypeCallback" msgid="2712175203065678206">"Połączenie zwrotne"</string>
+ <string name="phoneTypeCallback" msgid="2712175203065678206">"Oddzwanianie"</string>
<string name="phoneTypeCar" msgid="8738360689616716982">"Samochód"</string>
<string name="phoneTypeCompanyMain" msgid="540434356461478916">"Firmowy główny"</string>
<string name="phoneTypeIsdn" msgid="8022453193171370337">"ISDN"</string>
@@ -1232,7 +1228,7 @@
<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 przez"</string>
+ <string name="whichSendApplication" msgid="6902512414057341668">"Udostępnij przez:"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Udostępnij przez %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Wybierz aplikację ekranu głównego"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Użyj %1$s jako ekranu głównego"</string>
@@ -1670,7 +1666,7 @@
<string name="kg_login_checking_password" msgid="1052685197710252395">"Sprawdzam konto"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> wpisałeś nieprawidłowy PIN. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> wpisałeś nieprawidłowe hasło. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
- <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> narysowałeś nieprawidłowy wzór odblokowania. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"<xliff:g id="NUMBER_0">%d</xliff:g> razy narysowałeś nieprawidłowy wzór odblokowania. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> próbowałeś nieprawidłowo odblokować tablet. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach tablet zostanie zresetowany do ustawień fabrycznych, a wszystkie dane użytkownika zostaną utracone."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Podałeś nieprawidłowe dane odblokowania telewizora <xliff:g id="NUMBER_0">%d</xliff:g> razy. Po jeszcze <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach telewizor zostanie zresetowany do stanu fabrycznego, a wszystkie dane użytkownika zostaną skasowane."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Po raz <xliff:g id="NUMBER_0">%d</xliff:g> próbowałeś nieprawidłowo odblokować telefon. Po kolejnych <xliff:g id="NUMBER_1">%d</xliff:g> nieudanych próbach telefon zostanie zresetowany do ustawień fabrycznych, a wszystkie dane użytkownika zostaną utracone."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index de7e72a..4668792 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Permite que a aplicação comunique com etiquetas, cartões e leitores Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"desativar o bloqueio do ecrã"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite que a aplicação desative o bloqueio de teclas e qualquer segurança por palavra-passe associada. Por exemplo, o telemóvel desativa o bloqueio de teclas quando recebe uma chamada e reativa o bloqueio de teclas ao terminar a chamada."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"gerir o hardware de impressão digital"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que a aplicação invoque métodos para adicionar e eliminar modelos de impressão digital para utilização."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizar o hardware de impressão digital"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite que a aplicação utilize o hardware de impressão digital para autenticação"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler definições de sincronização"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite que a aplicação leia as definições de sincronização de uma conta. Por exemplo, pode determinar se a aplicação Pessoas está sincronizada com uma conta."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ativar e desativar a sincronização"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index ea02d30..0c9b2ba 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1007,7 +1007,7 @@
<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>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"O cartão SIM está bloqueado."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Desbloqueando o cartão SIM…"</string>
- <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Você desenhou seu padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes.\n\nTente novamente em <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
<string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear seu tablet.\n\n Tente novamente em <xliff:g id="NUMBER_2">%d</xliff:g> segundos."</string>
@@ -1368,7 +1368,7 @@
<string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"Se você ativar o armazenamento USB, alguns apps que estão em uso serão interrompidos e poderão ficar indisponíveis até você desativar o armazenamento USB."</string>
<string name="dlg_error_title" msgid="7323658469626514207">"Falha na operação do USB"</string>
<string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
- <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como um dispositivo de mídia"</string>
+ <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Conectado como disp. de mídia"</string>
<string name="usb_ptp_notification_title" msgid="1960817192216064833">"Conectado como câmera"</string>
<string name="usb_midi_notification_title" msgid="1399152904227676460">"Conectado como dispositivo MIDI"</string>
<string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Conectados como um instalador"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index e841dda..0dda24e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -739,14 +739,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Permite aplicaţiei să comunice cu etichetele, cardurile şi cititoarele NFC (Near Field Communication)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"dezactivează blocarea ecranului"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite aplicaţiei să dezactiveze blocarea tastelor şi orice modalitate asociată de securizare prin parolă. De exemplu, telefonul dezactivează blocarea tastelor când se primeşte un apel telefonic şi reactivează blocarea tastelor la terminarea apelului."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"gestionează hardware-ul pentru amprentă"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite aplicației să invoce metode pentru a adăuga și pentru a șterge șabloane de amprentă pentru utilizare."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"folosește hardware-ul pentru amprentă"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Permite aplicației să folosească hardware pentru amprentă pentru autentificare"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"citire setări sincronizare"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permite aplicaţiei să citească setările de sincronizare ale unui cont. De exemplu, cu această permisiune aplicaţia poate determina dacă aplicaţia Persoane este sincronizată cu un anumit cont."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activează/dezactivează sincronizarea"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index e87f1a3..960fb1e 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"ආසන්න ක්ෂේත්ර සන්නිවේදන (NFC) ටැග්, පත්, සහ කියවන්නන් සමඟ සන්නිවේදනය කිරීමට යෙදුමට අවසර දෙන්න."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"ඔබගේ තිරයේ අගුල අබල කරන්න"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"යතුරු අගුල සහ ඕනෑම සම්බන්ධිත මුරපද ආරක්ෂාවක් අබල කිරීමට යෙදුමට අවසර දෙන්න. මෙහි උදාහරණයක් වන්නේ පැමිණෙන ඇමතුමක් ලැබෙද්දී, දුරකථනය අක්රිය වන අතර ඇමතුම අවසාන වන විට යතුරු අගුල නැවත සක්රිය වෙයි."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ඇඟිලි සලකුණු දෘඩාංග කළමනාකරණය කිරීම."</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ඇඟිලි සලකුණු සැකිලි එක් කිරීමට සහ ඉවත් කිරීමට අදාළ විධික්රම භාවිතය සඳහා මෙම යෙදුමට අවසර දෙයි."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"ඇඟිලි සලකුණු දෘඩාංග භාවිතා කරන්න."</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"අනන්යතාවය තහවුරු කරගැනීමට ඇඟිලි සලකුණු දෘඩාංග භාවිතා කිරීමට මෙම යෙදුමට ඉඩ දෙන්න."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"සමමුහුර්ත සැකසීම් කියවන්න"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ගිණුම සඳහා සමමුහුර්ත සැකසීම් කියවීමට යෙදුමට අවසර දෙන්න. උදාහරණයක් ලෙස, ගිණුමක් සමඟ පුද්ගල යෙදුම සමමුහුර්ත දැයි මෙයට හඳුනා ගත හැක."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"සමමුහුර්ත කිරීම සක්රිය කරන්න සහ අක්රිය කරන්න"</string>
@@ -826,7 +822,7 @@
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"තිරය අගුළු හැරීමේදී වැරදියට ටයිප් කළ මුරපද ගණන නිරීක්ෂණය කරන්න සහ ටැබ්ලටය අගුළු දමන්න හෝ වැරදි මුරපද බොහෝ ගණනක් ටයිප් කර ඇති නම් ටැබ්ලටයේ සියලු දත්ත මකන්න."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"තීරය අගුළු අරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිර්ක්ෂණය කරන්න, සහ බොහෝ විටක් වැරදි මුරපද ටයිප් කළේ නම් රුපවාහිනීය අගුළු දමන්න හෝ සියළුම රුපවාහිනී දත්ත මකන්න."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"තිරය අගුළු හැරීමේදී වැරදියට ටයිප් කළ මුරපද ගණන නිරීක්ෂණය කරන්න සහ දුරකථනය අගුළු දමන්න හෝ වැරදි මුරපද බොහෝ ගණනක් ටයිප් කර ඇති නම් දුරකථනයේ සියලු දත්ත මකන්න."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් තල පරිගණකය අගුලු දමන්න නැතහොත් මෙම පරිශීලකයාගේ සියලු දත්ත මකන්න."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් ටැබ්ලටය අගුලු දමන්න නැතහොත් මෙම පරිශීලකයාගේ සියලු දත්ත මකන්න."</string>
<string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් TV අගුලු දමන්න නැතහොත් මෙම පරිශීලකයාගේ සියලු දත්ත මකන්න."</string>
<string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"තිරය අගුලු හරින විට වැරදියට මුරපදය ටයිප් කළ වාර ගණන නිරීක්ෂණය කර, ඉතා වැඩි වාර ගණනක් වැරදි මුරපද ටයිප් කළේ නම් දුරකථනය අගුලු දමන්න නැතහොත් මෙම පරිශීලකයාගේ සියලු දත්ත මකන්න."</string>
<string name="policylab_resetPassword" msgid="4934707632423915395">"තිර අගුල වෙනස් කරන්න"</string>
@@ -838,7 +834,7 @@
<string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"අනතුරු ඇඟවීමකින් තොරව කර්මාන්ත ශාලා දත්ත නැවත සැකසීමක් කිරීමෙන් රූපවාහිනියේ දත්ත මකා දමයි."</string>
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"කර්මාන්ත ශාලා දත්ත යළි පිහිටුවීමෙන් පසුව අනතුරු ඇඟවිමකින් තොරවම දුරකථන දත්ත මකා දමයි."</string>
<string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"පරිශීලක දත්ත මකන්න"</string>
- <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"අනතුරු ඇඟවීමකින් තොරව මෙම තල පරිගණකයෙහි මෙම පරිශීලකයාගේ දත්ත මැකීම."</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"අනතුරු ඇඟවීමකින් තොරව මෙම ටැබ්ලටයෙහි මෙම පරිශීලකයාගේ දත්ත මැකීම."</string>
<string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"අනතුරු ඇඟවීමකින් තොරව මෙම TV හි මෙම පරිශීලකයාගේ දත්ත මැකීම."</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"අනතුරු ඇඟවීමකින් තොරව මෙම දුරකථනයෙහි මෙම පරිශීලකයාගේ දත්ත මැකීම."</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"උපාංග ගෝලීය නියුතුව සකස් කිරීම"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c181881..bae9b63 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -740,14 +740,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie NFC."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivácia zámky obrazovky"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Umožňuje aplikácii zakázať uzamknutie klávesnice a akékoľvek súvisiace zabezpečenie heslom. Príkladom je zakázanie uzamknutia klávesnice pri prichádzajúcom telefonickom hovore a jeho opätovné povolenie po skončení hovoru."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"spravovať hardvér na snímanie odtlačkov prstov"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Umožňuje aplikácii zavolať metódy, ktoré pridávajú a odstraňujú vzory odtlačkov prstov."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"použiť hardvér na snímanie odtlačkov prstov"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Umožňuje aplikácii používať na overenie totožnosti hardvér na snímanie odtlačkov prstov."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítať nastavenia synchronizácie"</string>
<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>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 0f8d208..e1f15dd 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -740,14 +740,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Podpira komunikacijo med računalnikom in oznakami, karticami in bralniki komunikacije s tehnologijo bližnjega polja."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"onemogočanje zaklepanja zaslona"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Aplikaciji dovoljuje, da onemogoči zaklep tipkovnice in morebitno povezano varnostno geslo. Telefon na primer onemogoči zaklep tipkovnice pri dohodnem klicu ter vnovič omogoči zaklep, ko je klic končan."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"upravljanje strojne opreme za prstne odtise"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Aplikaciji omogoča sprožanje načinov za dodajanje in brisanje predlog s prstnimi odtisi za uporabo."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"uporaba strojne opreme za prstne odtise"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Aplikaciji omogoča uporabo strojne opreme za prstne odtise za preverjanje pristnosti"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"branje nastavitev sinhronizacije"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Aplikaciji omogoča branje nastavitev sinhronizacije za račun. S tem lahko aplikacija na primer ugotovi, ali je aplikacija Ljudje sinhronizirana z računom."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"vklop in izklop sinhronizacije"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index dd9c4ad..ecf1958 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -739,14 +739,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Дозвољава апликацији да комуницира са ознакама, картицама и читачима комуникације кратког домета (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"онемогућавање закључавања екрана"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Дозвољава апликацији да онемогући закључавање тастатуре и све повезане безбедносне мере са лозинкама. На пример, телефон онемогућава закључавање тастатуре при пријему долазног телефонског позива, а затим га поново омогућава по завршетку позива."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"управљај хардвером за отиске прстију"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Дозвољава апликацији да активира методе за додавање и брисање шаблона отисака прстију који ће се користити."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"користи хардвер за отиске прстију"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозвољава апликацији да користи хардвер за отиске прстију ради потврде аутентичности"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"читање подешавања синхронизације"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Дозвољава апликацији да чита подешавања синхронизације за налог. На пример, овако може да се утврди да ли је апликација Људи синхронизована са налогом."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"укључивање и искључивање синхронизације"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d959a66..26a1343 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Tillåter att appen kommunicerar med etiketter, kort och läsare för närfältskommunikation (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"inaktivera skärmlåset"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Tillåter att appen inaktiverar tangentlåset och tillhörande lösenordsskydd. Ett exempel kan vara att tangentlåset inaktiveras vid inkommande samtal och aktiveras igen när samtalet är avslutat."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"hantera maskinvara för fingeravtryck"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Tillåter att appen anropar metoder för att lägga till och radera fingeravtrycksmallar."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"använda maskinvara för fingeravtryck"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Tillåter att appen använder maskinvara för fingeravtryck vid autentisering"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"läsa synkroniseringsinställningar"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Tillåter att appen läser synkroniseringsinställningarna för ett konto. Detta kan användas till exempel för att avgöra om appen Personer är synkroniserad med ett konto."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"aktivera/inaktivera synkronisering"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index af8c799..82791e5 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Inaruhusu programu kuwasiliana na lebo, kadi na wasomaji wa Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"zima kufuli la skrini yako"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Inaruhusu programu kulemaza ufunguo wa vitufe na usalama mwingine ambata wa nenosiri. Kwa mfano, simu inalemaza ufunguo wa viitufe inapopokea simu inayoingia, kisha inawezesha upya ufunguo wa vitufe wakati simu inapokamilika."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"dhibiti maunzi ya kitambulisho"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Huruhusu programu kuomba njia za kuongeza na kufuta violezo vya kitambulisho kwa matumizi."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"tumia maunzi ya kitambulisho"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Huruhusu programu kutumia maunzi ya kitambulisho kwa uthibitisho"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"kusoma mipangilio ya usawazishaji"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Inaruhusu programu kusoma mipangilio ya upatanishi wa akaunti. Kwa mfano, huku kunaweza kuamua kama programu ya Watu imepatanishwa na akaunti."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"kuwasha na kuzima usawazishaji"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index e22beb1..fe4faf0 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"குறுகிய இடைவெளி தகவல்பரிமாற்றம் (NFC), குறிகள், கார்டுகள் மற்றும் ரீடர்கள் ஆகியவற்றுடன் தொடர்புகொள்ள, பயன்பாட்டை அனுமதிக்கிறது."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"உங்கள் திரைப் பூட்டை முடக்குதல்"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"விசைப்பூட்டையும், தொடர்புடைய கடவுச்சொல் பாதுகாப்பையும் முடக்கப் பயன்பாட்டை அனுமதிக்கிறது. எடுத்துக்காட்டாக, உள்வரும் மொபைல் அழைப்பைப் பெறும்போது மொபைல் விசைப்பூட்டை முடக்குகிறது, பிறகு அழைப்பு முடிந்தவுடன் விசைப்பூட்டை மீண்டும் இயக்குகிறது."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"கைரேகை வன்பொருளை நிர்வகி"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"பயன்படுத்துவதற்காக, கைரேகை டெம்ப்ளேட்களைச் சேர்க்க மற்றும் நீக்குவதற்கான செயல்முறைகளை இயக்குவதற்குப் பயன்பாட்டை அனுமதிக்கும்."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"கைரேகை வன்பொருளைப் பயன்படுத்து"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"அங்கீகரிப்பதற்கு, கைரேகை வன்பொருளைப் பயன்படுத்த, பயன்பாட்டை அனுமதிக்கும்"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"ஒத்திசைவு அமைப்புகளைப் படித்தல்"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"கணக்கிற்கான ஒத்திசைவு அமைப்புகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது. எடுத்துக்காட்டாக, பீப்பிள் பயன்பாடு கணக்குடன் ஒத்திசைக்கப்பட்டுள்ளதா என்பதை இது தீர்மானிக்கலாம்."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ஒத்திசைவை இயக்குவதையும், முடக்குவதையும் மாற்றுதல்"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index caa5725..eec41de9 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"సమీప ఫీల్డ్ కమ్యూనికేషన్ (NFC) ట్యాగ్లు, కార్డులు మరియు రీడర్లతో కమ్యూనికేట్ చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"మీ స్క్రీన్ లాక్ను నిలిపివేయడం"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"కీలాక్ మరియు ఏదైనా అనుబంధించబడిన పాస్వర్డ్ భద్రతను నిలిపివేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఉదాహరణకు, ఇన్కమింగ్ ఫోన్ కాల్ వస్తున్నప్పుడు ఫోన్ కీలాక్ను నిలిపివేస్తుంది, ఆపై కాల్ ముగిసిన తర్వాత కీలాక్ను మళ్లీ ప్రారంభిస్తుంది."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"వేలిముద్ర హార్డ్వేర్ని నిర్వహించడానికి అనుమతి"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"వినియోగం కోసం వేలిముద్ర టెంప్లేట్లను జోడించే మరియు తొలగించే పద్ధతులను అమలు చేయడానికి అనువర్తనాన్ని అనుమతిస్తుంది."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"వేలిముద్ర హార్డ్వేర్ని ఉపయోగించడానికి అనుమతి"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ప్రామాణీకరణ కోసం వేలిముద్ర హార్డ్వేర్ను ఉపయోగించడానికి అనువర్తనాన్ని అనుమతిస్తుంది"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"సమకాలీకరణ సెట్టింగ్లను చదవడం"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ఖాతా యొక్క సమకాలీకరణ సెట్టింగ్లను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఉదాహరణకు, వ్యక్తుల అనువర్తనం ఖాతాతో సమకాలీకరించబడాలా లేదా అనే విషయాన్ని ఇది నిశ్చయించవచ్చు."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"సమకాలీకరణను ఆన్ మరియు ఆఫ్కు టోగుల్ చేయడం"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index c9f07b5..6e0d4fc 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Pinapayagan ang app na makipag-ugnay sa Near Field Communication (NFC) na mga tag, card, at reader."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"huwag paganahin ang iyong lock ng screen"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Pinapayagan ang app na huwag paganahin ang keylock at anumang nauugnay na seguridad sa password. Halimbawa, hindi pinapagana ng telepono ang keylock kapag nakakatanggap ng papasok na tawag sa telepono, pagkatapos ay muling pinapagana ang keylock kapag tapos na ang tawag."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"pamahalaan ang hardware ng fingerprint"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Pinapayagan ang app na mag-invoke ng mga paraan upang magdagdag at mag-delete ng mga template ng fingerprint na magagamit."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"gamitina ng hardware ng fingerprint"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Pinapayagan ang app na gumamit ng hardware ng fingerprint para sa pagpapatotoo"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"basahin ang mga setting ng sync"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Pinapayagan ang app na basahin ang mga setting ng pag-sync para sa isang account. Halimbawa, matutukoy nito kung naka-sync ang app na Mga Tao sa isang account."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"I-toggle on at off ang pag-sync"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 54df4fd..a49d93d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Uygulamaya, Near Field Communication (NFC) etiketleri, kartlar ve okuyucular ile iletişim kurma izni verir."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"ekran kilidimi devre dışı bırak"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Uygulamaya, tuş kilidini ve ilişkili tüm şifreli güvenlik önlemlerini devre dışı bırakma izni verir. Örneğin, telefon, çağrı alındığında tuş kilidinin devre dışı bırakır ve sonra, görüşme bittiğinde kilidi yeniden etkinleştirir."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"parmak izi donanımını yönetme"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Uygulamanın, kullanılacak parmak izi şablonlarını ekleme ve silme yöntemlerini başlatmasına izin verir."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"parmak izi donanımını kullanma"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Uygulamanın kimlik doğrulama için parmak izi donanımını kullanmasına izin verir."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"senk. ayarlarını okuma"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Uygulamaya bir hesaba ait senkronizasyon ayarlarını okuma izni verir. Örneğin, bu izne sahip bir uygulama Kişiler uygulamasının bir hesapla senkronize olup olmadığını belirleyebilir."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"senkronizasyonu açma/kapatma"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 7171633..4fc776d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -740,14 +740,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Дозволяє програмі обмінюватися даними з тегами, картками та читачами екрана Near Field Communication (NFC)."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"вимикати блокування екрана"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Дозволяє програмі вимикати блокування клавіатури та будь-який пов’язаний паролем захист. Наприклад: телефон вимикає блокування клавіатури під час отримання вхідного дзвінка, після закінчення якого блокування клавіатури відновлюється."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"керувати апаратним забезпеченням для цифрових відбитків"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Увімкнути в додатку функції для додавання й видалення шаблонів цифрових відбитків."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"користуватися апаратним забезпеченням для цифрових відбитків"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Дозволити додатку використовувати апаратне забезпечення для автентифікації"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"читати налаштування синхронізації"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Дозволяє програмі читати налаштування синхронізації для облікового запису, наприклад, визначати, чи програма Люди синхронізується з обліковим записом."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"вмикати й вимикати синхронізацію"</string>
@@ -828,9 +824,9 @@
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Відстежувати кількість неправильних паролів, введених під час розблокування екрана, і блокувати планшетний ПК або стирати всі його дані, якщо введено забагато неправильних паролів."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Відстежувати кількість неправильних паролів, введених під час розблокування екрана, і блокувати телевізор або стирати всі його дані, якщо пароль введено неправильно забагато разів."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Відстежувати кількість неправильних паролів, введених під час розблокування екрана, і блокувати телефон або стирати всі його дані, якщо введено забагато неправильних паролів."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана, і блокуйте планшет або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана, і блокуйте телевізор або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана, і блокуйте телефон або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана. Блокуйте планшет або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана. Блокуйте телевізор або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Відстежуйте кількість неправильних паролів, введених під час розблокування екрана. Блокуйте телефон або стирайте всі його дані, якщо пароль введено неправильно забагато разів."</string>
<string name="policylab_resetPassword" msgid="4934707632423915395">"Змінення пароля розблокування екрана"</string>
<string name="policydesc_resetPassword" msgid="1278323891710619128">"Змініть пароль розблокування екрана."</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Блокувати екран"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 094f5e4..adc11a6 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"ایپ کو Near Field Communication (NFC) ٹیگز، کارڈز اور ریڈرز کے ساتھ مواصلت کرنے کی اجازت دیٹا ہے۔"</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"اپنے اسکرین لاک کو غیر فعال کریں"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"ایپ کو کلیدی لاک اور کسی بھی متعلقہ پاس ورڈ سیکیورٹی کو غیر فعال کرنے کی اجازت دیتا ہے۔ مثلاً، کوئی آنے والی فون کال موصول ہونے کے وقت فون کلیدی لاک کو غیر فعال کرتا ہے، پھر کال پوری ہوجانے پر کلیدی لاک کو دوبارہ فعال کردیتا ہے۔"</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"فنگر پرنٹ ہارڈ ویئر کا نظم کریں"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ایپ کو استعمال کیلئے فنگر پرنٹ کی تمثیلات شامل کرنے اور حذف کرنے کیلئے طریقوں کو کالعدم قرار دینے کی اجازت دیتا ہے۔"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"فنگر پرنٹ ہارڈ ویئر استعمال کریں"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ایپ کو توثیق کیلئے فنگر پرنٹ ہارڈ ویئر استعمال کرنے کی اجازت دیتا ہے"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"مطابقت پذیری کی ترتیبات پڑھیں"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ایپ کو کسی اکاؤنٹ کیلئے مطابقت پذیری کی ترتیبات پڑھنے کی اجازت دیتا ہے۔ مثلا، یہ تعین کرسکتا ہے کہ آیا People ایپ کسی اکاؤنٹ کے ساتھ مطابقت پذیر ہے۔"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"مطابقت پذیری آن اور آف ٹوگل کریں"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index a62cd31..27237f5 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Ilova qisqa masofali aloqa (NFC) texnologiyasi yordamida NFC yorliqlari, kartalar va o‘qish moslamalari bilan ma’lumot almashishi mumkin."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"ekran qulfini o‘chirib qo‘yish"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Ilovaga ekran qulfini va har qanday parol yordamidagi xavfsizlik himoyalarini o‘chirishga ruxsat beradi. Masalan, kirish qo‘ng‘irog‘ida telefon ekran qulfini o‘chiradi va qo‘ng‘iroq tugashi bilan qulfni yoqadi."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"barmoq izi sensorini boshqarish"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Ilova foydalanish uchun barmoq izi namunalarini qo‘shish va o‘chirish usullarini qo‘llashi mumkin."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"barmoq izi sensoridan foydalanish"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Ilova haqiqiylikni tekshirish uchun barmoq izi sensoridan foydalanishi mumkin"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"sinx-sh sozlamalarini o‘qish"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ilovaga hisobning sinxronlash sozlamalarini o‘qish uchun ruxsat beradi. Masalan, bu \"Odamlar\" ilovasi hisob bilan sinxronlangan yoki aksini aniqlay oladi."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"sinx.ni yoqish/o‘chirish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8784626..ce5fc5a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"Cho phép ứng dụng giao tiếp với thẻ Giao tiếp trường gần (NFC), thẻ và trình đọc."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"vô hiệu hóa khóa màn hình của bạn"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Cho phép ứng dụng tắt khóa phím và bất kỳ bảo mật mật khẩu được liên kết nào. Ví dụ: điện thoại tắt khóa phím khi nhận được cuộc gọi đến, sau đó bật lại khóa phím khi cuộc gọi kết thúc."</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"quản lý phần cứng vân tay"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Cho phép ứng dụng gọi các phương pháp để thêm và xóa các mẫu vân tay để sử dụng."</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"sử dụng phần cứng vân tay"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Cho phép ứng dụng sử dụng phần cứng vân tay để xác thực"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"đọc cài đặt đồng bộ hóa"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Cho phép ứng dụng đọc cài đặt đồng bộ hóa cho tài khoản. Ví dụ: việc này có thể xác định liệu ứng dụng Mọi người đã được đồng bộ hóa với tài khoản chưa."</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"chuyển đổi bật và tắt đồng bộ hóa"</string>
@@ -826,9 +822,9 @@
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Theo dõi số lần nhập mật khẩu không chính xác khi mở khóa màn hình và khóa máy tính bảng hoặc xóa tất cả dữ liệu của máy tính bảng nếu có quá nhiều lần nhập mật khẩu không chính xác."</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Giám sát số lượng mật khẩu đã nhập sai khi mở khóa màn hình và khóa TV hoặc xóa tất cả dữ liệu của TV nếu có quá nhiều mật khẩu sai được nhập vào."</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Theo dõi số lần nhập mật khẩu không chính xác khi mở khóa màn hình và khóa điện thoại hoặc xóa tất cả dữ liệu của điện thoại nếu có quá nhiều lần nhập mật khẩu không chính xác."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Giám sát số lượng mật khẩu đã nhập sai khi mở khóa màn hình và khóa máy tính bảng hoặc xóa tất cả dữ liệu của người dùng này nếu có quá nhiều mật khẩu sai được nhập vào."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Giám sát số lượng mật khẩu đã nhập sai khi mở khóa màn hình và khóa TV hoặc xóa tất cả dữ liệu của người dùng này nếu có quá nhiều mật khẩu sai được nhập vào."</string>
- <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Giám sát số lượng mật khẩu đã nhập sai khi mở khóa màn hình và khóa điện thoại hoặc xóa tất cả dữ liệu của người dùng này nếu có quá nhiều mật khẩu sai được nhập vào."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"Giám sát số lần nhập sai mật khẩu khi mở khóa màn hình và khóa máy tính bảng hoặc xóa tất cả dữ liệu của người dùng này nếu nhập sai mật khẩu quá nhiều lần."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"Giám sát số lần nhập sai mật khẩu khi mở khóa màn hình và khóa TV hoặc xóa tất cả dữ liệu của người dùng này nếu nhập sai mật khẩu quá nhiều lần."</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"Giám sát số lần nhập sai mật khẩu khi mở khóa màn hình và khóa điện thoại hoặc xóa tất cả dữ liệu của người dùng này nếu nhập sai mật khẩu quá nhiều lần."</string>
<string name="policylab_resetPassword" msgid="4934707632423915395">"Thay đổi khóa màn hình"</string>
<string name="policydesc_resetPassword" msgid="1278323891710619128">"Thay đổi khóa màn hình."</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Khóa màn hình"</string>
@@ -842,7 +838,7 @@
<string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"Xóa dữ liệu của người dùng trên TV này mà không cảnh báo."</string>
<string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"Xóa dữ liệu của người dùng trên điện thoại này mà không cảnh báo."</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Đặt proxy chung của điện thoại"</string>
- <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Đặt proxy chung của thiết bị được sử dụng trong khi chính sách được bật. Chỉ chủ sở hữu thiết bị mới có thể đặt proxy chung."</string>
+ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Đặt proxy chung của thiết bị được sử dụng trong khi chính sách bật. Chỉ chủ sở hữu thiết bị mới có thể đặt proxy chung."</string>
<string name="policylab_expirePassword" msgid="5610055012328825874">"Đặt thời hạn MK khóa màn hình"</string>
<string name="policydesc_expirePassword" msgid="5367525762204416046">"Thay đổi tần suất phải thay đổi mật khẩu khóa màn hình, mã PIN hoặc mẫu."</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Đặt mã hóa dung lượng lưu trữ"</string>
diff --git a/core/res/res/values-watch/strings.xml b/core/res/res/values-watch/strings.xml
new file mode 100644
index 0000000..4ea2b52
--- /dev/null
+++ b/core/res/res/values-watch/strings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- [CHAR LIMIT=16] Message shown in upgrading dialog for each .apk that is optimized. -->
+ <!-- Each word has an 8 character limit due to screen width limitation. -->
+ <string name="android_upgrading_apk">App
+ <xliff:g id="number" example="123">%1$d</xliff:g> of
+ <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
+</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index addf9ec..507e530 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -821,51 +821,36 @@
<string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"绑定到运营商消息传递服务"</string>
<string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"允许应用绑定到运营商消息传递服务的顶级接口。普通应用绝不需要此权限。"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
- <!-- no translation found for policydesc_limitPassword (2502021457917874968) -->
- <skip />
+ <string name="policydesc_limitPassword" msgid="2502021457917874968">"控制锁屏密码和 PIN 码所允许的长度和字符。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"监视在解锁屏幕时输错密码的次数,如果输错次数过多,则锁定平板电脑或清除其所有数据。"</string>
<string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定电视或清除电视上的所有数据。"</string>
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"监视在解锁屏幕时输错密码的次数,如果输错次数过多,则锁定手机或清除其所有数据。"</string>
- <!-- no translation found for policydesc_watchLogin_secondaryUser (4280246270601044505) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin_secondaryUser (3484832653564483250) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin_secondaryUser (2185480427217127147) -->
- <skip />
- <!-- no translation found for policylab_resetPassword (4934707632423915395) -->
- <skip />
- <!-- no translation found for policydesc_resetPassword (1278323891710619128) -->
- <skip />
+ <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定平板电脑或清空此用户的所有数据。"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定电视或清空此用户的所有数据。"</string>
+ <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定手机或清空此用户的所有数据。"</string>
+ <string name="policylab_resetPassword" msgid="4934707632423915395">"更改锁屏密码"</string>
+ <string name="policydesc_resetPassword" msgid="1278323891710619128">"更改锁屏密码。"</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="tv" msgid="5816221315214527028">"恢复出厂设置时,不发出警告就直接清除电视上的数据。"</string>
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"恢复出厂设置时,系统会在不发出警告的情况下清除手机上的数据。"</string>
- <!-- no translation found for policylab_wipeData_secondaryUser (8362863289455531813) -->
- <skip />
- <!-- no translation found for policydesc_wipeData_secondaryUser (6336255514635308054) -->
- <skip />
- <!-- no translation found for policydesc_wipeData_secondaryUser (2086473496848351810) -->
- <skip />
- <!-- no translation found for policydesc_wipeData_secondaryUser (6787904546711590238) -->
- <skip />
+ <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"清空用户数据"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"清空此用户在这台平板电脑上的数据,而不事先发出警告。"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"清空此用户在这台电视上的数据,而不事先发出警告。"</string>
+ <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"清空此用户在这部手机上的数据,而不事先发出警告。"</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"设置设备全局代理"</string>
- <!-- no translation found for policydesc_setGlobalProxy (8459859731153370499) -->
- <skip />
- <!-- no translation found for policylab_expirePassword (5610055012328825874) -->
- <skip />
- <!-- no translation found for policydesc_expirePassword (5367525762204416046) -->
- <skip />
+ <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"设置在规范启用时要使用的设备全局代理。只有设备所有者才能设置全局代理。"</string>
+ <string name="policylab_expirePassword" msgid="5610055012328825874">"设置锁屏密码的有效期"</string>
+ <string name="policydesc_expirePassword" msgid="5367525762204416046">"调整系统强制用户更改锁屏密码、PIN 码或解锁图案的频率。"</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"设置存储设备加密"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"要求对存储的应用数据进行加密。"</string>
<string name="policylab_disableCamera" msgid="6395301023152297826">"停用相机"</string>
<string name="policydesc_disableCamera" msgid="2306349042834754597">"禁止使用所有设备摄像头。"</string>
- <!-- no translation found for policylab_disableKeyguardFeatures (3565888260412415862) -->
- <skip />
- <!-- no translation found for policydesc_disableKeyguardFeatures (3980868516629887575) -->
- <skip />
+ <string name="policylab_disableKeyguardFeatures" msgid="3565888260412415862">"停用锁屏功能"</string>
+ <string name="policydesc_disableKeyguardFeatures" msgid="3980868516629887575">"禁止使用锁屏的部分功能。"</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"住宅"</item>
<item msgid="869923650527136615">"手机"</item>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 4503731..c60a1be 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"允許應用程式使用近距離無線通訊 (NFC) 標記、卡片及讀取程式進行通訊。"</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"停用螢幕上鎖"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全措施。例如:手機收到來電時停用按鍵鎖定,通話結束後重新啟用按鍵鎖定。"</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"管理指紋硬件"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"允許應用程式調用加入和刪除指紋模板的方法以供使用。"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"使用指紋硬件"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"允許應用程式使用指紋硬件驗證"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允許應用程式讀取帳戶的同步設定,例如確定「通訊錄」應用程式是否和某個帳戶保持同步。"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"開啟和關閉同步功能"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 98c334b..6925d9f 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -738,14 +738,10 @@
<string name="permdesc_nfc" msgid="7120611819401789907">"允許應用程式與近距離無線通訊 (NFC) 電子感應標籤、卡片及感應器進行通訊。"</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"停用螢幕鎖定"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全性功能。例如:手機收到來電時停用按鍵鎖定,通話結束後重新啟用按鍵鎖定。"</string>
- <!-- no translation found for permlab_manageFingerprint (5640858826254575638) -->
- <skip />
- <!-- no translation found for permdesc_manageFingerprint (178208705828055464) -->
- <skip />
- <!-- no translation found for permlab_useFingerprint (3150478619915124905) -->
- <skip />
- <!-- no translation found for permdesc_useFingerprint (9165097460730684114) -->
- <skip />
+ <string name="permlab_manageFingerprint" msgid="5640858826254575638">"管理指紋硬體"</string>
+ <string name="permdesc_manageFingerprint" msgid="178208705828055464">"允許應用程式呼叫方法來新增及移除可用的指紋範本"</string>
+ <string name="permlab_useFingerprint" msgid="3150478619915124905">"使用指紋硬體"</string>
+ <string name="permdesc_useFingerprint" msgid="9165097460730684114">"允許應用程式使用指紋硬體進行驗證"</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"允許應用程式讀取帳戶的同步處理設定,例如判斷「使用者」應用程式是否和某個帳戶進行同步處理。"</string>
<string name="permlab_writeSyncSettings" msgid="5408694875793945314">"開啟及關閉同步功能"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fd8b803..a383359 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -64,26 +64,11 @@
As of Honeycomb, blurring is not supported anymore. -->
<bool name="config_sf_slowBlur">true</bool>
- <!-- Flag indicating that the media framework should allow changing
- master volume stream and nothing else . -->
- <bool name="config_useMasterVolume">false</bool>
-
<!-- Flag indicating that the media framework should support playing of sounds on volume
key usage. This adds noticeable additional overhead to volume key processing, so
is disableable for products for which it is irrelevant. -->
<bool name="config_useVolumeKeySounds">true</bool>
- <!-- Array of integer pairs controlling the rate at which the master volume changes
- in response to volume up and down key events.
- The first integer of each pair is compared against the current master volume
- (in range 0 to 100).
- The last pair with first integer <= the current volume is chosen,
- and the second integer of the pair indicates the amount to increase the master volume
- when volume up is pressed. -->
- <integer-array name="config_masterVolumeRamp">
- <item>0</item> <item>5</item> <!-- default: always increase volume by 5% -->
- </integer-array>
-
<!-- The attenuation in dB applied to the sound effects played
through AudioManager.playSoundEffect() when no volume is specified. -->
<integer name="config_soundEffectVolumeDb">-6</integer>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d93d2c8..67ce159 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2354,6 +2354,11 @@
<string name="permdesc_bindNotificationListenerService">Allows the holder to bind to the top-level interface of a notification listener 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_bindChooserTargetService">bind to a chooser target 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_bindChooserTargetService">Allows the holder to bind to the top-level interface of a chooser target 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_bindConditionProviderService">bind to a condition provider 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_bindConditionProviderService">Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps.</string>
@@ -4983,8 +4988,14 @@
<!-- PIN entry dialog tells the user to not enter a PIN for a while. [CHAR LIMIT=none] -->
<string name="restr_pin_try_later">Try again later</string>
- <!-- Cling help message when hiding the navigation bar entering immersive mode [CHAR LIMIT=none] -->
- <string name="immersive_mode_confirmation" msgid="8554991488096662508">Swipe down from the top to exit full screen.</string>
+ <!-- Cling help message title when hiding the navigation bar entering immersive mode [CHAR LIMIT=none] -->
+ <string name="immersive_cling_title">Viewing full screen</string>
+
+ <!-- Cling help message description when hiding the navigation bar entering immersive mode [CHAR LIMIT=none] -->
+ <string name="immersive_cling_description">To exit, swipe down from the top.</string>
+
+ <!-- Cling help message confirmation button when hiding the navigation bar entering immersive mode [CHAR LIMIT=30] -->
+ <string name="immersive_cling_positive">Got it</string>
<!-- Label for button to confirm chosen date or time [CHAR LIMIT=30] -->
<string name="done_label">Done</string>
@@ -5049,7 +5060,7 @@
<!-- Notify use that they are in Lock-to-app in accessibility mode -->
<string name="lock_to_app_toast_accessible">To unpin this screen, touch and hold Overview.</string>
<!-- Notify user that they are locked in lock-to-app mode -->
- <string name="lock_to_app_toast_locked">Screen is pinned. Unpinning isn\'t allowed by your organization.</string>
+ <string name="lock_to_app_toast_locked">App is pinned: Unpinning isn\'t allowed on this device.</string>
<!-- Starting lock-to-app indication. -->
<string name="lock_to_app_start">Screen pinned</string>
<!-- Exting lock-to-app indication. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index c520a46..cc64b43 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -237,6 +237,12 @@
<item name="windowExitAnimation">@anim/fade_out</item>
</style>
+ <!-- Window animations used for immersive mode confirmation. -->
+ <style name="Animation.ImmersiveModeConfirmation">
+ <item name="windowEnterAnimation">@null</item>
+ <item name="windowExitAnimation">@anim/fast_fade_out</item>
+ </style>
+
<!-- Window animations for screen savers. {@hide} -->
<style name="Animation.Dream">
<item name="windowEnterAnimation">@anim/slow_fade_in</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 86e46f6b..078c12f 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -274,7 +274,6 @@
<java-symbol type="bool" name="preferences_prefer_dual_pane" />
<java-symbol type="bool" name="skip_restoring_network_selection" />
<java-symbol type="bool" name="split_action_bar_is_narrow" />
- <java-symbol type="bool" name="config_useMasterVolume" />
<java-symbol type="bool" name="config_useVolumeKeySounds" />
<java-symbol type="bool" name="config_enableWallpaperService" />
<java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
@@ -1087,7 +1086,6 @@
<java-symbol type="array" name="sim_colors" />
<java-symbol type="array" name="special_locale_codes" />
<java-symbol type="array" name="special_locale_names" />
- <java-symbol type="array" name="config_masterVolumeRamp" />
<java-symbol type="array" name="config_cdma_dun_supported_types" />
<java-symbol type="array" name="config_disabledUntilUsedPreinstalledImes" />
<java-symbol type="array" name="config_operatorConsideredNonRoaming" />
@@ -2147,6 +2145,8 @@
<java-symbol type="integer" name="config_defaultNightMode" />
+ <java-symbol type="style" name="Animation.ImmersiveModeConfirmation" />
+
<java-symbol type="integer" name="config_screen_magnification_multi_tap_adjustment" />
<java-symbol type="dimen" name="config_screen_magnification_scaling_threshold" />
<java-symbol type="dimen" name="timepicker_selector_stroke"/>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
index 7bf5f65..78e718f 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
@@ -27,6 +27,8 @@
LOCAL_PACKAGE_NAME := MultiDexLegacyAndException
+LOCAL_DEX_PREOPT := false
+
mainDexList:= \
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
@@ -34,15 +36,17 @@
LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
-D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifdef LOCAL_USE_JACK
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
endif
-LOCAL_DEX_PREOPT := false
-
include $(BUILD_PACKAGE)
-ifndef LOCAL_USE_JACK
+ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
$(hide) mkdir -p $(dir $@)
$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index 416c238..7c699b6 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -27,21 +27,26 @@
LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp
+LOCAL_DEX_PREOPT := false
+
mainDexList:= \
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
-D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifdef LOCAL_USE_JACK
+
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
endif
-LOCAL_DEX_PREOPT := false
-
include $(BUILD_PACKAGE)
-ifndef LOCAL_USE_JACK
+ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
$(hide) mkdir -p $(dir $@)
$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
@@ -63,21 +68,26 @@
LOCAL_PACKAGE_NAME := MultiDexLegacyTestApp2
+LOCAL_DEX_PREOPT := false
+
mainDexList2:= \
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList2)
LOCAL_JACK_FLAGS := -D jack.dex.output.policy=multidex -D jack.preprocessor=true\
-D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifdef LOCAL_USE_JACK
+
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
endif
-LOCAL_DEX_PREOPT := false
-
include $(BUILD_PACKAGE)
-ifndef LOCAL_USE_JACK
+ifndef LOCAL_JACK_ENABLED
$(mainDexList2): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
$(hide) mkdir -p $(dir $@)
$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
index 83ead4b..b85c02c 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk
@@ -36,7 +36,7 @@
include $(BUILD_PACKAGE)
-ifndef LOCAL_USE_JACK
+ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
$(hide) mkdir -p $(dir $@)
$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
index d706ca9..0f1d9c0 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk
@@ -26,6 +26,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
+LOCAL_DEX_PREOPT := false
+
mainDexList:= \
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
@@ -33,15 +35,17 @@
LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
-D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifdef LOCAL_USE_JACK
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
endif
-LOCAL_DEX_PREOPT := false
-
include $(BUILD_PACKAGE)
-ifndef LOCAL_USE_JACK
+ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
$(hide) mkdir -p $(dir $@)
$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
index 99b2a8b..67ca483 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk
@@ -26,6 +26,8 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
+LOCAL_DEX_PREOPT := false
+
mainDexList:= \
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
@@ -33,15 +35,17 @@
LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
-D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifdef LOCAL_USE_JACK
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
endif
-LOCAL_DEX_PREOPT := false
-
include $(BUILD_PACKAGE)
-ifndef LOCAL_USE_JACK
+ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
$(hide) mkdir -p $(dir $@)
$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
index 3ee1c22..bf2efb1 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk
@@ -29,19 +29,23 @@
mainDexList:= \
$(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
+LOCAL_DEX_PREOPT := false
+
LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
-D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
-ifdef LOCAL_USE_JACK
+#################################
+include $(BUILD_SYSTEM)/configure_local_jack.mk
+#################################
+
+ifdef LOCAL_JACK_ENABLED
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
endif
-LOCAL_DEX_PREOPT := false
-
include $(BUILD_PACKAGE)
-ifndef LOCAL_USE_JACK
+ifndef LOCAL_JACK_ENABLED
$(mainDexList): $(full_classes_proguard_jar) | $(HOST_OUT_EXECUTABLES)/mainDexClasses
$(hide) mkdir -p $(dir $@)
$(HOST_OUT_EXECUTABLES)/mainDexClasses $< 1>$@
diff --git a/docs/html/google/play-services/wallet.jd b/docs/html/google/play-services/wallet.jd
index e5ed514..744c8d3 100644
--- a/docs/html/google/play-services/wallet.jd
+++ b/docs/html/google/play-services/wallet.jd
@@ -17,14 +17,14 @@
available to US-based merchants. Once you've completed integration, you can
apply for production access by <a class="external-link" href="https://support.google.com/wallet/business/contact/ui_review">submitting your sandbox integration for review</a>.</p>
- <p>Check out the <a
+ <p>Check out the <a
href="{@docRoot}reference/com/google/android/gms/wallet/package-summary.html">Instant
Buy API reference</a> and visit
<a href="https://developers.google.com/wallet/instant-buy/">developers.google.com/wallet/instant-buy/</a>
for complete information about integrating Google Wallet Instant Buy into your app.</p>
</div>
-<div class="col-4">
+<div class="col-4">
<img src="{@docRoot}images/google/gps-wallet-instant.png" alt="" style="padding-bottom:14px;width:210px">
</div>
</div>
@@ -44,16 +44,16 @@
<h4>Streamline Purchases with Google+ Sign-On</h4>
<p>For users ready to purchase, you can simplify the login and account creation steps
by adding Google+ sign in. Users can sign in with a single click and share their
- profile information during the purchase.
+ profile information during the purchase.
<br />
<a href="https://developers.google.com/commerce/wallet/instant-buy/wallet-sso#android"
class="external-link">Add Google+ Sign-In for Wallet</a>.</p>
-
+
<h4>Minimize User Data Entry</h4>
<p>Google Wallet provides auto-completion of addresses, minimizing user data entry. You can also
retrieve billing and shipping addresses directly from the user’s Wallet to-do form pre-fills.<br />
<a class="external-link"
- href="https://developers.google.com/commerce/wallet/instant-buy/android/reference/com/google/android/gms/wallet/MaskedWallet#getBillingAddress()">Get
+ href="{@docRoot}reference/com/google/android/gms/wallet/MaskedWallet.html#getBillingAddress()">Get
billing addresses</a>.</p>
</div>
@@ -75,7 +75,7 @@
class="external-link" href="https://developers.google.com/wallet/instant-buy/android/tutorial">Instant Buy Android API tutorial</a>
provides directions on how to get the Wallet sample up and running.</p>
<h4>3. Read the documentation</h4>
- <p>For quick access while developing your Android apps, the <a
+ <p>For quick access while developing your Android apps, the <a
href="{@docRoot}reference/com/google/android/gms/wallet/package-summary.html">Google Wallet
API reference</a> is available here on developer.android.com.</p>
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index b5a6477..47b603a 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -24,7 +24,7 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
- alt=""/>SDK Tools, Revision 24.1.2</a> <em>(February 2014)</em>
+ alt=""/>SDK Tools, Revision 24.1.2</a> <em>(February 2015)</em>
</p>
<div class="toggle-content-toggleme">
diff --git a/docs/html/training/scheduling/index.jd b/docs/html/training/scheduling/index.jd
index 4d2db60..4239ffb 100644
--- a/docs/html/training/scheduling/index.jd
+++ b/docs/html/training/scheduling/index.jd
@@ -1,5 +1,5 @@
page.title=Managing Device Awake State
-page.tags=
+page.tags=wakelock, AlarmManager, WakefulBroadcastReceiver
trainingnavtop=true
startpage=true
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 132c6ef..5b20d48 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -21,6 +21,7 @@
import android.os.Parcelable;
import android.os.Trace;
import android.util.DisplayMetrics;
+
import dalvik.system.VMRuntime;
import java.io.OutputStream;
@@ -37,21 +38,14 @@
* @see Bitmap#setDensity(int)
*/
public static final int DENSITY_NONE = 0;
-
- /**
- * Note: mNativeBitmap is used by FaceDetector_jni.cpp
- * Don't change/rename without updating FaceDetector_jni.cpp
- *
- * @hide
- */
- public final long mNativeBitmap;
+
+ private final long mSkBitmapPtr;
/**
* Backing buffer for the Bitmap.
*/
private byte[] mBuffer;
- @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
private final BitmapFinalizer mFinalizer;
private final boolean mIsMutable;
@@ -92,11 +86,11 @@
sDefaultDensity = density;
}
+ @SuppressWarnings("deprecation")
static int getDefaultDensity() {
if (sDefaultDensity >= 0) {
return sDefaultDensity;
}
- //noinspection deprecation
sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
return sDefaultDensity;
}
@@ -105,7 +99,7 @@
* Private constructor that must received an already allocated native bitmap
* int (pointer).
*/
- @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
+ // called from JNI
Bitmap(long nativeBitmap, byte[] buffer, int width, int height, int density,
boolean isMutable, boolean requestPremultiplied,
byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
@@ -120,7 +114,7 @@
mBuffer = buffer;
// we delete this in our finalizer
- mNativeBitmap = nativeBitmap;
+ mSkBitmapPtr = nativeBitmap;
mNinePatchChunk = ninePatchChunk;
mNinePatchInsets = ninePatchInsets;
@@ -136,7 +130,7 @@
* Native bitmap has been reconfigured, so set premult and cached
* width/height values
*/
- @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
+ // called from JNI
void reinit(int width, int height, boolean requestPremultiplied) {
mWidth = width;
mHeight = height;
@@ -227,7 +221,7 @@
throw new IllegalStateException("native-backed bitmaps may not be reconfigured");
}
- nativeReconfigure(mNativeBitmap, width, height, config.nativeInt, mBuffer.length,
+ nativeReconfigure(mSkBitmapPtr, width, height, config.nativeInt, mBuffer.length,
mRequestPremultiplied);
mWidth = width;
mHeight = height;
@@ -305,7 +299,7 @@
*/
public void recycle() {
if (!mRecycled && mFinalizer.mNativeBitmap != 0) {
- if (nativeRecycle(mNativeBitmap)) {
+ if (nativeRecycle(mSkBitmapPtr)) {
// return value indicates whether native pixel object was actually recycled.
// false indicates that it is still in use at the native level and these
// objects should not be collected now. They will be collected later when the
@@ -331,13 +325,13 @@
* Returns the generation ID of this bitmap. The generation ID changes
* whenever the bitmap is modified. This can be used as an efficient way to
* check if a bitmap has changed.
- *
+ *
* @return The current generation ID for this bitmap.
*/
public int getGenerationId() {
- return nativeGenerationId(mNativeBitmap);
+ return nativeGenerationId(mSkBitmapPtr);
}
-
+
/**
* This is called by methods that want to throw an exception if the bitmap
* has already been recycled.
@@ -399,12 +393,12 @@
* encoded: red is stored with 5 bits of precision (32 possible
* values), green is stored with 6 bits of precision (64 possible
* values) and blue is stored with 5 bits of precision.
- *
+ *
* This configuration can produce slight visual artifacts depending
* on the configuration of the source. For instance, without
* dithering, the result might show a greenish tint. To get better
* results dithering should be applied.
- *
+ *
* This configuration may be useful when using opaque bitmaps
* that do not require high color fidelity.
*/
@@ -414,18 +408,18 @@
* Each pixel is stored on 2 bytes. The three RGB color channels
* and the alpha channel (translucency) are stored with a 4 bits
* precision (16 possible values.)
- *
+ *
* This configuration is mostly useful if the application needs
* to store translucency information but also needs to save
* memory.
- *
+ *
* It is recommended to use {@link #ARGB_8888} instead of this
* configuration.
*
* Note: as of {@link android.os.Build.VERSION_CODES#KITKAT},
* any bitmap created with this configuration will be created
* using {@link #ARGB_8888} instead.
- *
+ *
* @deprecated Because of the poor quality of this configuration,
* it is advised to use {@link #ARGB_8888} instead.
*/
@@ -436,7 +430,7 @@
* Each pixel is stored on 4 bytes. Each channel (RGB and alpha
* for translucency) is stored with 8 bits of precision (256
* possible values.)
- *
+ *
* This configuration is very flexible and offers the best
* quality. It should be used whenever possible.
*/
@@ -444,11 +438,10 @@
final int nativeInt;
- @SuppressWarnings({"deprecation"})
private static Config sConfigs[] = {
null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
};
-
+
Config(int ni) {
this.nativeInt = ni;
}
@@ -492,7 +485,7 @@
throw new RuntimeException("Buffer not large enough for pixels");
}
- nativeCopyPixelsToBuffer(mNativeBitmap, dst);
+ nativeCopyPixelsToBuffer(mSkBitmapPtr, dst);
// now update the buffer's position
int position = dst.position();
@@ -532,7 +525,7 @@
throw new RuntimeException("Buffer not large enough for pixels");
}
- nativeCopyPixelsFromBuffer(mNativeBitmap, src);
+ nativeCopyPixelsFromBuffer(mSkBitmapPtr, src);
// now update the buffer's position
int position = src.position();
@@ -554,7 +547,7 @@
*/
public Bitmap copy(Config config, boolean isMutable) {
checkRecycled("Can't copy a recycled bitmap");
- Bitmap b = nativeCopy(mNativeBitmap, config.nativeInt, isMutable);
+ Bitmap b = nativeCopy(mSkBitmapPtr, config.nativeInt, isMutable);
if (b != null) {
b.setPremultiplied(mRequestPremultiplied);
b.mDensity = mDensity;
@@ -564,7 +557,7 @@
/**
* Creates a new bitmap, scaled from an existing bitmap, when possible. If the
- * specified width and height are the same as the current width and height of
+ * specified width and height are the same as the current width and height of
* the source bitmap, the source bitmap is returned and no new bitmap is
* created.
*
@@ -639,7 +632,7 @@
* transformed by the optional matrix. The new bitmap may be the
* same object as source, or a copy may have been made. It is
* initialized with the same density as the original bitmap.
- *
+ *
* If the source bitmap is immutable and the requested subset is the
* same as the source bitmap itself, then the source bitmap is
* returned and no new bitmap is created.
@@ -781,8 +774,8 @@
* @param config The bitmap config to create.
* @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
* bitmap as opaque. Doing so will clear the bitmap in black
- * instead of transparent.
- *
+ * instead of transparent.
+ *
* @throws IllegalArgumentException if the width or height are <= 0
*/
private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
@@ -800,8 +793,8 @@
* @param config The bitmap config to create.
* @param hasAlpha If the bitmap is ARGB_8888 this flag can be used to mark the
* bitmap as opaque. Doing so will clear the bitmap in black
- * instead of transparent.
- *
+ * instead of transparent.
+ *
* @throws IllegalArgumentException if the width or height are <= 0
*/
private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
@@ -815,7 +808,7 @@
}
bm.setHasAlpha(hasAlpha);
if (config == Config.ARGB_8888 && !hasAlpha) {
- nativeErase(bm.mNativeBitmap, 0xff000000);
+ nativeErase(bm.mSkBitmapPtr, 0xff000000);
}
// No need to initialize the bitmap to zeroes with other configs;
// it is backed by a VM byte array which is by definition preinitialized
@@ -1005,7 +998,7 @@
throw new IllegalArgumentException("quality must be 0..100");
}
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
- boolean result = nativeCompress(mNativeBitmap, format.nativeInt, quality,
+ boolean result = nativeCompress(mSkBitmapPtr, format.nativeInt, quality,
stream, new byte[WORKING_COMPRESS_STORAGE]);
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
return result;
@@ -1022,12 +1015,12 @@
* <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
* When a pixel is pre-multiplied, the RGB components have been multiplied by
* the alpha component. For instance, if the original color is a 50%
- * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is
+ * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is
* <code>(128, 128, 0, 0)</code>.</p>
- *
+ *
* <p>This method always returns false if {@link #getConfig()} is
* {@link Bitmap.Config#RGB_565}.</p>
- *
+ *
* <p>The return value is undefined if {@link #getConfig()} is
* {@link Bitmap.Config#ALPHA_8}.</p>
*
@@ -1046,7 +1039,7 @@
* @see BitmapFactory.Options#inPremultiplied
*/
public final boolean isPremultiplied() {
- return nativeIsPremultiplied(mNativeBitmap);
+ return nativeIsPremultiplied(mSkBitmapPtr);
}
/**
@@ -1071,7 +1064,7 @@
*/
public final void setPremultiplied(boolean premultiplied) {
mRequestPremultiplied = premultiplied;
- nativeSetPremultiplied(mNativeBitmap, premultiplied);
+ nativeSetPremultiplied(mSkBitmapPtr, premultiplied);
}
/** Returns the bitmap's width */
@@ -1137,7 +1130,7 @@
public int getScaledHeight(int targetDensity) {
return scaleFromDensity(getHeight(), mDensity, targetDensity);
}
-
+
/**
* @hide
*/
@@ -1145,11 +1138,11 @@
if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
return size;
}
-
+
// Scale by tdensity / sdensity, rounding up.
return ((size * tdensity) + (sdensity >> 1)) / sdensity;
}
-
+
/**
* Return the number of bytes between rows in the bitmap's pixels. Note that
* this refers to the pixels as stored natively by the bitmap. If you call
@@ -1163,7 +1156,7 @@
* @return number of bytes between rows of the native bitmap pixels.
*/
public final int getRowBytes() {
- return nativeRowBytes(mNativeBitmap);
+ return nativeRowBytes(mSkBitmapPtr);
}
/**
@@ -1206,7 +1199,7 @@
* that config, otherwise return null.
*/
public final Config getConfig() {
- return Config.nativeToConfig(nativeConfig(mNativeBitmap));
+ return Config.nativeToConfig(nativeConfig(mSkBitmapPtr));
}
/** Returns true if the bitmap's config supports per-pixel alpha, and
@@ -1218,7 +1211,7 @@
* it will return true by default.
*/
public final boolean hasAlpha() {
- return nativeHasAlpha(mNativeBitmap);
+ return nativeHasAlpha(mSkBitmapPtr);
}
/**
@@ -1232,28 +1225,28 @@
* non-opaque per-pixel alpha values.
*/
public void setHasAlpha(boolean hasAlpha) {
- nativeSetHasAlpha(mNativeBitmap, hasAlpha, mRequestPremultiplied);
+ nativeSetHasAlpha(mSkBitmapPtr, hasAlpha, mRequestPremultiplied);
}
/**
* Indicates whether the renderer responsible for drawing this
* bitmap should attempt to use mipmaps when this bitmap is drawn
* scaled down.
- *
+ *
* If you know that you are going to draw this bitmap at less than
* 50% of its original size, you may be able to obtain a higher
* quality
- *
+ *
* This property is only a suggestion that can be ignored by the
* renderer. It is not guaranteed to have any effect.
- *
+ *
* @return true if the renderer should attempt to use mipmaps,
* false otherwise
- *
+ *
* @see #setHasMipMap(boolean)
*/
public final boolean hasMipMap() {
- return nativeHasMipMap(mNativeBitmap);
+ return nativeHasMipMap(mSkBitmapPtr);
}
/**
@@ -1264,7 +1257,7 @@
* If you know that you are going to draw this bitmap at less than
* 50% of its original size, you may be able to obtain a higher
* quality by turning this property on.
- *
+ *
* Note that if the renderer respects this hint it might have to
* allocate extra memory to hold the mipmap levels for this bitmap.
*
@@ -1277,7 +1270,7 @@
* @see #hasMipMap()
*/
public final void setHasMipMap(boolean hasMipMap) {
- nativeSetHasMipMap(mNativeBitmap, hasMipMap);
+ nativeSetHasMipMap(mSkBitmapPtr, hasMipMap);
}
/**
@@ -1290,7 +1283,7 @@
if (!isMutable()) {
throw new IllegalStateException("cannot erase immutable bitmaps");
}
- nativeErase(mNativeBitmap, c);
+ nativeErase(mSkBitmapPtr, c);
}
/**
@@ -1306,7 +1299,7 @@
public int getPixel(int x, int y) {
checkRecycled("Can't call getPixel() on a recycled bitmap");
checkPixelAccess(x, y);
- return nativeGetPixel(mNativeBitmap, x, y);
+ return nativeGetPixel(mSkBitmapPtr, x, y);
}
/**
@@ -1339,14 +1332,14 @@
return; // nothing to do
}
checkPixelsAccess(x, y, width, height, offset, stride, pixels);
- nativeGetPixels(mNativeBitmap, pixels, offset, stride,
+ nativeGetPixels(mSkBitmapPtr, pixels, offset, stride,
x, y, width, height);
}
/**
* Shared code to check for illegal arguments passed to getPixel()
* or setPixel()
- *
+ *
* @param x x coordinate of the pixel
* @param y y coordinate of the pixel
*/
@@ -1420,7 +1413,7 @@
throw new IllegalStateException();
}
checkPixelAccess(x, y);
- nativeSetPixel(mNativeBitmap, x, y, color);
+ nativeSetPixel(mSkBitmapPtr, x, y, color);
}
/**
@@ -1456,7 +1449,7 @@
return; // nothing to do
}
checkPixelsAccess(x, y, width, height, offset, stride, pixels);
- nativeSetPixels(mNativeBitmap, pixels, offset, stride,
+ nativeSetPixels(mSkBitmapPtr, pixels, offset, stride,
x, y, width, height);
}
@@ -1494,7 +1487,7 @@
*/
public void writeToParcel(Parcel p, int flags) {
checkRecycled("Can't parcel a recycled bitmap");
- if (!nativeWriteToParcel(mNativeBitmap, mIsMutable, mDensity, p)) {
+ if (!nativeWriteToParcel(mSkBitmapPtr, mIsMutable, mDensity, p)) {
throw new RuntimeException("native writeToParcel failed");
}
}
@@ -1522,9 +1515,9 @@
* -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then
* drawing the original would result in the blur visually aligning with
* the original.
- *
+ *
* <p>The initial density of the returned bitmap is the same as the original's.
- *
+ *
* @param paint Optional paint used to modify the alpha values in the
* resulting bitmap. Pass null for default behavior.
* @param offsetXY Optional array that returns the X (index 0) and Y
@@ -1538,7 +1531,7 @@
public Bitmap extractAlpha(Paint paint, int[] offsetXY) {
checkRecycled("Can't extractAlpha on a recycled bitmap");
long nativePaint = paint != null ? paint.getNativeInstance() : 0;
- Bitmap bm = nativeExtractAlpha(mNativeBitmap, nativePaint, offsetXY);
+ Bitmap bm = nativeExtractAlpha(mSkBitmapPtr, nativePaint, offsetXY);
if (bm == null) {
throw new RuntimeException("Failed to extractAlpha on Bitmap");
}
@@ -1552,7 +1545,7 @@
* If other is null, return false.
*/
public boolean sameAs(Bitmap other) {
- return this == other || (other != null && nativeSameAs(mNativeBitmap, other.mNativeBitmap));
+ return this == other || (other != null && nativeSameAs(mSkBitmapPtr, other.mSkBitmapPtr));
}
/**
@@ -1567,7 +1560,12 @@
* and therefore is harmless.
*/
public void prepareToDraw() {
- nativePrepareToDraw(mNativeBitmap);
+ nativePrepareToDraw(mSkBitmapPtr);
+ }
+
+ /** @hide */
+ public final long getSkBitmap() {
+ return mSkBitmapPtr;
}
private static class BitmapFinalizer {
@@ -1658,8 +1656,4 @@
private static native boolean nativeHasMipMap(long nativeBitmap);
private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
-
- /* package */ final long ni() {
- return mNativeBitmap;
- }
}
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 5e004a3..f2f890e 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -42,7 +42,7 @@
mBitmap = bitmap;
mTileX = tileX;
mTileY = tileY;
- final long b = bitmap.ni();
+ final long b = bitmap.getSkBitmap();
init(nativeCreate(b, tileX.nativeInt, tileY.nativeInt));
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index e4c2f0e..85fa3cb 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -154,7 +154,7 @@
throw new IllegalStateException("Immutable bitmap passed to Canvas constructor");
}
throwIfCannotDraw(bitmap);
- mNativeCanvasWrapper = initRaster(bitmap.ni());
+ mNativeCanvasWrapper = initRaster(bitmap.getSkBitmap());
mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper);
mBitmap = bitmap;
mDensity = bitmap.mDensity;
@@ -219,7 +219,7 @@
}
throwIfCannotDraw(bitmap);
- native_setBitmap(mNativeCanvasWrapper, bitmap.ni(), true);
+ native_setBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), true);
mDensity = bitmap.mDensity;
}
@@ -1339,7 +1339,7 @@
*/
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
throwIfCannotDraw(bitmap);
- native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top,
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top,
paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
}
@@ -1385,7 +1385,7 @@
bottom = src.bottom;
}
- native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top, right, bottom,
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, right, bottom,
dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
bitmap.mDensity);
}
@@ -1432,7 +1432,7 @@
bottom = src.bottom;
}
- native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top, right, bottom,
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, right, bottom,
dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
bitmap.mDensity);
}
@@ -1513,7 +1513,7 @@
* @param paint May be null. The paint used to draw the bitmap
*/
public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
- nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.ni(), matrix.ni(),
+ nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getSkBitmap(), matrix.ni(),
paint != null ? paint.getNativeInstance() : 0);
}
@@ -1568,7 +1568,7 @@
// no mul by 2, since we need only 1 color per vertex
checkRange(colors.length, colorOffset, count);
}
- nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap.ni(), meshWidth, meshHeight,
+ nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getSkBitmap(), meshWidth, meshHeight,
verts, vertOffset, colors, colorOffset,
paint != null ? paint.getNativeInstance() : 0);
}
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index ebc86aa..9c4299a 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -98,7 +98,7 @@
public NinePatch(Bitmap bitmap, byte[] chunk, String srcName) {
mBitmap = bitmap;
mSrcName = srcName;
- mNativeChunk = validateNinePatchChunk(mBitmap.ni(), chunk);
+ mNativeChunk = validateNinePatchChunk(mBitmap.getSkBitmap(), chunk);
}
/**
@@ -199,12 +199,12 @@
}
void drawSoftware(Canvas canvas, RectF location, Paint paint) {
- nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.ni(), mNativeChunk,
+ nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.getSkBitmap(), mNativeChunk,
paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
}
void drawSoftware(Canvas canvas, Rect location, Paint paint) {
- nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.ni(), mNativeChunk,
+ nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.getSkBitmap(), mNativeChunk,
paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
}
@@ -252,7 +252,7 @@
* that are transparent.
*/
public final Region getTransparentRegion(Rect bounds) {
- long r = nativeGetTransparentRegion(mBitmap.ni(), mNativeChunk, bounds);
+ long r = nativeGetTransparentRegion(mBitmap.getSkBitmap(), mNativeChunk, bounds);
return r != 0 ? new Region(r) : null;
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 91c8dba..681bc62 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -534,8 +534,9 @@
* @hide
*/
public long getNativeInstance() {
- if (mShader != null && mShader.getNativeInstance() != mNativeShader) {
- mNativeShader = mShader.getNativeInstance();
+ long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
+ if (newNativeShader != mNativeShader) {
+ mNativeShader = newNativeShader;
native_setShader(mNativePaint, mNativeShader);
}
return mNativePaint;
diff --git a/graphics/java/android/graphics/PorterDuff.java b/graphics/java/android/graphics/PorterDuff.java
index 2ef1662..f5fbe70 100644
--- a/graphics/java/android/graphics/PorterDuff.java
+++ b/graphics/java/android/graphics/PorterDuff.java
@@ -18,7 +18,7 @@
public class PorterDuff {
- // these value must match their native equivalents. See SkPorterDuff.h
+ // these value must match their native equivalents. See SkXfermode.h
public enum Mode {
/** [0, 0] */
CLEAR (0),
@@ -46,17 +46,17 @@
XOR (11),
/** [Sa + Da - Sa*Da,
Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
- DARKEN (12),
+ DARKEN (16),
/** [Sa + Da - Sa*Da,
Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
- LIGHTEN (13),
+ LIGHTEN (17),
/** [Sa * Da, Sc * Dc] */
- MULTIPLY (14),
+ MULTIPLY (24),
/** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
- SCREEN (15),
+ SCREEN (14),
/** Saturate(S + D) */
- ADD (16),
- OVERLAY (17);
+ ADD (12),
+ OVERLAY (15);
Mode(int nativeInt) {
this.nativeInt = nativeInt;
diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java
index 79934da..b32dcc6 100644
--- a/graphics/java/android/graphics/pdf/PdfRenderer.java
+++ b/graphics/java/android/graphics/pdf/PdfRenderer.java
@@ -380,7 +380,7 @@
final long transformPtr = (transform != null) ? transform.native_instance : 0;
- nativeRenderPage(mNativeDocument, mNativePage, destination.mNativeBitmap, contentLeft,
+ nativeRenderPage(mNativeDocument, mNativePage, destination.getSkBitmap(), contentLeft,
contentTop, contentRight, contentBottom, transformPtr, renderMode);
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 71c1fc3..d313c18 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -216,7 +216,7 @@
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) override
- { LOG_ALWAYS_FATAL("DisplayListRenderer does not support drawVertices()"); }
+ { /* DisplayListRenderer does not support drawVertices(); ignore */ }
// Bitmap-based
virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) override;
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index f94dc38..711b11c 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -198,7 +198,7 @@
mOutGlop->mesh.vertices = {
mCaches.patchCache.getMeshBuffer(),
VertexAttribFlags::kTextureCoord,
- (void*)patch.offset, (void*)patch.textureOffset, nullptr,
+ (void*)patch.positionOffset, (void*)patch.textureOffset, nullptr,
kTextureVertexStride };
mOutGlop->mesh.elementCount = patch.indexCount;
return *this;
@@ -518,6 +518,7 @@
}
mOutGlop->transform.modelView.loadTranslate(offsetX, offsetY, 0.0f);
+ mOutGlop->bounds = source;
mOutGlop->bounds.translate(offsetX, offsetY);
return *this;
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index eef4b73..7fd115f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2384,7 +2384,7 @@
ignoreTransform = true;
}
drawIndexedTextureMesh(left, top, right, bottom, texture->id, paint,
- texture->blend, (GLvoid*) mesh->offset, (GLvoid*) mesh->textureOffset,
+ texture->blend, (GLvoid*) mesh->positionOffset, (GLvoid*) mesh->textureOffset,
GL_TRIANGLES, mesh->indexCount, false, ignoreTransform,
mCaches.patchCache.getMeshBuffer(), kModelViewMode_Translate, !mesh->hasEmptyQuads);
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index ce51e04..f673c6a 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -24,6 +24,7 @@
#include "Patch.h"
#include "Properties.h"
#include "UvMapper.h"
+#include "utils/MathUtils.h"
namespace android {
namespace uirenderer {
@@ -36,19 +37,11 @@
return verticesCount * sizeof(TextureVertex);
}
-TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
- float width, float height, const Res_png_9patch* patch) {
- UvMapper mapper;
- return createMesh(bitmapWidth, bitmapHeight, width, height, mapper, patch);
-}
-
-TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
- float width, float height, const UvMapper& mapper, const Res_png_9patch* patch) {
- if (vertices) return vertices.get();
+Patch::Patch(const float bitmapWidth, const float bitmapHeight,
+ float width, float height, const UvMapper& mapper, const Res_png_9patch* patch)
+ : mColors(patch->getColors()) {
int8_t emptyQuads = 0;
- mColors = patch->getColors();
-
const int8_t numColors = patch->numColors;
if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
for (int8_t i = 0; i < numColors; i++) {
@@ -64,7 +57,7 @@
uint32_t yCount = patch->numYDivs;
uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
- if (maxVertices == 0) return nullptr;
+ if (maxVertices == 0) return;
vertices.reset(new TextureVertex[maxVertices]);
TextureVertex* vertex = vertices.get();
@@ -151,8 +144,6 @@
memcpy(reducedVertices.get(), vertices.get(), verticesCount * sizeof(TextureVertex));
vertices = std::move(reducedVertices);
}
-
- return vertices.get();
}
void Patch::generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex,
@@ -200,10 +191,10 @@
const uint32_t oldQuadCount = quadCount;
quadCount++;
- if (x1 < 0.0f) x1 = 0.0f;
- if (x2 < 0.0f) x2 = 0.0f;
- if (y1 < 0.0f) y1 = 0.0f;
- if (y2 < 0.0f) y2 = 0.0f;
+ x1 = MathUtils::max(x1, 0.0f);
+ x2 = MathUtils::max(x2, 0.0f);
+ y1 = MathUtils::max(y1, 0.0f);
+ y2 = MathUtils::max(y2, 0.0f);
// Skip degenerate and transparent (empty) quads
if ((mColors[oldQuadCount] == 0) || x1 >= x2 || y1 >= y2) {
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 9afb41d..b63bd24 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -39,7 +39,9 @@
class Patch {
public:
- Patch() {}
+ Patch(const float bitmapWidth, const float bitmapHeight,
+ float width, float height,
+ const UvMapper& mapper, const Res_png_9patch* patch);
/**
* Returns the size of this patch's mesh in bytes.
@@ -52,15 +54,9 @@
bool hasEmptyQuads = false;
Vector<Rect> quads;
- Rect bounds;
- GLintptr offset = 0;
+ GLintptr positionOffset = 0;
GLintptr textureOffset = 0;
- TextureVertex* createMesh(const float bitmapWidth, const float bitmapHeight,
- float width, float height, const Res_png_9patch* patch);
- TextureVertex* createMesh(const float bitmapWidth, const float bitmapHeight,
- float width, float height, const UvMapper& mapper, const Res_png_9patch* patch);
-
private:
void generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex,
float y1, float y2, float v1, float v2, float stretchX, float rescaleX,
@@ -68,7 +64,7 @@
void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
float u1, float v1, float u2, float v2, uint32_t& quadCount);
- const uint32_t* mColors = nullptr;
+ const uint32_t* mColors;
UvMapper mUvMapper;
}; // struct Patch
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index af403b4..2765262 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -162,7 +162,7 @@
// Release the patch and mark the space in the free list
Patch* patch = pair.getSecond();
- BufferBlock* block = new BufferBlock(patch->offset, patch->getSize());
+ BufferBlock* block = new BufferBlock(patch->positionOffset, patch->getSize());
block->next = mFreeBlocks;
mFreeBlocks = block;
@@ -190,7 +190,7 @@
* Sets the mesh's offsets and copies its associated vertices into
* the mesh buffer (VBO).
*/
-void PatchCache::setupMesh(Patch* newMesh, TextureVertex* vertices) {
+void PatchCache::setupMesh(Patch* newMesh) {
// This call ensures the VBO exists and that it is bound
init();
@@ -223,9 +223,9 @@
}
// Copy the 9patch mesh in the VBO
- newMesh->offset = (GLintptr) (block->offset);
- newMesh->textureOffset = newMesh->offset + kMeshTextureOffset;
- glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
+ newMesh->positionOffset = (GLintptr) (block->offset);
+ newMesh->textureOffset = newMesh->positionOffset + kMeshTextureOffset;
+ glBufferSubData(GL_ARRAY_BUFFER, newMesh->positionOffset, size, newMesh->vertices.get());
// Remove the block since we've used it entirely
if (block->size == size) {
@@ -244,6 +244,8 @@
mSize += size;
}
+static const UvMapper sIdentity;
+
const Patch* PatchCache::get(const AssetAtlas::Entry* entry,
const uint32_t bitmapWidth, const uint32_t bitmapHeight,
const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) {
@@ -252,20 +254,12 @@
const Patch* mesh = mCache.get(description);
if (!mesh) {
- Patch* newMesh = new Patch();
- TextureVertex* vertices;
+ const UvMapper& mapper = entry ? entry->uvMapper : sIdentity;
+ Patch* newMesh = new Patch(bitmapWidth, bitmapHeight,
+ pixelWidth, pixelHeight, mapper, patch);
- if (entry) {
- // An atlas entry has a UV mapper
- vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
- pixelWidth, pixelHeight, entry->uvMapper, patch);
- } else {
- vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
- pixelWidth, pixelHeight, patch);
- }
-
- if (vertices) {
- setupMesh(newMesh, vertices);
+ if (newMesh->vertices) {
+ setupMesh(newMesh);
}
#if DEBUG_PATCHES
@@ -284,7 +278,7 @@
String8 dump;
BufferBlock* block = mFreeBlocks;
while (block) {
- dump.appendFormat("->(%d, %d)", block->offset, block->size);
+ dump.appendFormat("->(%d, %d)", block->positionOffset, block->size);
block = block->next;
}
ALOGD("%s: Free blocks%s", prefix, dump.string());
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index e038720..387f79a 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -160,7 +160,7 @@
void clearCache();
void createVertexBuffer();
- void setupMesh(Patch* newMesh, TextureVertex* vertices);
+ void setupMesh(Patch* newMesh);
void remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch);
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 1716cf0..c82082f 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -252,6 +252,13 @@
bottom = fmaxf(bottom, y);
}
+ void expandToCoverRect(float otherLeft, float otherTop, float otherRight, float otherBottom) {
+ left = fminf(left, otherLeft);
+ top = fminf(top, otherTop);
+ right = fmaxf(right, otherRight);
+ bottom = fmaxf(bottom, otherBottom);
+ }
+
SkRect toSkRect() const {
return SkRect::MakeLTRB(left, top, right, bottom);
}
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index efbb709..71088b7 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -22,7 +22,6 @@
#include <SkDeque.h>
#include <SkDrawFilter.h>
#include <SkGraphics.h>
-#include <SkPorterDuff.h>
#include <SkShader.h>
#include <SkTArray.h>
#include <SkTemplates.h>
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 3c65705..ec1bb90 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -22,9 +22,10 @@
namespace android {
namespace uirenderer {
-SkiaCanvasProxy::SkiaCanvasProxy(Canvas* canvas)
+SkiaCanvasProxy::SkiaCanvasProxy(Canvas* canvas, bool filterHwuiCalls)
: INHERITED(canvas->width(), canvas->height())
- , mCanvas(canvas) {}
+ , mCanvas(canvas)
+ , mFilterHwuiCalls(filterHwuiCalls) {}
void SkiaCanvasProxy::onDrawPaint(const SkPaint& paint) {
mCanvas->drawPaint(paint);
@@ -32,6 +33,10 @@
void SkiaCanvasProxy::onDrawPoints(PointMode pointMode, size_t count, const SkPoint pts[],
const SkPaint& paint) {
+ if (!pts || count == 0) {
+ return;
+ }
+
// convert the SkPoints into floats
SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
const size_t floatCount = count << 1;
@@ -118,6 +123,9 @@
void SkiaCanvasProxy::onDrawVertices(VertexMode mode, int vertexCount, const SkPoint vertices[],
const SkPoint texs[], const SkColor colors[], SkXfermode*, const uint16_t indices[],
int indexCount, const SkPaint& paint) {
+ if (mFilterHwuiCalls) {
+ return;
+ }
// convert the SkPoints into floats
SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
const int floatCount = vertexCount << 1;
@@ -312,6 +320,9 @@
void SkiaCanvasProxy::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
+ if (mFilterHwuiCalls) {
+ return;
+ }
SkPatchUtils::VertexData data;
SkMatrix matrix;
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 4322fcf..0de9650 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -27,16 +27,19 @@
/**
* This class serves as a proxy between Skia's SkCanvas and Android Framework's
- * Canvas. The class does not maintain any state and will pass through any request
- * directly to the Canvas provided in the constructor.
+ * Canvas. The class does not maintain any draw-related state and will pass
+ * through most requests directly to the Canvas provided in the constructor.
*
* Upon construction it is expected that the provided Canvas has already been
* prepared for recording and will continue to be in the recording state while
* this proxy class is being used.
+ *
+ * If filterHwuiCalls is true, the proxy silently ignores away draw calls that
+ * aren't supported by HWUI.
*/
class ANDROID_API SkiaCanvasProxy : public SkCanvas {
public:
- SkiaCanvasProxy(Canvas* canvas);
+ SkiaCanvasProxy(Canvas* canvas, bool filterHwuiCalls = false);
virtual ~SkiaCanvasProxy() {}
protected:
@@ -94,6 +97,7 @@
private:
Canvas* mCanvas;
+ bool mFilterHwuiCalls;
typedef SkCanvas INHERITED;
};
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3a07bef..287b646 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -26,7 +26,6 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.media.RemoteController.OnClientUpdateListener;
import android.media.audiopolicy.AudioPolicy;
import android.media.session.MediaController;
import android.media.session.MediaSession;
@@ -59,10 +58,8 @@
private final Context mContext;
private long mVolumeKeyUpTime;
- private final boolean mUseMasterVolume;
private final boolean mUseVolumeKeySounds;
private final boolean mUseFixedVolume;
- private final Binder mToken = new Binder();
private static String TAG = "AudioManager";
private static final AudioPortEventHandler sAudioPortEventHandler = new AudioPortEventHandler();
@@ -148,17 +145,6 @@
"android.media.STREAM_MUTE_CHANGED_ACTION";
/**
- * @hide Broadcast intent when the master volume changes.
- * Includes the new volume
- *
- * @see #EXTRA_MASTER_VOLUME_VALUE
- * @see #EXTRA_PREV_MASTER_VOLUME_VALUE
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String MASTER_VOLUME_CHANGED_ACTION =
- "android.media.MASTER_VOLUME_CHANGED_ACTION";
-
- /**
* @hide Broadcast intent when the master mute state changes.
* Includes the the new volume
*
@@ -210,20 +196,6 @@
"android.media.EXTRA_PREV_VOLUME_STREAM_VALUE";
/**
- * @hide The new master volume value for the master volume changed intent.
- * Value is integer between 0 and 100 inclusive.
- */
- public static final String EXTRA_MASTER_VOLUME_VALUE =
- "android.media.EXTRA_MASTER_VOLUME_VALUE";
-
- /**
- * @hide The previous master volume value for the master volume changed intent.
- * Value is integer between 0 and 100 inclusive.
- */
- public static final String EXTRA_PREV_MASTER_VOLUME_VALUE =
- "android.media.EXTRA_PREV_MASTER_VOLUME_VALUE";
-
- /**
* @hide The new master volume mute state for the master mute changed intent.
* Value is boolean
*/
@@ -604,8 +576,6 @@
*/
public AudioManager(Context context) {
mContext = context;
- mUseMasterVolume = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_useMasterVolume);
mUseVolumeKeySounds = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useVolumeKeySounds);
mUseFixedVolume = mContext.getResources().getBoolean(
@@ -667,12 +637,8 @@
* The user has hit another key during the delay (e.g., 300ms)
* since the last volume key up, so cancel any sounds.
*/
- if (mUseMasterVolume) {
- adjustMasterVolume(ADJUST_SAME, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
- } else {
- adjustSuggestedStreamVolume(ADJUST_SAME,
- stream, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
- }
+ adjustSuggestedStreamVolume(ADJUST_SAME,
+ stream, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
}
}
@@ -688,22 +654,12 @@
* Adjust the volume in on key down since it is more
* responsive to the user.
*/
- int flags = FLAG_SHOW_UI | FLAG_VIBRATE;
-
- if (mUseMasterVolume) {
- adjustMasterVolume(
- keyCode == KeyEvent.KEYCODE_VOLUME_UP
- ? ADJUST_RAISE
- : ADJUST_LOWER,
- flags);
- } else {
- adjustSuggestedStreamVolume(
- keyCode == KeyEvent.KEYCODE_VOLUME_UP
- ? ADJUST_RAISE
- : ADJUST_LOWER,
- stream,
- flags);
- }
+ adjustSuggestedStreamVolume(
+ keyCode == KeyEvent.KEYCODE_VOLUME_UP
+ ? ADJUST_RAISE
+ : ADJUST_LOWER,
+ stream,
+ FLAG_SHOW_UI | FLAG_VIBRATE);
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
if (event.getRepeatCount() == 0) {
@@ -726,15 +682,10 @@
* sound to play when a user holds down volume down to mute.
*/
if (mUseVolumeKeySounds) {
- if (mUseMasterVolume) {
- adjustMasterVolume(ADJUST_SAME, FLAG_PLAY_SOUND);
- } else {
- int flags = FLAG_PLAY_SOUND;
- adjustSuggestedStreamVolume(
- ADJUST_SAME,
- stream,
- flags);
- }
+ adjustSuggestedStreamVolume(
+ ADJUST_SAME,
+ stream,
+ FLAG_PLAY_SOUND);
}
mVolumeKeyUpTime = SystemClock.uptimeMillis();
break;
@@ -783,12 +734,8 @@
public void adjustStreamVolume(int streamType, int direction, int flags) {
IAudioService service = getService();
try {
- if (mUseMasterVolume) {
- service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
- } else {
- service.adjustStreamVolume(streamType, direction, flags,
- mContext.getOpPackageName());
- }
+ service.adjustStreamVolume(streamType, direction, flags,
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustStreamVolume", e);
}
@@ -818,17 +765,8 @@
* @see #isVolumeFixed()
*/
public void adjustVolume(int direction, int flags) {
- IAudioService service = getService();
- try {
- if (mUseMasterVolume) {
- service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
- } else {
- MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
- helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in adjustVolume", e);
- }
+ MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
+ helper.sendAdjustVolumeBy(USE_DEFAULT_STREAM_TYPE, direction, flags);
}
/**
@@ -856,34 +794,17 @@
* @see #isVolumeFixed()
*/
public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
- IAudioService service = getService();
- try {
- if (mUseMasterVolume) {
- service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
- } else {
- MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
- helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in adjustSuggestedStreamVolume", e);
- }
+ MediaSessionLegacyHelper helper = MediaSessionLegacyHelper.getHelper(mContext);
+ helper.sendAdjustVolumeBy(suggestedStreamType, direction, flags);
}
- /**
- * Adjusts the master volume for the device's audio amplifier.
- * <p>
- *
- * @param steps The number of volume steps to adjust. A positive
- * value will raise the volume.
- * @param flags One or more flags.
- * @hide
- */
- public void adjustMasterVolume(int steps, int flags) {
+ /** @hide */
+ public void setMasterMute(boolean mute, int flags) {
IAudioService service = getService();
try {
- service.adjustMasterVolume(steps, flags, mContext.getOpPackageName());
+ service.setMasterMute(mute, flags, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in adjustMasterVolume", e);
+ Log.e(TAG, "Dead object in setMasterMute", e);
}
}
@@ -935,11 +856,7 @@
public int getStreamMaxVolume(int streamType) {
IAudioService service = getService();
try {
- if (mUseMasterVolume) {
- return service.getMasterMaxVolume();
- } else {
- return service.getStreamMaxVolume(streamType);
- }
+ return service.getStreamMaxVolume(streamType);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in getStreamMaxVolume", e);
return 0;
@@ -957,11 +874,7 @@
public int getStreamVolume(int streamType) {
IAudioService service = getService();
try {
- if (mUseMasterVolume) {
- return service.getMasterVolume();
- } else {
- return service.getStreamVolume(streamType);
- }
+ return service.getStreamVolume(streamType);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in getStreamVolume", e);
return 0;
@@ -976,11 +889,7 @@
public int getLastAudibleStreamVolume(int streamType) {
IAudioService service = getService();
try {
- if (mUseMasterVolume) {
- return service.getLastAudibleMasterVolume();
- } else {
- return service.getLastAudibleStreamVolume(streamType);
- }
+ return service.getLastAudibleStreamVolume(streamType);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in getLastAudibleStreamVolume", e);
return 0;
@@ -993,12 +902,12 @@
* It is assumed that this stream type is also tied to ringer mode changes.
* @hide
*/
- public int getMasterStreamType() {
+ public int getUiSoundsStreamType() {
IAudioService service = getService();
try {
- return service.getMasterStreamType();
+ return service.getUiSoundsStreamType();
} catch (RemoteException e) {
- Log.e(TAG, "Dead object in getMasterStreamType", e);
+ Log.e(TAG, "Dead object in getUiSoundsStreamType", e);
return STREAM_RING;
}
}
@@ -1043,82 +952,13 @@
public void setStreamVolume(int streamType, int index, int flags) {
IAudioService service = getService();
try {
- if (mUseMasterVolume) {
- service.setMasterVolume(index, flags, mContext.getOpPackageName());
- } else {
- service.setStreamVolume(streamType, index, flags, mContext.getOpPackageName());
- }
+ service.setStreamVolume(streamType, index, flags, mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setStreamVolume", e);
}
}
/**
- * Returns the maximum volume index for master volume.
- *
- * @hide
- */
- public int getMasterMaxVolume() {
- IAudioService service = getService();
- try {
- return service.getMasterMaxVolume();
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in getMasterMaxVolume", e);
- return 0;
- }
- }
-
- /**
- * Returns the current volume index for master volume.
- *
- * @return The current volume index for master volume.
- * @hide
- */
- public int getMasterVolume() {
- IAudioService service = getService();
- try {
- return service.getMasterVolume();
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in getMasterVolume", e);
- return 0;
- }
- }
-
- /**
- * Get last audible volume before master volume was muted.
- *
- * @hide
- */
- public int getLastAudibleMasterVolume() {
- IAudioService service = getService();
- try {
- return service.getLastAudibleMasterVolume();
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in getLastAudibleMasterVolume", e);
- return 0;
- }
- }
-
- /**
- * Sets the volume index for master volume.
- *
- * @param index The volume index to set. See
- * {@link #getMasterMaxVolume()} for the largest valid value.
- * @param flags One or more flags.
- * @see #getMasterMaxVolume()
- * @see #getMasterVolume()
- * @hide
- */
- public void setMasterVolume(int index, int flags) {
- IAudioService service = getService();
- try {
- service.setMasterVolume(index, flags, mContext.getOpPackageName());
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in setMasterVolume", e);
- }
- }
-
- /**
* Solo or unsolo a particular stream.
* <p>
* Do not use. This method has been deprecated and is now a no-op.
@@ -1189,11 +1029,7 @@
public boolean isStreamMute(int streamType) {
IAudioService service = getService();
try {
- if (mUseMasterVolume) {
- return service.isMasterMute();
- } else {
- return service.isStreamMute(streamType);
- }
+ return service.isStreamMute(streamType);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in isStreamMute", e);
return false;
@@ -1223,9 +1059,6 @@
* @hide
*/
public void forceVolumeControlStream(int streamType) {
- if (mUseMasterVolume) {
- return;
- }
IAudioService service = getService();
try {
service.forceVolumeControlStream(streamType, mICallBack);
@@ -2694,7 +2527,7 @@
* metadata updates and playback state information from applications using
* {@link RemoteControlClient}, and control their playback.
* <p>
- * Registration requires the {@link OnClientUpdateListener} listener to be
+ * Registration requires the {@link RemoteController.OnClientUpdateListener} listener to be
* one of the enabled notification listeners (see
* {@link android.service.notification.NotificationListenerService}).
*
diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java
index ef5710c..059d940 100644
--- a/media/java/android/media/AudioManagerInternal.java
+++ b/media/java/android/media/AudioManagerInternal.java
@@ -36,9 +36,6 @@
public abstract void setStreamVolumeForUid(int streamType, int direction, int flags,
String callingPackage, int uid);
- public abstract void adjustMasterVolumeForUid(int steps, int flags, String callingPackage,
- int uid);
-
public abstract void setRingerModeDelegate(RingerModeDelegate delegate);
public abstract int getRingerModeInternal();
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 17f5b59..20f7d29 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -44,32 +44,24 @@
void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage);
- void adjustMasterVolume(int direction, int flags, String callingPackage);
-
void setStreamVolume(int streamType, int index, int flags, String callingPackage);
oneway void setRemoteStreamVolume(int index);
- void setMasterVolume(int index, int flags, String callingPackage);
-
boolean isStreamMute(int streamType);
void forceRemoteSubmixFullVolume(boolean startForcing, IBinder cb);
boolean isMasterMute();
- int getStreamVolume(int streamType);
+ void setMasterMute(boolean mute, int flags, String callingPackage);
- int getMasterVolume();
+ int getStreamVolume(int streamType);
int getStreamMaxVolume(int streamType);
- int getMasterMaxVolume();
-
int getLastAudibleStreamVolume(int streamType);
- int getLastAudibleMasterVolume();
-
void setMicrophoneMute(boolean on, String callingPackage);
void setRingerModeExternal(int ringerMode, String caller);
@@ -187,7 +179,7 @@
void setRingtonePlayer(IRingtonePlayer player);
IRingtonePlayer getRingtonePlayer();
- int getMasterStreamType();
+ int getUiSoundsStreamType();
void setWiredDeviceConnectionState(int type, int state, String address, String name);
int setBluetoothA2dpDeviceConnectionState(in BluetoothDevice device, int state, int profile);
diff --git a/media/java/android/media/IVolumeController.aidl b/media/java/android/media/IVolumeController.aidl
index e3593a6..90ac416 100644
--- a/media/java/android/media/IVolumeController.aidl
+++ b/media/java/android/media/IVolumeController.aidl
@@ -27,8 +27,6 @@
void volumeChanged(int streamType, int flags);
- void masterVolumeChanged(int flags);
-
void masterMuteChanged(int flags);
void setLayoutDirection(int layoutDirection);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index d61610d..d77fcd8 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -16,6 +16,7 @@
package android.media;
+import android.annotation.IntDef;
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.content.ContentResolver;
@@ -61,6 +62,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.Runnable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Scanner;
@@ -472,6 +475,11 @@
* <td>{} </p></td>
* <td>This method can be called in any state and calling it does not change
* the object state. </p></td></tr>
+ * <tr><td>setPlaybackRate</p></td>
+ * <td>any </p></td>
+ * <td>{} </p></td>
+ * <td>This method can be called in any state and calling it does not change
+ * the object state. </p></td></tr>
* <tr><td>setVolume </p></td>
* <td>{Idle, Initialized, Stopped, Prepared, Started, Paused,
* PlaybackCompleted}</p></td>
@@ -1319,6 +1327,59 @@
public native boolean isPlaying();
/**
+ * Specifies resampling as audio mode for variable rate playback, i.e.,
+ * resample the waveform based on the requested playback rate to get
+ * a new waveform, and play back the new waveform at the original sampling
+ * frequency.
+ * When rate is larger than 1.0, pitch becomes higher.
+ * When rate is smaller than 1.0, pitch becomes lower.
+ */
+ public static final int PLAYBACK_RATE_AUDIO_MODE_RESAMPLE = 0;
+
+ /**
+ * Specifies time stretching as audio mode for variable rate playback.
+ * Time stretching changes the duration of the audio samples without
+ * affecting its pitch.
+ * FIXME: implement time strectching.
+ * @hide
+ */
+ public static final int PLAYBACK_RATE_AUDIO_MODE_STRETCH = 1;
+
+ /** @hide */
+ @IntDef(
+ value = {
+ PLAYBACK_RATE_AUDIO_MODE_RESAMPLE,
+ PLAYBACK_RATE_AUDIO_MODE_STRETCH })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PlaybackRateAudioMode {}
+
+ /**
+ * Sets playback rate and audio mode.
+ *
+ * <p> The supported audio modes are:
+ * <ul>
+ * <li> {@link #PLAYBACK_RATE_AUDIO_MODE_RESAMPLE}
+ * </ul>
+ *
+ * @param rate the ratio between desired playback rate and normal one.
+ * @param audioMode audio playback mode. Must be one of the supported
+ * audio modes.
+ *
+ * @throws IllegalStateException if the internal player engine has not been
+ * initialized.
+ * @throws IllegalArgumentException if audioMode is not supported.
+ */
+ public void setPlaybackRate(float rate, @PlaybackRateAudioMode int audioMode) {
+ if (!isAudioPlaybackModeSupported(audioMode)) {
+ final String msg = "Audio playback mode " + audioMode + " is not supported";
+ throw new IllegalArgumentException(msg);
+ }
+ _setPlaybackRate(rate);
+ }
+
+ private native void _setPlaybackRate(float rate) throws IllegalStateException;
+
+ /**
* Seeks to specified time position.
*
* @param msec the offset in milliseconds from the start to seek to
@@ -3078,6 +3139,14 @@
mode == VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING);
}
+ /*
+ * Test whether a given audio playback mode is supported.
+ * TODO query supported AudioPlaybackMode from player.
+ */
+ private boolean isAudioPlaybackModeSupported(int mode) {
+ return (mode == PLAYBACK_RATE_AUDIO_MODE_RESAMPLE);
+ }
+
/** @hide */
static class TimeProvider implements MediaPlayer.OnSeekCompleteListener,
MediaTimeProvider {
diff --git a/media/java/android/media/midi/IMidiListener.aidl b/media/java/android/media/midi/IMidiDeviceListener.aidl
similarity index 95%
rename from media/java/android/media/midi/IMidiListener.aidl
rename to media/java/android/media/midi/IMidiDeviceListener.aidl
index a4129e9..17d9bfd 100644
--- a/media/java/android/media/midi/IMidiListener.aidl
+++ b/media/java/android/media/midi/IMidiDeviceListener.aidl
@@ -19,7 +19,7 @@
import android.media.midi.MidiDeviceInfo;
/** @hide */
-oneway interface IMidiListener
+oneway interface IMidiDeviceListener
{
void onDeviceAdded(in MidiDeviceInfo device);
void onDeviceRemoved(in MidiDeviceInfo device);
diff --git a/media/java/android/media/midi/IMidiManager.aidl b/media/java/android/media/midi/IMidiManager.aidl
index bba35f5..617b03e 100644
--- a/media/java/android/media/midi/IMidiManager.aidl
+++ b/media/java/android/media/midi/IMidiManager.aidl
@@ -16,8 +16,8 @@
package android.media.midi;
+import android.media.midi.IMidiDeviceListener;
import android.media.midi.IMidiDeviceServer;
-import android.media.midi.IMidiListener;
import android.media.midi.MidiDeviceInfo;
import android.os.Bundle;
import android.os.IBinder;
@@ -28,14 +28,20 @@
MidiDeviceInfo[] getDeviceList();
// for device creation & removal notifications
- void registerListener(IBinder token, in IMidiListener listener);
- void unregisterListener(IBinder token, in IMidiListener listener);
+ void registerListener(IBinder token, in IMidiDeviceListener listener);
+ void unregisterListener(IBinder token, in IMidiDeviceListener listener);
- // for communicating with MIDI devices
+ // for opening built-in MIDI devices
IMidiDeviceServer openDevice(IBinder token, in MidiDeviceInfo device);
- // for implementing virtual MIDI devices
+ // for registering built-in MIDI devices
MidiDeviceInfo registerDeviceServer(in IMidiDeviceServer server, int numInputPorts,
- int numOutputPorts, in Bundle properties, boolean isPrivate, int type);
+ int numOutputPorts, in Bundle properties, int type);
+
+ // for unregistering built-in MIDI devices
void unregisterDeviceServer(in IMidiDeviceServer server);
+
+ // used by MidiDeviceService to access the MidiDeviceInfo that was created based on its
+ // manifest's meta-data
+ MidiDeviceInfo getServiceDeviceInfo(String packageName, String className);
}
diff --git a/media/java/android/media/midi/MidiDeviceInfo.java b/media/java/android/media/midi/MidiDeviceInfo.java
index fd35052..b7756fd 100644
--- a/media/java/android/media/midi/MidiDeviceInfo.java
+++ b/media/java/android/media/midi/MidiDeviceInfo.java
@@ -50,6 +50,7 @@
private final int mInputPortCount;
private final int mOutputPortCount;
private final Bundle mProperties;
+ private final boolean mIsPrivate;
/**
* Bundle key for the device's manufacturer name property.
@@ -83,6 +84,8 @@
* Bundle key for the device's ALSA card number.
* Only set for USB MIDI devices.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
+ *
+ * @hide
*/
public static final String PROPERTY_ALSA_CARD = "alsa_card";
@@ -90,20 +93,32 @@
* Bundle key for the device's ALSA device number.
* Only set for USB MIDI devices.
* Used with the {@link android.os.Bundle} returned by {@link #getProperties}
+ *
+ * @hide
*/
public static final String PROPERTY_ALSA_DEVICE = "alsa_device";
/**
+ * {@link android.content.pm.ServiceInfo} for the service hosting the device implementation.
+ * Only set for Virtual MIDI devices.
+ * Used with the {@link android.os.Bundle} returned by {@link #getProperties}
+ *
+ * @hide
+ */
+ public static final String PROPERTY_SERVICE_INFO = "service_info";
+
+ /**
* MidiDeviceInfo should only be instantiated by MidiService implementation
* @hide
*/
public MidiDeviceInfo(int type, int id, int numInputPorts, int numOutputPorts,
- Bundle properties) {
+ Bundle properties, boolean isPrivate) {
mType = type;
mId = id;
mInputPortCount = numInputPorts;
mOutputPortCount = numOutputPorts;
mProperties = properties;
+ mIsPrivate = isPrivate;
}
/**
@@ -152,6 +167,16 @@
return mProperties;
}
+ /**
+ * Returns true if the device is private. Private devices are only visible and accessible
+ * to clients with the same UID as the application that is hosting the device.
+ *
+ * @return true if the device is private
+ */
+ public boolean isPrivate() {
+ return mIsPrivate;
+ }
+
@Override
public boolean equals(Object o) {
if (o instanceof MidiDeviceInfo) {
@@ -171,7 +196,8 @@
return ("MidiDeviceInfo[mType=" + mType +
",mInputPortCount=" + mInputPortCount +
",mOutputPortCount=" + mOutputPortCount +
- ",mProperties=" + mProperties);
+ ",mProperties=" + mProperties +
+ ",mIsPrivate=" + mIsPrivate);
}
public static final Parcelable.Creator<MidiDeviceInfo> CREATOR =
@@ -182,7 +208,8 @@
int inputPorts = in.readInt();
int outputPorts = in.readInt();
Bundle properties = in.readBundle();
- return new MidiDeviceInfo(type, id, inputPorts, outputPorts, properties);
+ boolean isPrivate = (in.readInt() == 1);
+ return new MidiDeviceInfo(type, id, inputPorts, outputPorts, properties, isPrivate);
}
public MidiDeviceInfo[] newArray(int size) {
@@ -200,5 +227,6 @@
parcel.writeInt(mInputPortCount);
parcel.writeInt(mOutputPortCount);
parcel.writeBundle(mProperties);
+ parcel.writeInt(mIsPrivate ? 1 : 0);
}
}
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index 3317baa..24ef528 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -16,21 +16,22 @@
package android.media.midi;
+import android.os.IBinder;
+import android.os.Binder;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.RemoteException;
import android.system.OsConstants;
import android.util.Log;
+import libcore.io.IoUtils;
+
import java.io.Closeable;
import java.io.IOException;
-import java.util.ArrayList;
/**
- * This class is used to provide the implemention of MIDI device.
- * Applications may call {@link MidiManager#createDeviceServer}
- * to create an instance of this class to implement a virtual MIDI device.
+ * Internal class used for providing an implementation for a MIDI device.
*
- * CANDIDATE FOR PUBLIC API
* @hide
*/
public final class MidiDeviceServer implements Closeable {
@@ -40,64 +41,36 @@
// MidiDeviceInfo for the device implemented by this server
private MidiDeviceInfo mDeviceInfo;
- private int mInputPortCount;
- private int mOutputPortCount;
+ private final int mInputPortCount;
+ private final int mOutputPortCount;
- // output ports for receiving messages from our clients
- // we can have only one per port number
- private MidiOutputPort[] mInputPortSenders;
+ // MidiReceivers for receiving data on our input ports
+ private final MidiReceiver[] mInputPortReceivers;
- // receivers attached to our input ports
- private ArrayList<MidiReceiver>[] mInputPortReceivers;
+ // MidiDispatchers for sending data on our output ports
+ private MidiDispatcher[] mOutputPortDispatchers;
- // input ports for sending messages to our clients
- // we can have multiple outputs per port number
- private ArrayList<MidiInputPort>[] mOutputPortReceivers;
-
- // subclass of MidiInputPort for passing to clients
- // that notifies us when the connection has failed
- private class ServerInputPort extends MidiInputPort {
- ServerInputPort(ParcelFileDescriptor pfd, int portNumber) {
- super(pfd, portNumber);
- }
-
- @Override
- public void onIOException() {
- synchronized (mOutputPortReceivers) {
- mOutputPortReceivers[getPortNumber()].clear();
- }
- }
- }
-
- // subclass of MidiOutputPort for passing to clients
- // that notifies us when the connection has failed
- private class ServerOutputPort extends MidiOutputPort {
- ServerOutputPort(ParcelFileDescriptor pfd, int portNumber) {
- super(pfd, portNumber);
- }
-
- @Override
- public void onIOException() {
- synchronized (mInputPortSenders) {
- mInputPortSenders[getPortNumber()] = null;
- }
- }
- }
+ // MidiOutputPorts for clients connected to our input ports
+ private final MidiOutputPort[] mInputPortOutputPorts;
// Binder interface stub for receiving connection requests from clients
private final IMidiDeviceServer mServer = new IMidiDeviceServer.Stub() {
@Override
public ParcelFileDescriptor openInputPort(int portNumber) {
+ if (mDeviceInfo.isPrivate()) {
+ if (Binder.getCallingUid() != Process.myUid()) {
+ throw new SecurityException("Can't access private device from different UID");
+ }
+ }
+
if (portNumber < 0 || portNumber >= mInputPortCount) {
Log.e(TAG, "portNumber out of range in openInputPort: " + portNumber);
return null;
}
- ParcelFileDescriptor result = null;
-
- synchronized (mInputPortSenders) {
- if (mInputPortSenders[portNumber] != null) {
+ synchronized (mInputPortOutputPorts) {
+ if (mInputPortOutputPorts[portNumber] != null) {
Log.d(TAG, "port " + portNumber + " already open");
return null;
}
@@ -105,47 +78,86 @@
try {
ParcelFileDescriptor[] pair = ParcelFileDescriptor.createSocketPair(
OsConstants.SOCK_SEQPACKET);
- MidiOutputPort newOutputPort = new ServerOutputPort(pair[0], portNumber);
- mInputPortSenders[portNumber] = newOutputPort;
- result = pair[1];
+ final MidiOutputPort outputPort = new MidiOutputPort(pair[0], portNumber);
+ mInputPortOutputPorts[portNumber] = outputPort;
+ final int portNumberF = portNumber;
+ final MidiReceiver inputPortReceviver = mInputPortReceivers[portNumber];
- ArrayList<MidiReceiver> receivers = mInputPortReceivers[portNumber];
- synchronized (receivers) {
- for (int i = 0; i < receivers.size(); i++) {
- newOutputPort.connect(receivers.get(i));
+ outputPort.connect(new MidiReceiver() {
+ @Override
+ public void post(byte[] msg, int offset, int count, long timestamp)
+ throws IOException {
+ try {
+ inputPortReceviver.post(msg, offset, count, timestamp);
+ } catch (IOException e) {
+ IoUtils.closeQuietly(mInputPortOutputPorts[portNumberF]);
+ mInputPortOutputPorts[portNumberF] = null;
+ // FIXME also flush the receiver
+ }
}
- }
+ });
+
+ return pair[1];
} catch (IOException e) {
Log.e(TAG, "unable to create ParcelFileDescriptors in openInputPort");
return null;
}
}
-
- return result;
}
@Override
public ParcelFileDescriptor openOutputPort(int portNumber) {
+ if (mDeviceInfo.isPrivate()) {
+ if (Binder.getCallingUid() != Process.myUid()) {
+ throw new SecurityException("Can't access private device from different UID");
+ }
+ }
+
if (portNumber < 0 || portNumber >= mOutputPortCount) {
Log.e(TAG, "portNumber out of range in openOutputPort: " + portNumber);
return null;
}
- synchronized (mOutputPortReceivers) {
- try {
- ParcelFileDescriptor[] pair = ParcelFileDescriptor.createSocketPair(
- OsConstants.SOCK_SEQPACKET);
- mOutputPortReceivers[portNumber].add(new ServerInputPort(pair[0], portNumber));
- return pair[1];
- } catch (IOException e) {
- Log.e(TAG, "unable to create ParcelFileDescriptors in openOutputPort");
- return null;
- }
+
+ try {
+ ParcelFileDescriptor[] pair = ParcelFileDescriptor.createSocketPair(
+ OsConstants.SOCK_SEQPACKET);
+ final MidiInputPort inputPort = new MidiInputPort(pair[0], portNumber);
+ final MidiSender sender = mOutputPortDispatchers[portNumber].getSender();
+ sender.connect(new MidiReceiver() {
+ @Override
+ public void post(byte[] msg, int offset, int count, long timestamp)
+ throws IOException {
+ try {
+ inputPort.post(msg, offset, count, timestamp);
+ } catch (IOException e) {
+ IoUtils.closeQuietly(inputPort);
+ sender.disconnect(this);
+ // FIXME also flush the receiver?
+ }
+ }
+ });
+
+ return pair[1];
+ } catch (IOException e) {
+ Log.e(TAG, "unable to create ParcelFileDescriptors in openOutputPort");
+ return null;
}
}
};
- /* package */ MidiDeviceServer(IMidiManager midiManager) {
+ /* package */ MidiDeviceServer(IMidiManager midiManager, MidiReceiver[] inputPortReceivers,
+ int numOutputPorts) {
mMidiManager = midiManager;
+ mInputPortReceivers = inputPortReceivers;
+ mInputPortCount = inputPortReceivers.length;
+ mOutputPortCount = numOutputPorts;
+
+ mInputPortOutputPorts = new MidiOutputPort[mInputPortCount];
+
+ mOutputPortDispatchers = new MidiDispatcher[numOutputPorts];
+ for (int i = 0; i < numOutputPorts; i++) {
+ mOutputPortDispatchers[i] = new MidiDispatcher();
+ }
}
/* package */ IMidiDeviceServer getBinderInterface() {
@@ -157,19 +169,6 @@
throw new IllegalStateException("setDeviceInfo should only be called once");
}
mDeviceInfo = deviceInfo;
- mInputPortCount = deviceInfo.getInputPortCount();
- mOutputPortCount = deviceInfo.getOutputPortCount();
- mInputPortSenders = new MidiOutputPort[mInputPortCount];
-
- mInputPortReceivers = new ArrayList[mInputPortCount];
- for (int i = 0; i < mInputPortCount; i++) {
- mInputPortReceivers[i] = new ArrayList<MidiReceiver>();
- }
-
- mOutputPortReceivers = new ArrayList[mOutputPortCount];
- for (int i = 0; i < mOutputPortCount; i++) {
- mOutputPortReceivers[i] = new ArrayList<MidiInputPort>();
- }
}
@Override
@@ -183,86 +182,13 @@
}
/**
- * Returns a {@link MidiDeviceInfo} object, which describes this device.
- *
- * @return the {@link MidiDeviceInfo} object
+ * Returns an array of {@link MidiReceiver} for the device's output ports.
+ * Clients can use these receivers to send data out the device's output ports.
+ * @return array of MidiReceivers
*/
- public MidiDeviceInfo getInfo() {
- return mDeviceInfo;
- }
-
- /**
- * Called to open a {@link MidiSender} to allow receiving MIDI messages
- * on the device's input port for the specified port number.
- *
- * @param portNumber the number of the input port
- * @return the {@link MidiSender}
- */
- public MidiSender openInputPortSender(int portNumber) {
- if (portNumber < 0 || portNumber >= mDeviceInfo.getInputPortCount()) {
- throw new IllegalArgumentException("portNumber " + portNumber + " out of range");
- }
- final int portNumberF = portNumber;
- return new MidiSender() {
-
- @Override
- public void connect(MidiReceiver receiver) {
- // We always synchronize on mInputPortSenders before receivers if we need to
- // synchronize on both.
- synchronized (mInputPortSenders) {
- ArrayList<MidiReceiver> receivers = mInputPortReceivers[portNumberF];
- synchronized (receivers) {
- receivers.add(receiver);
- MidiOutputPort outputPort = mInputPortSenders[portNumberF];
- if (outputPort != null) {
- outputPort.connect(receiver);
- }
- }
- }
- }
-
- @Override
- public void disconnect(MidiReceiver receiver) {
- // We always synchronize on mInputPortSenders before receivers if we need to
- // synchronize on both.
- synchronized (mInputPortSenders) {
- ArrayList<MidiReceiver> receivers = mInputPortReceivers[portNumberF];
- synchronized (receivers) {
- receivers.remove(receiver);
- MidiOutputPort outputPort = mInputPortSenders[portNumberF];
- if (outputPort != null) {
- outputPort.disconnect(receiver);
- }
- }
- }
- }
- };
- }
-
- /**
- * Called to open a {@link MidiReceiver} to allow sending MIDI messages
- * on the virtual device's output port for the specified port number.
- *
- * @param portNumber the number of the output port
- * @return the {@link MidiReceiver}
- */
- public MidiReceiver openOutputPortReceiver(int portNumber) {
- if (portNumber < 0 || portNumber >= mDeviceInfo.getOutputPortCount()) {
- throw new IllegalArgumentException("portNumber " + portNumber + " out of range");
- }
- final int portNumberF = portNumber;
- return new MidiReceiver() {
-
- @Override
- public void post(byte[] msg, int offset, int count, long timestamp) throws IOException {
- ArrayList<MidiInputPort> receivers = mOutputPortReceivers[portNumberF];
- synchronized (receivers) {
- for (int i = 0; i < receivers.size(); i++) {
- // FIXME catch errors and remove dead ones
- receivers.get(i).post(msg, offset, count, timestamp);
- }
- }
- }
- };
+ public MidiReceiver[] getOutputPortReceivers() {
+ MidiReceiver[] receivers = new MidiReceiver[mOutputPortCount];
+ System.arraycopy(mOutputPortDispatchers, 0, receivers, 0, mOutputPortCount);
+ return receivers;
}
}
diff --git a/media/java/android/media/midi/MidiDeviceService.java b/media/java/android/media/midi/MidiDeviceService.java
new file mode 100644
index 0000000..1d91be2
--- /dev/null
+++ b/media/java/android/media/midi/MidiDeviceService.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.midi;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * A service that implements a virtual MIDI device.
+ * Subclasses must implement the {@link #getInputPortReceivers} method to provide a
+ * list of {@link MidiReceiver}s to receive data sent to the device's input ports.
+ * Similarly, subclasses can call {@link #getOutputPortReceivers} to fetch a list
+ * of {@link MidiReceiver}s for sending data out the output ports.
+ *
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * an intent filter with the {@link #SERVICE_INTERFACE} action
+ * and meta-data to describe the virtual device.
+ For example:</p>
+ * <pre>
+ * <service android:name=".VirtualDeviceService"
+ * android:label="@string/service_name">
+ * <intent-filter>
+ * <action android:name="android.media.midi.MidiDeviceService" />
+ * </intent-filter>
+ * <meta-data android:name="android.media.midi.MidiDeviceService"
+ android:resource="@xml/device_info" />
+ * </service></pre>
+ *
+ * CANDIDATE FOR PUBLIC API
+ * @hide
+ */
+abstract public class MidiDeviceService extends Service {
+ private static final String TAG = "MidiDeviceService";
+
+ public static final String SERVICE_INTERFACE = "android.media.midi.MidiDeviceService";
+
+ private IMidiManager mMidiManager;
+ private MidiDeviceServer mServer;
+
+ @Override
+ public void onCreate() {
+ mMidiManager = IMidiManager.Stub.asInterface(
+ ServiceManager.getService(Context.MIDI_SERVICE));
+ MidiDeviceServer server;
+ try {
+ MidiDeviceInfo deviceInfo = mMidiManager.getServiceDeviceInfo(getPackageName(),
+ this.getClass().getName());
+ MidiReceiver[] inputPortReceivers = getInputPortReceivers();
+ if (inputPortReceivers == null) {
+ inputPortReceivers = new MidiReceiver[0];
+ }
+ server = new MidiDeviceServer(mMidiManager, inputPortReceivers,
+ deviceInfo.getOutputPortCount());
+ server.setDeviceInfo(deviceInfo);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in IMidiManager.getServiceDeviceInfo");
+ server = null;
+ }
+ mServer = server;
+ }
+
+ /**
+ * Returns an array of {@link MidiReceiver} for the device's input ports.
+ * Subclasses must override this to provide the receivers which will receive
+ * data sent to the device's input ports. An empty array or null should be returned if
+ * the device has no input ports.
+ * @return array of MidiReceivers
+ */
+ abstract public MidiReceiver[] getInputPortReceivers();
+
+ /**
+ * Returns an array of {@link MidiReceiver} for the device's output ports.
+ * These can be used to send data out the device's output ports.
+ * @return array of MidiReceivers
+ */
+ public MidiReceiver[] getOutputPortReceivers() {
+ if (mServer == null) {
+ return null;
+ } else {
+ return mServer.getOutputPortReceivers();
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (SERVICE_INTERFACE.equals(intent.getAction()) && mServer != null) {
+ return mServer.getBinderInterface().asBinder();
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/media/java/android/media/midi/MidiDispatcher.java b/media/java/android/media/midi/MidiDispatcher.java
new file mode 100644
index 0000000..165061f
--- /dev/null
+++ b/media/java/android/media/midi/MidiDispatcher.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.midi;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Utility class for dispatching MIDI data to a list of {@link MidiReceiver}s.
+ * This class subclasses {@link MidiReceiver} and dispatches any data it receives
+ * to its receiver list. Any receivers that throw an exception upon receiving data will
+ * be automatically removed from the receiver list, but no IOException will be returned
+ * from the dispatcher's {@link #post} in that case.
+ *
+ * CANDIDATE FOR PUBLIC API
+ * @hide
+ */
+public class MidiDispatcher implements MidiReceiver {
+
+ private final ArrayList<MidiReceiver> mReceivers = new ArrayList<MidiReceiver>();
+
+ private final MidiSender mSender = new MidiSender() {
+ /**
+ * Called to connect a {@link MidiReceiver} to the sender
+ *
+ * @param receiver the receiver to connect
+ */
+ public void connect(MidiReceiver receiver) {
+ mReceivers.add(receiver);
+ }
+
+ /**
+ * Called to disconnect a {@link MidiReceiver} from the sender
+ *
+ * @param receiver the receiver to disconnect
+ */
+ public void disconnect(MidiReceiver receiver) {
+ mReceivers.remove(receiver);
+ }
+ };
+
+ /**
+ * Returns whether this dispatcher contains any receivers.
+ * @return true if the receiver list is not empty
+ */
+ public boolean hasReceivers() {
+ return mReceivers.size() > 0;
+ }
+
+ /**
+ * Returns a {@link MidiSender} which is used to add and remove {@link MidiReceiver}s
+ * to the dispatcher's receiver list.
+ * @return the dispatcher's MidiSender
+ */
+ public MidiSender getSender() {
+ return mSender;
+ }
+
+ @Override
+ public void post(byte[] msg, int offset, int count, long timestamp) throws IOException {
+ synchronized (mReceivers) {
+ for (int i = 0; i < mReceivers.size(); ) {
+ MidiReceiver receiver = mReceivers.get(i);
+ try {
+ receiver.post(msg, offset, count, timestamp);
+ i++; // increment only on success. on failure we remove the receiver
+ // so i should not be incremented
+ } catch (IOException e) {
+ // if the receiver fails we remove the receiver but do not propogate the exception
+ mSender.disconnect(receiver);
+ }
+ }
+ }
+ }
+}
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index a502e3e..ca7d3c2 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -16,7 +16,11 @@
package android.media.midi;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.IBinder;
import android.os.Bundle;
@@ -49,7 +53,7 @@
new HashMap<DeviceCallback,DeviceListener>();
// Binder stub for receiving device notifications from MidiService
- private class DeviceListener extends IMidiListener.Stub {
+ private class DeviceListener extends IMidiDeviceListener.Stub {
private final DeviceCallback mCallback;
private final Handler mHandler;
@@ -88,22 +92,33 @@
/**
* Callback class used for clients to receive MIDI device added and removed notifications
*/
- public static class DeviceCallback {
+ abstract public static class DeviceCallback {
/**
* Called to notify when a new MIDI device has been added
*
* @param device a {@link MidiDeviceInfo} for the newly added device
*/
- public void onDeviceAdded(MidiDeviceInfo device) {
- }
+ abstract public void onDeviceAdded(MidiDeviceInfo device);
/**
* Called to notify when a MIDI device has been removed
*
* @param device a {@link MidiDeviceInfo} for the removed device
*/
- public void onDeviceRemoved(MidiDeviceInfo device) {
- }
+ abstract public void onDeviceRemoved(MidiDeviceInfo device);
+ }
+
+ /**
+ * Callback class used for receiving the results of {@link #openDevice}
+ */
+ abstract public static class DeviceOpenCallback {
+ /**
+ * Called to respond to a {@link #openDevice} request
+ *
+ * @param deviceInfo the {@link MidiDeviceInfo} for the device to open
+ * @param device a {@link MidiDevice} for opened device, or null if opening failed
+ */
+ abstract public void onDeviceOpened(MidiDeviceInfo deviceInfo, MidiDevice device);
}
/**
@@ -163,33 +178,85 @@
}
}
+ private void sendOpenDeviceResponse(final MidiDeviceInfo deviceInfo, final MidiDevice device,
+ final DeviceOpenCallback callback, Handler handler) {
+ if (handler != null) {
+ handler.post(new Runnable() {
+ @Override public void run() {
+ callback.onDeviceOpened(deviceInfo, device);
+ }
+ });
+ } else {
+ callback.onDeviceOpened(deviceInfo, device);
+ }
+ }
+
/**
* Opens a MIDI device for reading and writing.
*
* @param deviceInfo a {@link android.media.midi.MidiDeviceInfo} to open
- * @return a {@link MidiDevice} object for the device
+ * @param callback a {@link #DeviceOpenCallback} to be called to receive the result
+ * @param handler the {@link android.os.Handler Handler} that will be used for delivering
+ * the result. If handler is null, then the thread used for the
+ * callback is unspecified.
*/
- public MidiDevice openDevice(MidiDeviceInfo deviceInfo) {
+ public void openDevice(MidiDeviceInfo deviceInfo, DeviceOpenCallback callback,
+ Handler handler) {
+ MidiDevice device = null;
try {
IMidiDeviceServer server = mService.openDevice(mToken, deviceInfo);
if (server == null) {
- Log.e(TAG, "could not open device " + deviceInfo);
- return null;
+ ServiceInfo serviceInfo = (ServiceInfo)deviceInfo.getProperties().getParcelable(
+ MidiDeviceInfo.PROPERTY_SERVICE_INFO);
+ if (serviceInfo == null) {
+ Log.e(TAG, "no ServiceInfo for " + deviceInfo);
+ } else {
+ Intent intent = new Intent(MidiDeviceService.SERVICE_INTERFACE);
+ intent.setComponent(new ComponentName(serviceInfo.packageName,
+ serviceInfo.name));
+ final MidiDeviceInfo deviceInfoF = deviceInfo;
+ final DeviceOpenCallback callbackF = callback;
+ final Handler handlerF = handler;
+ if (mContext.bindService(intent,
+ new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder binder) {
+ IMidiDeviceServer server =
+ IMidiDeviceServer.Stub.asInterface(binder);
+ MidiDevice device = new MidiDevice(deviceInfoF, server);
+ sendOpenDeviceResponse(deviceInfoF, device, callbackF, handlerF);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ // FIXME - anything to do here?
+ }
+ },
+ Context.BIND_AUTO_CREATE))
+ {
+ // return immediately to avoid calling sendOpenDeviceResponse below
+ return;
+ } else {
+ Log.e(TAG, "Unable to bind service: " + intent);
+ }
+ }
+ } else {
+ device = new MidiDevice(deviceInfo, server);
}
- return new MidiDevice(deviceInfo, server);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in openDevice");
}
- return null;
+ sendOpenDeviceResponse(deviceInfo, device, callback, handler);
}
/** @hide */
- public MidiDeviceServer createDeviceServer(int numInputPorts, int numOutputPorts,
- Bundle properties, boolean isPrivate, int type) {
+ public MidiDeviceServer createDeviceServer(MidiReceiver[] inputPortReceivers,
+ int numOutputPorts, Bundle properties, int type) {
try {
- MidiDeviceServer server = new MidiDeviceServer(mService);
+ MidiDeviceServer server = new MidiDeviceServer(mService, inputPortReceivers,
+ numOutputPorts);
MidiDeviceInfo deviceInfo = mService.registerDeviceServer(server.getBinderInterface(),
- numInputPorts, numOutputPorts, properties, isPrivate, type);
+ inputPortReceivers.length, numOutputPorts, properties, type);
if (deviceInfo == null) {
Log.e(TAG, "registerVirtualDevice failed");
return null;
@@ -201,21 +268,4 @@
return null;
}
}
-
- /**
- * Creates a new MIDI virtual device.
- *
- * @param numInputPorts number of input ports for the virtual device
- * @param numOutputPorts number of output ports for the virtual device
- * @param properties a {@link android.os.Bundle} containing properties describing the device
- * @param isPrivate true if this device should only be visible and accessible to apps
- * with the same UID as the caller
- * @return a {@link MidiDeviceServer} object to locally represent the device
- */
- public MidiDeviceServer createDeviceServer(int numInputPorts, int numOutputPorts,
- Bundle properties, boolean isPrivate) {
- return createDeviceServer(numInputPorts, numOutputPorts, properties,
- isPrivate, MidiDeviceInfo.TYPE_VIRTUAL);
- }
-
}
diff --git a/media/java/android/media/midi/MidiOutputPort.java b/media/java/android/media/midi/MidiOutputPort.java
index 83ddeeb..c195603 100644
--- a/media/java/android/media/midi/MidiOutputPort.java
+++ b/media/java/android/media/midi/MidiOutputPort.java
@@ -23,7 +23,6 @@
import java.io.FileInputStream;
import java.io.IOException;
-import java.util.ArrayList;
/**
* This class is used for receiving data from a port on a MIDI device
@@ -35,11 +34,7 @@
private static final String TAG = "MidiOutputPort";
private final FileInputStream mInputStream;
-
- // array of receiver lists, indexed by port number
- private final ArrayList<MidiReceiver> mReceivers = new ArrayList<MidiReceiver>();
-
- private int mReceiverCount; // total number of receivers for all ports
+ private final MidiDispatcher mDispatcher = new MidiDispatcher();
// This thread reads MIDI events from a socket and distributes them to the list of
// MidiReceivers attached to this device.
@@ -47,7 +42,6 @@
@Override
public void run() {
byte[] buffer = new byte[MAX_PACKET_SIZE];
- ArrayList<MidiReceiver> deadReceivers = new ArrayList<MidiReceiver>();
try {
while (true) {
@@ -55,77 +49,39 @@
int count = mInputStream.read(buffer);
if (count < 0) {
break;
+ // FIXME - inform receivers here?
}
int offset = getMessageOffset(buffer, count);
int size = getMessageSize(buffer, count);
long timestamp = getMessageTimeStamp(buffer, count);
- synchronized (mReceivers) {
- for (int i = 0; i < mReceivers.size(); i++) {
- MidiReceiver receiver = mReceivers.get(i);
- try {
- receiver.post(buffer, offset, size, timestamp);
- } catch (IOException e) {
- Log.e(TAG, "post failed");
- deadReceivers.add(receiver);
- }
- }
- // remove any receivers that failed
- if (deadReceivers.size() > 0) {
- for (MidiReceiver receiver: deadReceivers) {
- mReceivers.remove(receiver);
- mReceiverCount--;
- }
- deadReceivers.clear();
- }
- // exit if we have no receivers left
- if (mReceiverCount == 0) {
- break;
- }
- }
+ // dispatch to all our receivers
+ mDispatcher.post(buffer, offset, size, timestamp);
}
} catch (IOException e) {
- // report I/O failure
+ // FIXME report I/O failure?
Log.e(TAG, "read failed");
} finally {
IoUtils.closeQuietly(mInputStream);
- onIOException();
}
}
};
- /* package */ MidiOutputPort(ParcelFileDescriptor pfd, int portNumber) {
+ /* package */ MidiOutputPort(ParcelFileDescriptor pfd, int portNumber) {
super(portNumber);
mInputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ mThread.start();
}
- /**
- * Connects a {@link MidiReceiver} to the output port to allow receiving
- * MIDI messages from the port.
- *
- * @param receiver the receiver to connect
- */
+ @Override
public void connect(MidiReceiver receiver) {
- synchronized (mReceivers) {
- mReceivers.add(receiver);
- if (mReceiverCount++ == 0) {
- mThread.start();
- }
- }
+ mDispatcher.getSender().connect(receiver);
}
- /**
- * Disconnects a {@link MidiReceiver} from the output port.
- *
- * @param receiver the receiver to connect
- */
+ @Override
public void disconnect(MidiReceiver receiver) {
- synchronized (mReceivers) {
- if (mReceivers.remove(receiver)) {
- mReceiverCount--;
- }
- }
+ mDispatcher.getSender().disconnect(receiver);
}
@Override
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 93138fa..2f6bbf4 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -40,7 +40,6 @@
struct fields_t {
jfieldID context;
jclass bitmapClazz; // Must be a global ref
- jfieldID nativeBitmap;
jmethodID createBitmapMethod;
jmethodID createScaledBitmapMethod;
jclass configClazz; // Must be a global ref
@@ -282,8 +281,7 @@
return NULL;
}
- SkBitmap *bitmap =
- (SkBitmap *) env->GetLongField(jBitmap, fields.nativeBitmap);
+ SkBitmap *bitmap = GraphicsJNI::getSkBitmap(env, jBitmap);
bitmap->lockPixels();
rotate((uint16_t*)bitmap->getPixels(),
@@ -421,10 +419,6 @@
if (fields.createScaledBitmapMethod == NULL) {
return;
}
- fields.nativeBitmap = env->GetFieldID(fields.bitmapClazz, "mNativeBitmap", "J");
- if (fields.nativeBitmap == NULL) {
- return;
- }
jclass configClazz = env->FindClass("android/graphics/Bitmap$Config");
if (configClazz == NULL) {
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 820de5b..55643f7 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -402,6 +402,18 @@
}
static void
+android_media_MediaPlayer_setPlaybackRate(JNIEnv *env, jobject thiz, jfloat rate)
+{
+ sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+ if (mp == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+ ALOGV("setPlaybackRate: %f", rate);
+ process_media_player_call(env, thiz, mp->setPlaybackRate(rate), NULL, NULL);
+}
+
+static void
android_media_MediaPlayer_seekTo(JNIEnv *env, jobject thiz, jint msec)
{
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
@@ -867,6 +879,7 @@
{"_stop", "()V", (void *)android_media_MediaPlayer_stop},
{"getVideoWidth", "()I", (void *)android_media_MediaPlayer_getVideoWidth},
{"getVideoHeight", "()I", (void *)android_media_MediaPlayer_getVideoHeight},
+ {"_setPlaybackRate", "(F)V", (void *)android_media_MediaPlayer_setPlaybackRate},
{"seekTo", "(I)V", (void *)android_media_MediaPlayer_seekTo},
{"_pause", "()V", (void *)android_media_MediaPlayer_pause},
{"isPlaying", "()Z", (void *)android_media_MediaPlayer_isPlaying},
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index a73209b..dfe2844 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -256,7 +256,7 @@
dump();
// allocate a channel
- channel = allocateChannel_l(priority);
+ channel = allocateChannel_l(priority, sampleID);
// no channel allocated - return 0
if (!channel) {
@@ -271,13 +271,25 @@
return channelID;
}
-SoundChannel* SoundPool::allocateChannel_l(int priority)
+SoundChannel* SoundPool::allocateChannel_l(int priority, int sampleID)
{
List<SoundChannel*>::iterator iter;
SoundChannel* channel = NULL;
- // allocate a channel
+ // check if channel for given sampleID still available
if (!mChannels.empty()) {
+ for (iter = mChannels.begin(); iter != mChannels.end(); ++iter) {
+ if (sampleID == (*iter)->getPrevSampleID() && (*iter)->state() == SoundChannel::IDLE) {
+ channel = *iter;
+ mChannels.erase(iter);
+ ALOGV("Allocated recycled channel for same sampleID");
+ break;
+ }
+ }
+ }
+
+ // allocate any channel
+ if (!channel && !mChannels.empty()) {
iter = mChannels.begin();
if (priority >= (*iter)->priority()) {
channel = *iter;
@@ -648,6 +660,7 @@
void SoundChannel::init(SoundPool* soundPool)
{
mSoundPool = soundPool;
+ mPrevSampleID = -1;
}
// call with sound pool lock held
@@ -656,7 +669,7 @@
{
sp<AudioTrack> oldTrack;
sp<AudioTrack> newTrack;
- status_t status;
+ status_t status = NO_ERROR;
{ // scope for the lock
Mutex::Autolock lock(&mLock);
@@ -701,38 +714,43 @@
}
#endif
- // mToggle toggles each time a track is started on a given channel.
- // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
- // as callback user data. This enables the detection of callbacks received from the old
- // audio track while the new one is being started and avoids processing them with
- // wrong audio audio buffer size (mAudioBufferSize)
- unsigned long toggle = mToggle ^ 1;
- void *userData = (void *)((unsigned long)this | toggle);
- audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels);
+ if (!mAudioTrack.get() || mPrevSampleID != sample->sampleID()) {
+ // mToggle toggles each time a track is started on a given channel.
+ // The toggle is concatenated with the SoundChannel address and passed to AudioTrack
+ // as callback user data. This enables the detection of callbacks received from the old
+ // audio track while the new one is being started and avoids processing them with
+ // wrong audio audio buffer size (mAudioBufferSize)
+ unsigned long toggle = mToggle ^ 1;
+ void *userData = (void *)((unsigned long)this | toggle);
+ audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(numChannels);
- // do not create a new audio track if current track is compatible with sample parameters
-#ifdef USE_SHARED_MEM_BUFFER
- newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
- channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
-#else
- uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
- newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
- channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
- bufferFrames);
-#endif
- oldTrack = mAudioTrack;
- status = newTrack->initCheck();
- if (status != NO_ERROR) {
- ALOGE("Error creating AudioTrack");
- goto exit;
+ // do not create a new audio track if current track is compatible with sample parameters
+ #ifdef USE_SHARED_MEM_BUFFER
+ newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+ channelMask, sample->getIMemory(), AUDIO_OUTPUT_FLAG_FAST, callback, userData);
+ #else
+ uint32_t bufferFrames = (totalFrames + (kDefaultBufferCount - 1)) / kDefaultBufferCount;
+ newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
+ channelMask, frameCount, AUDIO_OUTPUT_FLAG_FAST, callback, userData,
+ bufferFrames);
+ #endif
+ oldTrack = mAudioTrack;
+ status = newTrack->initCheck();
+ if (status != NO_ERROR) {
+ ALOGE("Error creating AudioTrack");
+ goto exit;
+ }
+ // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
+ mToggle = toggle;
+ mAudioTrack = newTrack;
+ ALOGV("using new track %p for sample %d", newTrack.get(), sample->sampleID());
+ } else {
+ newTrack = mAudioTrack;
+ newTrack->setSampleRate(sampleRate);
+ ALOGV("reusing track %p for sample %d", mAudioTrack.get(), sample->sampleID());
}
- ALOGV("setVolume %p", newTrack.get());
newTrack->setVolume(leftVolume, rightVolume);
newTrack->setLoop(0, frameCount, loop);
-
- // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
- mToggle = toggle;
- mAudioTrack = newTrack;
mPos = 0;
mSample = sample;
mChannelID = nextChannelID;
@@ -875,6 +893,7 @@
setVolume_l(0, 0);
ALOGV("stop");
mAudioTrack->stop();
+ mPrevSampleID = mSample->sampleID();
mSample.clear();
mState = IDLE;
mPriority = IDLE_PRIORITY;
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 9d9cbdf..f520406 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -136,6 +136,7 @@
void nextEvent();
int nextChannelID() { return mNextEvent.channelID(); }
void dump();
+ int getPrevSampleID(void) { return mPrevSampleID; }
private:
static void callback(int event, void* user, void *info);
@@ -152,6 +153,7 @@
int mAudioBufferSize;
unsigned long mToggle;
bool mAutoPaused;
+ int mPrevSampleID;
};
// application object for managing a pool of sounds
@@ -193,7 +195,7 @@
sp<Sample> findSample(int sampleID) { return mSamples.valueFor(sampleID); }
SoundChannel* findChannel (int channelID);
SoundChannel* findNextChannel (int channelID);
- SoundChannel* allocateChannel_l(int priority);
+ SoundChannel* allocateChannel_l(int priority, int sampleID);
void moveToFront_l(SoundChannel* channel);
void notify(SoundPoolEvent event);
void dump();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index cc50c43..362bbc4 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -316,6 +316,11 @@
throws RemoteException {
Log.v(TAG, String.format("Camera %d has status changed to 0x%x", cameraId, status));
}
+ public void onTorchStatusChanged(int status, String cameraId)
+ throws RemoteException {
+ Log.v(TAG, String.format("Camera %s has torch status changed to 0x%x",
+ cameraId, status));
+ }
}
/**
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index ea32edc..ddb01a0 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -27,7 +27,7 @@
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
- SkBitmap* bm = GraphicsJNI::getNativeBitmap(env, jbitmap);
+ SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
if (NULL == bm) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
@@ -64,7 +64,7 @@
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
- SkBitmap* bm = GraphicsJNI::getNativeBitmap(env, jbitmap);
+ SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
if (NULL == bm) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
@@ -87,7 +87,7 @@
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
- SkBitmap* bm = GraphicsJNI::getNativeBitmap(env, jbitmap);
+ SkBitmap* bm = GraphicsJNI::getSkBitmap(env, jbitmap);
if (NULL == bm) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java
index a9d33dd..4d890c9 100644
--- a/opengl/java/android/opengl/GLUtils.java
+++ b/opengl/java/android/opengl/GLUtils.java
@@ -29,14 +29,6 @@
public final class GLUtils {
- /*
- * We use a class initializer to allow the native code to cache some
- * field offsets.
- */
- static {
- nativeClassInit();
- }
-
private GLUtils() {
}
@@ -275,8 +267,6 @@
*/
native public static void setTracingLevel(int level);
- native private static void nativeClassInit();
-
native private static int native_getInternalFormat(Bitmap bitmap);
native private static int native_getType(Bitmap bitmap);
native private static int native_texImage2D(int target, int level, int internalformat,
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index 908fb4c..049552c 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -231,7 +231,7 @@
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"বিমান মোড"</string>
<string name="quick_settings_dnd_label" msgid="8735855737575028208">"বিরক্ত করবেন না"</string>
<string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"শুধুমাত্র অগ্রাধিকার"</string>
- <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"কোন বাধা নয়"</string>
+ <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"কোনো বাধা নয়"</string>
<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>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index dc50de5..fde6fd2 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -231,7 +231,7 @@
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"हवाई जहाज़ मोड"</string>
<string name="quick_settings_dnd_label" msgid="8735855737575028208">"परेशान ना करें"</string>
<string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"केवल प्राथमिकता"</string>
- <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"कोई बाधा नहीं"</string>
+ <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"कोई मेसज और कॉल को नहीं रोका गया"</string>
<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>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index d58ef52..c995637 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -176,16 +176,11 @@
<string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"បើករបៀបជិះយន្តហោះ។"</string>
<string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"បានបិទរបៀបជិះយន្តហោះ។"</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"បានបើករបៀបជិះយន្តហោះ។"</string>
- <!-- no translation found for accessibility_quick_settings_dnd_priority_on (1448402297221249355) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_dnd_none_on (5910777408232088752) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_dnd_off (2371832603753738581) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_dnd_changed_off (898107593453022935) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_dnd_changed_on (4483780856613561039) -->
- <skip />
+ <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"បានបើកមុខងារកុំរំខាន (អាទិភាពប៉ុណ្ណោះ)។"</string>
+ <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"បានបើកមុខងារកុំរំខាន សូមកុំរំខាន"</string>
+ <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"បានបិទមុខងារកុំរំខាន។"</string>
+ <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"បានបិទមុខងារកុំរំខាន។"</string>
+ <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"បានបើកមុខងារកុំរំខាន។"</string>
<string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"បិទប៊្លូធូស។"</string>
<string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"បើកប៊្លូធូស។"</string>
<string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"ការភ្ជាប់ប៊្លូធូស។"</string>
@@ -234,12 +229,9 @@
<string name="start_dreams" msgid="7219575858348719790">"ធាតុរក្សាអេក្រង់"</string>
<string name="ethernet_label" msgid="7967563676324087464">"អ៊ីសឺរណិត"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"របៀបពេលជិះយន្តហោះ"</string>
- <!-- no translation found for quick_settings_dnd_label (8735855737575028208) -->
- <skip />
- <!-- no translation found for quick_settings_dnd_priority_label (483232950670692036) -->
- <skip />
- <!-- no translation found for quick_settings_dnd_none_label (7309935569360609114) -->
- <skip />
+ <string name="quick_settings_dnd_label" msgid="8735855737575028208">"កុំរំខាន"</string>
+ <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"អាទិភាពប៉ុណ្ណោះ"</string>
+ <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"សូមកុំរំខាន"</string>
<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>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index a1854ad..a6869a5 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -176,11 +176,11 @@
<string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"हवाइजहाज मोड खुला।"</string>
<string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"हवाइजहाज मोड बन्द छ।"</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"हवाइजहाज मोड खोलियो।"</string>
- <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"प्राथमिकता मात्र मा बाधा नपुर्याउनुहोस्।"</string>
- <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"कुनै रुकावटहरूमा बाधा नगर्नुहोस्।"</string>
- <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"बन्दलाई बाधा नपुर्याउनुहोस्"</string>
- <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"बन्द गर्नेलाई अवरोध नपुर्याउनुहोस्।"</string>
- <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"चालु रहेकोलाई अवरोध नपुर्याउनुहोस्।"</string>
+ <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"प्राथमिकतालाई मात्र बाधा नपुर्याउनुहोस्।"</string>
+ <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"बाधा नपुर्याउँनुहोस्, कुनै पनि अवरोध छैनन्।"</string>
+ <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"निष्क्रियलाई बाधा नपुर्याउनुहोस्"</string>
+ <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"निष्क्रिय गरिएकालाई अवरोध नपुर्याउनुहोस्।"</string>
+ <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"सक्रिय रहेकोलाई अवरोध नपुर्याउनुहोस्।"</string>
<string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"ब्लुटुथ बन्द छ।"</string>
<string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"ब्लुटुथ खुला छ।"</string>
<string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"ब्लुटुथ जोडीदै।"</string>
@@ -229,9 +229,9 @@
<string name="start_dreams" msgid="7219575858348719790">"दिवासपना"</string>
<string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"हवाइजहाज मोड"</string>
- <string name="quick_settings_dnd_label" msgid="8735855737575028208">"नअल्मल्याउनुहोस्"</string>
+ <string name="quick_settings_dnd_label" msgid="8735855737575028208">"बाधा नपुर्याउँनुहोस्"</string>
<string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"प्राथमिकता मात्र"</string>
- <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"कुनै रुकावटहरू छैन"</string>
+ <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"कुनै अवरोधहरू छैन"</string>
<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>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 84b7a9c..1acdace 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -313,8 +313,8 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="8524949573675922138">"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 direita para usar o telefone"</string>
- <string name="camera_hint" msgid="5241441720959174226">"Deslize para a esquerda para usar a câmera"</string>
+ <string name="phone_hint" msgid="3101468054914424646">"Deslize à direita p/ usar o telefone"</string>
+ <string name="camera_hint" msgid="5241441720959174226">"Deslize à esquerda p/ usar a câmera"</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>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e49c20b..4ca33f6 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -181,7 +181,7 @@
<string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Режим полета отключен."</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Режим полета включен."</string>
<string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Режим \"Не беспокоить\" включен. Будут показаны только важные оповещения."</string>
- <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Режим \"Не беспокоить\" включен. Никаких оповещений показано не будет."</string>
+ <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"Включен режим \"Не беспокоить\". Все оповещения отключены."</string>
<string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"Режим \"Не беспокоить\" выключен."</string>
<string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"Режим \"Не беспокоить\" выключен."</string>
<string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"Режим \"Не беспокоить\" включен."</string>
@@ -235,7 +235,7 @@
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим полета"</string>
<string name="quick_settings_dnd_label" msgid="8735855737575028208">"Не беспокоить"</string>
<string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"Только важные"</string>
- <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Никаких оповещений"</string>
+ <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"Без оповещений"</string>
<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>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index dc1815e..003b784 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -179,8 +179,8 @@
<string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"බාධා නොකරන්න ක්රියාත්මකයි, ප්රමුඛතා පමණි."</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"බාධා නොකරන්න ක්රියාත්මකයි, බාධා කිරීම් නැත."</string>
<string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"බාධා නොකරන්න ක්රියා විරහිතයි."</string>
- <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"බාධා නොකරන්න ක්රියා විරහිත කරන ලදී."</string>
- <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"බාධා නොකරන්න ක්රියාත්මක කරන ලදී"</string>
+ <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"බාධා නොකරන්න ක්රියා විරහිත කරන ලදි."</string>
+ <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"බාධා නොකරන්න ක්රියාත්මක කරන ලදි"</string>
<string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"බ්ලූටූත් අක්රියයි."</string>
<string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"බ්ලූටූත් සක්රියයි."</string>
<string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"බ්ලූටූත් සම්බන්ධවෙමින්."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index c4cad95..d12e309 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -178,16 +178,11 @@
<string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"飞行模式开启。"</string>
<string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"飞行模式已关闭。"</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"飞行模式已开启。"</string>
- <!-- no translation found for accessibility_quick_settings_dnd_priority_on (1448402297221249355) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_dnd_none_on (5910777408232088752) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_dnd_off (2371832603753738581) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_dnd_changed_off (898107593453022935) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_dnd_changed_on (4483780856613561039) -->
- <skip />
+ <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"勿扰模式已开启,仅限优先打扰。"</string>
+ <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"勿扰模式已开启,禁止打扰。"</string>
+ <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"勿扰模式关闭。"</string>
+ <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"已关闭勿扰模式。"</string>
+ <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"已开启勿扰模式。"</string>
<string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"蓝牙关闭。"</string>
<string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"蓝牙开启。"</string>
<string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"蓝牙连接中。"</string>
@@ -236,12 +231,9 @@
<string name="start_dreams" msgid="7219575858348719790">"互动屏保"</string>
<string name="ethernet_label" msgid="7967563676324087464">"有线网络"</string>
<string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飞行模式"</string>
- <!-- no translation found for quick_settings_dnd_label (8735855737575028208) -->
- <skip />
- <!-- no translation found for quick_settings_dnd_priority_label (483232950670692036) -->
- <skip />
- <!-- no translation found for quick_settings_dnd_none_label (7309935569360609114) -->
- <skip />
+ <string name="quick_settings_dnd_label" msgid="8735855737575028208">"勿扰"</string>
+ <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"仅限优先打扰"</string>
+ <string name="quick_settings_dnd_none_label" msgid="7309935569360609114">"禁止打扰"</string>
<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>
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 1cf0129..275a6be 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -172,7 +172,7 @@
private static final String KEYGUARD_ANALYTICS_SETTING = "keyguard_analytics";
/** The stream type that the lock sounds are tied to. */
- private int mMasterStreamType;
+ private int mUiSoundsStreamType;
private AlarmManager mAlarmManager;
private AudioManager mAudioManager;
@@ -439,6 +439,8 @@
public void onFingerprintRecognized(int userId) {
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mViewMediatorCallback.keyguardDone(true);
+ } else {
+ mStatusBarKeyguardViewManager.animateCollapsePanels();
}
};
@@ -1242,10 +1244,10 @@
if (mAudioManager == null) {
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
if (mAudioManager == null) return;
- mMasterStreamType = mAudioManager.getMasterStreamType();
+ mUiSoundsStreamType = mAudioManager.getUiSoundsStreamType();
}
// If the stream is muted, don't play the sound
- if (mAudioManager.isStreamMute(mMasterStreamType)) return;
+ if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
mLockSoundStreamId = mLockSounds.play(soundId,
mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index ca54349..37d9a73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -59,6 +59,7 @@
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.Display;
@@ -419,61 +420,67 @@
public void onNotificationPosted(final StatusBarNotification sbn,
final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- Notification n = sbn.getNotification();
- boolean isUpdate = mNotificationData.get(sbn.getKey()) != null
- || isHeadsUp(sbn.getKey());
+ if (sbn != null) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Notification n = sbn.getNotification();
+ boolean isUpdate = mNotificationData.get(sbn.getKey()) != null
+ || isHeadsUp(sbn.getKey());
- // Ignore children of notifications that have a summary, since we're not
- // going to show them anyway. This is true also when the summary is canceled,
- // because children are automatically canceled by NoMan in that case.
- if (n.isGroupChild() &&
- mNotificationData.isGroupWithSummary(sbn.getGroupKey())) {
- if (DEBUG) {
- Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
+ // Ignore children of notifications that have a summary, since we're not
+ // going to show them anyway. This is true also when the summary is canceled,
+ // because children are automatically canceled by NoMan in that case.
+ if (n.isGroupChild() &&
+ mNotificationData.isGroupWithSummary(sbn.getGroupKey())) {
+ if (DEBUG) {
+ Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
+ }
+
+ // Remove existing notification to avoid stale data.
+ if (isUpdate) {
+ removeNotification(sbn.getKey(), rankingMap);
+ } else {
+ mNotificationData.updateRanking(rankingMap);
+ }
+ return;
}
-
- // Remove existing notification to avoid stale data.
if (isUpdate) {
- removeNotification(sbn.getKey(), rankingMap);
+ updateNotification(sbn, rankingMap);
} else {
- mNotificationData.updateRanking(rankingMap);
+ addNotification(sbn, rankingMap);
}
- return;
}
- if (isUpdate) {
- updateNotification(sbn, rankingMap);
- } else {
- addNotification(sbn, rankingMap);
- }
- }
- });
+ });
+ }
}
@Override
- public void onNotificationRemoved(final StatusBarNotification sbn,
+ public void onNotificationRemoved(StatusBarNotification sbn,
final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- removeNotification(sbn.getKey(), rankingMap);
- }
- });
+ if (sbn != null) {
+ final String key = sbn.getKey();
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ removeNotification(key, rankingMap);
+ }
+ });
+ }
}
@Override
public void onNotificationRankingUpdate(final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onRankingUpdate");
+ if (rankingMap != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
updateNotificationRanking(rankingMap);
}
});
- }
+ } }
};
@@ -2144,6 +2151,14 @@
}
public boolean isKeyguardSecure() {
+ if (mStatusBarKeyguardViewManager == null) {
+ // startKeyguard() hasn't been called yet, so we don't know.
+ // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this
+ // value onVisibilityChanged().
+ Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false",
+ new Throwable());
+ return false;
+ }
return mStatusBarKeyguardViewManager.isSecure();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index acf7af9..0c21b20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -220,6 +220,7 @@
public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
mPhoneStatusBar = phoneStatusBar;
+ updateCameraVisibility(); // in case onFinishInflate() was called too early
}
private Intent getCameraIntent() {
@@ -231,6 +232,10 @@
}
private void updateCameraVisibility() {
+ if (mCameraImageView == null) {
+ // Things are not set up yet; reply hazy, ask again later
+ return;
+ }
ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
PackageManager.MATCH_DEFAULT_ONLY,
mLockPatternUtils.getCurrentUser());
@@ -253,7 +258,7 @@
private boolean isCameraDisabledByDpm() {
final DevicePolicyManager dpm =
(DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
- if (dpm != null) {
+ if (dpm != null && mPhoneStatusBar != null) {
try {
final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 2f3a159..6369d5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -31,6 +31,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.statusbar.CommandQueue;
import static com.android.keyguard.KeyguardHostView.OnDismissAction;
@@ -439,4 +440,8 @@
public void keyguardGoingAway() {
mPhoneStatusBar.keyguardGoingAway();
}
+
+ public void animateCollapsePanels() {
+ mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 31264ee..51adaac 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -125,8 +125,6 @@
private static final int MSG_NOTIFICATION_EFFECTS_SUPPRESSOR_CHANGED = 15;
private static final int MSG_INTERNAL_RINGER_MODE_CHANGED = 16;
- // Pseudo stream type for master volume
- private static final int STREAM_MASTER = -100;
// Pseudo stream type for remote volume
private static final int STREAM_REMOTE_MUSIC = -200;
@@ -154,10 +152,6 @@
private int mLastRingerProgress = 0;
private int mDemoIcon;
- // True if we want to play tones on the system stream when the master stream is specified.
- private final boolean mPlayMasterStreamTones;
-
-
/** Volume panel content view */
private final View mView;
/** Dialog hosting the panel */
@@ -213,12 +207,6 @@
com.android.systemui.R.drawable.ic_ringer_audible,
com.android.systemui.R.drawable.ic_ringer_mute,
true),
- // for now, use media resources for master volume
- MasterStream(STREAM_MASTER,
- R.string.volume_icon_description_media, //FIXME should have its own description
- IC_AUDIO_VOL,
- IC_AUDIO_VOL_MUTE,
- false),
RemoteStream(STREAM_REMOTE_MUSIC,
R.string.volume_icon_description_media, //FIXME should have its own description
com.android.systemui.R.drawable.ic_audio_remote,
@@ -249,7 +237,6 @@
StreamResources.MediaStream,
StreamResources.NotificationStream,
StreamResources.AlarmStream,
- StreamResources.MasterStream,
StreamResources.RemoteStream
};
@@ -371,15 +358,6 @@
mSecondaryIconTransition = new SecondaryIconTransition();
mIconPulser = new IconPulser(context);
- // For now, only show master volume if master volume is supported
- final Resources res = context.getResources();
- final boolean useMasterVolume = res.getBoolean(R.bool.config_useMasterVolume);
- if (useMasterVolume) {
- for (int i = 0; i < STREAMS.length; i++) {
- StreamResources streamRes = STREAMS[i];
- streamRes.show = (streamRes.streamType == STREAM_MASTER);
- }
- }
if (LOGD) Log.d(mTag, "new VolumePanel");
mDisabledAlpha = 0.5f;
@@ -419,6 +397,7 @@
mDialog.create();
+ final Resources res = context.getResources();
window.setAttributes(getDialogLayoutParams(window, res));
updateWidth();
@@ -447,16 +426,12 @@
mHasVibrator = mVibrator != null && mVibrator.hasVibrator();
mVoiceCapable = context.getResources().getBoolean(R.bool.config_voice_capable);
- if (mZenController != null && !useMasterVolume) {
+ if (mZenController != null) {
mZenModeAvailable = mZenController.isZenAvailable();
mNotificationEffectsSuppressor = mZenController.getEffectsSuppressor();
mZenController.addCallback(mZenCallback);
}
- final boolean masterVolumeOnly = res.getBoolean(R.bool.config_useMasterVolume);
- final boolean masterVolumeKeySounds = res.getBoolean(R.bool.config_useVolumeKeySounds);
- mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds;
-
registerReceiver();
}
@@ -489,7 +464,6 @@
pw.print(" mDisabledAlpha="); pw.println(mDisabledAlpha);
pw.print(" mLastRingerMode="); pw.println(mLastRingerMode);
pw.print(" mLastRingerProgress="); pw.println(mLastRingerProgress);
- pw.print(" mPlayMasterStreamTones="); pw.println(mPlayMasterStreamTones);
pw.print(" isShowing()="); pw.println(isShowing());
pw.print(" mCallback="); pw.println(mCallback);
pw.print(" sConfirmSafeVolumeDialog=");
@@ -576,9 +550,7 @@
}
private boolean isMuted(int streamType) {
- if (streamType == STREAM_MASTER) {
- return mAudioManager.isMasterMute();
- } else if (streamType == STREAM_REMOTE_MUSIC) {
+ if (streamType == STREAM_REMOTE_MUSIC) {
// TODO do we need to support a distinct mute property for remote?
return false;
} else {
@@ -587,9 +559,7 @@
}
private int getStreamMaxVolume(int streamType) {
- if (streamType == STREAM_MASTER) {
- return mAudioManager.getMasterMaxVolume();
- } else if (streamType == STREAM_REMOTE_MUSIC) {
+ if (streamType == STREAM_REMOTE_MUSIC) {
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(streamType);
if (sc != null && sc.controller != null) {
@@ -604,9 +574,7 @@
}
private int getStreamVolume(int streamType) {
- if (streamType == STREAM_MASTER) {
- return mAudioManager.getLastAudibleMasterVolume();
- } else if (streamType == STREAM_REMOTE_MUSIC) {
+ if (streamType == STREAM_REMOTE_MUSIC) {
if (mStreamControls != null) {
StreamControl sc = mStreamControls.get(streamType);
if (sc != null && sc.controller != null) {
@@ -628,11 +596,7 @@
Log.w(mTag, "Adjusting remote volume without a controller!");
}
} else if (getStreamVolume(sc.streamType) != index) {
- if (sc.streamType == STREAM_MASTER) {
- mAudioManager.setMasterVolume(index, flags);
- } else {
- mAudioManager.setStreamVolume(sc.streamType, index, flags);
- }
+ mAudioManager.setStreamVolume(sc.streamType, index, flags);
}
}
@@ -833,7 +797,7 @@
sc.icon.setAlpha(mDisabledAlpha);
sc.icon.setClickable(false);
} else if (fixedVolume ||
- (sc.streamType != mAudioManager.getMasterStreamType() && !isRinger && muted) ||
+ (sc.streamType != mAudioManager.getUiSoundsStreamType() && !isRinger && muted) ||
(sSafetyWarning != null)) {
sc.seekbarView.setEnabled(false);
} else {
@@ -977,10 +941,6 @@
obtainMessage(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN).sendToTarget();
}
- public void postMasterVolumeChanged(int flags) {
- postVolumeChanged(STREAM_MASTER, flags);
- }
-
public void postMuteChanged(int streamType, int flags) {
if (hasMessages(MSG_VOLUME_CHANGED)) return;
synchronized (this) {
@@ -992,10 +952,6 @@
obtainMessage(MSG_MUTE_CHANGED, streamType, flags).sendToTarget();
}
- public void postMasterMuteChanged(int flags) {
- postMuteChanged(STREAM_MASTER, flags);
- }
-
public void postDisplaySafeVolumeWarning(int flags) {
if (hasMessages(MSG_DISPLAY_SAFE_VOLUME_WARNING)) return;
obtainMessage(MSG_DISPLAY_SAFE_VOLUME_WARNING, flags, 0).sendToTarget();
@@ -1192,9 +1148,7 @@
if (!isShowing()) {
int stream = (streamType == STREAM_REMOTE_MUSIC) ? -1 : streamType;
// when the stream is for remote playback, use -1 to reset the stream type evaluation
- if (stream != STREAM_MASTER) {
- mAudioManager.forceVolumeControlStream(stream);
- }
+ mAudioManager.forceVolumeControlStream(stream);
mDialog.show();
if (mCallback != null) {
mCallback.onVisible(true);
@@ -1360,16 +1314,6 @@
* Lock on this VolumePanel instance as long as you use the returned ToneGenerator.
*/
private ToneGenerator getOrCreateToneGenerator(int streamType) {
- if (streamType == STREAM_MASTER) {
- // For devices that use the master volume setting only but still want to
- // play a volume-changed tone, direct the master volume pseudostream to
- // the system stream's tone generator.
- if (mPlayMasterStreamTones) {
- streamType = AudioManager.STREAM_SYSTEM;
- } else {
- return null;
- }
- }
synchronized (this) {
if (mToneGenerators[streamType] == null) {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index f7f3bd8..7603c7d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -201,13 +201,8 @@
}
@Override
- public void masterVolumeChanged(int flags) throws RemoteException {
- mPanel.postMasterVolumeChanged(flags);
- }
-
- @Override
public void masterMuteChanged(int flags) throws RemoteException {
- mPanel.postMasterMuteChanged(flags);
+ // no-op
}
@Override
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
index edb1630..ac40222 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServer.java
@@ -20,6 +20,7 @@
import com.android.net.IProxyPortListener;
import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
import java.io.IOException;
import java.io.InputStream;
@@ -33,6 +34,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -46,6 +48,10 @@
private static final String TAG = "ProxyServer";
+ // HTTP Headers
+ private static final String HEADER_CONNECTION = "connection";
+ private static final String HEADER_PROXY_CONNECTION = "proxy-connection";
+
private ExecutorService threadExecutor;
public boolean mIsRunning = false;
@@ -65,10 +71,6 @@
public void run() {
try {
String requestLine = getLine(connection.getInputStream());
- if (requestLine == null) {
- connection.close();
- return;
- }
String[] splitLine = requestLine.split(" ");
if (splitLine.length < 3) {
connection.close();
@@ -76,22 +78,30 @@
}
String requestType = splitLine[0];
String urlString = splitLine[1];
+ String httpVersion = splitLine[2];
- String host = "";
- int port = 80;
+ URI url = null;
+ String host;
+ int port;
if (requestType.equals(CONNECT)) {
String[] hostPortSplit = urlString.split(":");
host = hostPortSplit[0];
- try {
- port = Integer.parseInt(hostPortSplit[1]);
- } catch (NumberFormatException nfe) {
+ // Use default SSL port if not specified. Parse it otherwise
+ if (hostPortSplit.length < 2) {
port = 443;
+ } else {
+ try {
+ port = Integer.parseInt(hostPortSplit[1]);
+ } catch (NumberFormatException nfe) {
+ connection.close();
+ return;
+ }
}
urlString = "Https://" + host + ":" + port;
} else {
try {
- URI url = new URI(urlString);
+ url = new URI(urlString);
host = url.getHost();
port = url.getPort();
if (port < 0) {
@@ -122,44 +132,99 @@
} else {
server = new Socket(host, port);
if (requestType.equals(CONNECT)) {
- while (getLine(connection.getInputStream()).length() != 0);
+ skipToRequestBody(connection);
// No proxy to respond so we must.
sendLine(connection, HTTP_OK);
} else {
- sendLine(server, requestLine);
+ // Proxying the request directly to the origin server.
+ sendAugmentedRequestToHost(connection, server,
+ requestType, url, httpVersion);
}
}
} catch (IOException ioe) {
-
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to connect to proxy " + proxy, ioe);
+ }
}
if (server != null) {
break;
}
}
- if (server == null) {
+ if (list.isEmpty()) {
server = new Socket(host, port);
if (requestType.equals(CONNECT)) {
- while (getLine(connection.getInputStream()).length() != 0);
+ skipToRequestBody(connection);
// No proxy to respond so we must.
sendLine(connection, HTTP_OK);
} else {
- sendLine(server, requestLine);
+ // Proxying the request directly to the origin server.
+ sendAugmentedRequestToHost(connection, server,
+ requestType, url, httpVersion);
}
}
// Pass data back and forth until complete.
- SocketConnect.connect(connection, server);
- } catch (IOException e) {
+ if (server != null) {
+ SocketConnect.connect(connection, server);
+ }
+ } catch (Exception e) {
Log.d(TAG, "Problem Proxying", e);
}
try {
connection.close();
} catch (IOException ioe) {
-
+ // Do nothing
}
}
+ /**
+ * Sends HTTP request-line (i.e. the first line in the request)
+ * that contains absolute path of a given absolute URI.
+ *
+ * @param server server to send the request to.
+ * @param requestType type of the request, a.k.a. HTTP method.
+ * @param absoluteUri absolute URI which absolute path should be extracted.
+ * @param httpVersion version of HTTP, e.g. HTTP/1.1.
+ * @throws IOException if the request-line cannot be sent.
+ */
+ private void sendRequestLineWithPath(Socket server, String requestType,
+ URI absoluteUri, String httpVersion) throws IOException {
+
+ String absolutePath = getAbsolutePathFromAbsoluteURI(absoluteUri);
+ String outgoingRequestLine = String.format("%s %s %s",
+ requestType, absolutePath, httpVersion);
+ sendLine(server, outgoingRequestLine);
+ }
+
+ /**
+ * Extracts absolute path form a given URI. E.g., passing
+ * <code>http://google.com:80/execute?query=cat#top</code>
+ * will result in <code>/execute?query=cat#top</code>.
+ *
+ * @param uri URI which absolute path has to be extracted,
+ * @return the absolute path of the URI,
+ */
+ private String getAbsolutePathFromAbsoluteURI(URI uri) {
+ String rawPath = uri.getRawPath();
+ String rawQuery = uri.getRawQuery();
+ String rawFragment = uri.getRawFragment();
+ StringBuilder absolutePath = new StringBuilder();
+
+ if (rawPath != null) {
+ absolutePath.append(rawPath);
+ } else {
+ absolutePath.append("/");
+ }
+ if (rawQuery != null) {
+ absolutePath.append("?").append(rawQuery);
+ }
+ if (rawFragment != null) {
+ absolutePath.append("#").append(rawFragment);
+ }
+ return absolutePath.toString();
+ }
+
private String getLine(InputStream inputStream) throws IOException {
- StringBuffer buffer = new StringBuffer();
+ StringBuilder buffer = new StringBuilder();
int byteBuffer = inputStream.read();
if (byteBuffer < 0) return "";
do {
@@ -179,6 +244,79 @@
os.write('\n');
os.flush();
}
+
+ /**
+ * Reads from socket until an empty line is read which indicates the end of HTTP headers.
+ *
+ * @param socket socket to read from.
+ * @throws IOException if an exception took place during the socket read.
+ */
+ private void skipToRequestBody(Socket socket) throws IOException {
+ while (getLine(socket.getInputStream()).length() != 0);
+ }
+
+ /**
+ * Sends an augmented request to the final host (DIRECT connection).
+ *
+ * @param src socket to read HTTP headers from.The socket current position should point
+ * to the beginning of the HTTP header section.
+ * @param dst socket to write the augmented request to.
+ * @param httpMethod original request http method.
+ * @param uri original request absolute URI.
+ * @param httpVersion original request http version.
+ * @throws IOException if an exception took place during socket reads or writes.
+ */
+ private void sendAugmentedRequestToHost(Socket src, Socket dst,
+ String httpMethod, URI uri, String httpVersion) throws IOException {
+
+ sendRequestLineWithPath(dst, httpMethod, uri, httpVersion);
+ filterAndForwardRequestHeaders(src, dst);
+
+ // Currently the proxy does not support keep-alive connections; therefore,
+ // the proxy has to request the destination server to close the connection
+ // after the destination server sent the response.
+ sendLine(dst, "Connection: close");
+
+ // Sends and empty line that indicates termination of the header section.
+ sendLine(dst, "");
+ }
+
+ /**
+ * Forwards original request headers filtering out the ones that have to be removed.
+ *
+ * @param src source socket that contains original request headers.
+ * @param dst destination socket to send the filtered headers to.
+ * @throws IOException if the data cannot be read from or written to the sockets.
+ */
+ private void filterAndForwardRequestHeaders(Socket src, Socket dst) throws IOException {
+ String line;
+ do {
+ line = getLine(src.getInputStream());
+ if (line.length() > 0 && !shouldRemoveHeaderLine(line)) {
+ sendLine(dst, line);
+ }
+ } while (line.length() > 0);
+ }
+
+ /**
+ * Returns true if a given header line has to be removed from the original request.
+ *
+ * @param line header line that should be analysed.
+ * @return true if the header line should be removed and not forwarded to the destination.
+ */
+ private boolean shouldRemoveHeaderLine(String line) {
+ int colIndex = line.indexOf(":");
+ if (colIndex != -1) {
+ String headerName = line.substring(0, colIndex).trim();
+ if (headerName.regionMatches(true, 0, HEADER_CONNECTION, 0,
+ HEADER_CONNECTION.length())
+ || headerName.regionMatches(true, 0, HEADER_PROXY_CONNECTION,
+ 0, HEADER_PROXY_CONNECTION.length())) {
+ return true;
+ }
+ }
+ return false;
+ }
}
public ProxyServer() {
@@ -192,23 +330,21 @@
try {
serverSocket = new ServerSocket(0);
- if (serverSocket != null) {
- setPort(serverSocket.getLocalPort());
+ setPort(serverSocket.getLocalPort());
- while (mIsRunning) {
- try {
- Socket socket = serverSocket.accept();
- // Only receive local connections.
- if (socket.getInetAddress().isLoopbackAddress()) {
- ProxyConnection parser = new ProxyConnection(socket);
+ while (mIsRunning) {
+ try {
+ Socket socket = serverSocket.accept();
+ // Only receive local connections.
+ if (socket.getInetAddress().isLoopbackAddress()) {
+ ProxyConnection parser = new ProxyConnection(socket);
- threadExecutor.execute(parser);
- } else {
- socket.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
+ threadExecutor.execute(parser);
+ } else {
+ socket.close();
}
+ } catch (IOException e) {
+ e.printStackTrace();
}
}
} catch (SocketException e) {
diff --git a/preloaded-classes b/preloaded-classes
index dee84f0..c8d8c5d 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -1172,6 +1172,7 @@
android.telecom.InCallService
android.telephony.PhoneNumberUtils
android.telephony.Rlog
+android.telephony.SignalStrength
android.telephony.SubscriptionManager
android.telephony.TelephonyManager
android.text.AndroidBidi
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index f1f0bfc..94f0859 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -14,7 +14,8 @@
libskia \
libutils \
libui \
- libgui
+ libgui \
+ libjnigraphics
LOCAL_STATIC_LIBRARIES :=
@@ -23,6 +24,7 @@
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
frameworks/rs \
+ frameworks/base/core/jni \
$(rs_generated_include_dir)
LOCAL_CFLAGS += -Wno-unused-parameter -std=c++11
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index a145166..d8e1464 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -24,8 +24,6 @@
#include <utils/misc.h>
#include <inttypes.h>
-#include <SkBitmap.h>
-
#include <androidfw/Asset.h>
#include <androidfw/AssetManager.h>
#include <androidfw/ResourceTypes.h>
@@ -35,6 +33,7 @@
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/android_view_Surface.h"
#include "android_runtime/android_util_AssetManager.h"
+#include "android/graphics/GraphicsJNI.h"
#include <rs.h>
#include <rsEnv.h>
@@ -172,14 +171,10 @@
// ---------------------------------------------------------------------------
static jfieldID gContextId = 0;
-static jfieldID gNativeBitmapID = 0;
static void _nInit(JNIEnv *_env, jclass _this)
{
gContextId = _env->GetFieldID(_this, "mContext", "J");
-
- jclass bitmapClass = _env->FindClass("android/graphics/Bitmap");
- gNativeBitmapID = _env->GetFieldID(bitmapClass, "mNativeBitmap", "J");
}
// ---------------------------------------------------------------------------
@@ -934,7 +929,7 @@
jobject jbitmap, jint usage)
{
SkBitmap const * nativeBitmap =
- (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+ GraphicsJNI::getSkBitmap(_env, jbitmap);
const SkBitmap& bitmap(*nativeBitmap);
bitmap.lockPixels();
@@ -951,7 +946,7 @@
jint mip, jobject jbitmap, jint usage)
{
SkBitmap const * nativeBitmap =
- (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+ GraphicsJNI::getSkBitmap(_env, jbitmap);
const SkBitmap& bitmap(*nativeBitmap);
bitmap.lockPixels();
@@ -968,7 +963,7 @@
jobject jbitmap, jint usage)
{
SkBitmap const * nativeBitmap =
- (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+ GraphicsJNI::getSkBitmap(_env, jbitmap);
const SkBitmap& bitmap(*nativeBitmap);
bitmap.lockPixels();
@@ -984,7 +979,7 @@
nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
{
SkBitmap const * nativeBitmap =
- (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+ GraphicsJNI::getSkBitmap(_env, jbitmap);
const SkBitmap& bitmap(*nativeBitmap);
int w = bitmap.width();
int h = bitmap.height();
@@ -1001,7 +996,7 @@
nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap)
{
SkBitmap const * nativeBitmap =
- (SkBitmap const *)_env->GetLongField(jbitmap, gNativeBitmapID);
+ GraphicsJNI::getSkBitmap(_env, jbitmap);
const SkBitmap& bitmap(*nativeBitmap);
bitmap.lockPixels();
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index a2c87b9..e6dc1c7 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -291,7 +291,7 @@
}
canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
canvas.restore();
- atlasMap[mapIndex++] = bitmap.mNativeBitmap;
+ atlasMap[mapIndex++] = bitmap.getSkBitmap();
atlasMap[mapIndex++] = entry.x;
atlasMap[mapIndex++] = entry.y;
atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
diff --git a/services/core/java/com/android/server/MidiService.java b/services/core/java/com/android/server/MidiService.java
index 59b82da..7f98b30 100644
--- a/services/core/java/com/android/server/MidiService.java
+++ b/services/core/java/com/android/server/MidiService.java
@@ -17,10 +17,18 @@
package com.android.server;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.XmlResourceParser;
+import android.media.midi.IMidiDeviceListener;
import android.media.midi.IMidiDeviceServer;
-import android.media.midi.IMidiListener;
import android.media.midi.IMidiManager;
import android.media.midi.MidiDeviceInfo;
+import android.media.midi.MidiDeviceService;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -28,12 +36,17 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.content.PackageMonitor;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
public class MidiService extends IMidiManager.Stub {
private static final String TAG = "MidiService";
@@ -53,6 +66,27 @@
// used for assigning IDs to MIDI devices
private int mNextDeviceId = 1;
+ private final PackageManager mPackageManager;
+
+ // PackageMonitor for listening to package changes
+ private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+ @Override
+ public void onPackageAdded(String packageName, int uid) {
+ addPackageDeviceServers(packageName);
+ }
+
+ @Override
+ public void onPackageModified(String packageName) {
+ removePackageDeviceServers(packageName);
+ addPackageDeviceServers(packageName);
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ removePackageDeviceServers(packageName);
+ }
+ };
+
private final class Client implements IBinder.DeathRecipient {
// Binder token for this client
private final IBinder mToken;
@@ -61,7 +95,8 @@
// This client's PID
private final int mPid;
// List of all receivers for this client
- private final ArrayList<IMidiListener> mListeners = new ArrayList<IMidiListener>();
+ private final ArrayList<IMidiDeviceListener> mListeners
+ = new ArrayList<IMidiDeviceListener>();
public Client(IBinder token) {
mToken = token;
@@ -73,11 +108,11 @@
return mUid;
}
- public void addListener(IMidiListener listener) {
+ public void addListener(IMidiDeviceListener listener) {
mListeners.add(listener);
}
- public void removeListener(IMidiListener listener) {
+ public void removeListener(IMidiDeviceListener listener) {
mListeners.remove(listener);
if (mListeners.size() == 0) {
removeClient(mToken);
@@ -90,7 +125,7 @@
MidiDeviceInfo deviceInfo = device.getDeviceInfo();
try {
- for (IMidiListener listener : mListeners) {
+ for (IMidiDeviceListener listener : mListeners) {
listener.onDeviceAdded(deviceInfo);
}
} catch (RemoteException e) {
@@ -104,7 +139,7 @@
MidiDeviceInfo deviceInfo = device.getDeviceInfo();
try {
- for (IMidiListener listener : mListeners) {
+ for (IMidiDeviceListener listener : mListeners) {
listener.onDeviceRemoved(deviceInfo);
}
} catch (RemoteException e) {
@@ -152,16 +187,17 @@
private final class Device implements IBinder.DeathRecipient {
private final IMidiDeviceServer mServer;
private final MidiDeviceInfo mDeviceInfo;
- // UID of device creator
+ // ServiceInfo for the device's MidiDeviceServer implementation (virtual devices only)
+ private final ServiceInfo mServiceInfo;
+ // UID of device implementation
private final int mUid;
- // PID of device creator
- private final int mPid;
- public Device(IMidiDeviceServer server, MidiDeviceInfo deviceInfo) {
+ public Device(IMidiDeviceServer server, MidiDeviceInfo deviceInfo,
+ ServiceInfo serviceInfo, int uid) {
mServer = server;
mDeviceInfo = deviceInfo;
- mUid = Binder.getCallingUid();
- mPid = Binder.getCallingPid();
+ mServiceInfo = serviceInfo;
+ mUid = uid;
}
public MidiDeviceInfo getDeviceInfo() {
@@ -172,13 +208,20 @@
return mServer;
}
+ public ServiceInfo getServiceInfo() {
+ return mServiceInfo;
+ }
+
+ public String getPackageName() {
+ return (mServiceInfo == null ? null : mServiceInfo.packageName);
+ }
+
public boolean isUidAllowed(int uid) {
- // FIXME
- return true;
+ return (!mDeviceInfo.isPrivate() || mUid == uid);
}
public void binderDied() {
- synchronized (mDevicesByServer) {
+ synchronized (mDevicesByInfo) {
removeDeviceLocked(this);
}
}
@@ -189,32 +232,59 @@
sb.append(mDeviceInfo);
sb.append(" UID: ");
sb.append(mUid);
- sb.append(" PID: ");
- sb.append(mPid);
return sb.toString();
}
}
public MidiService(Context context) {
mContext = context;
- }
+ mPackageManager = context.getPackageManager();
+ mPackageMonitor.register(context, null, true);
- public void registerListener(IBinder token, IMidiListener listener) {
+ Intent intent = new Intent(MidiDeviceService.SERVICE_INTERFACE);
+ List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServices(intent,
+ PackageManager.GET_META_DATA);
+ if (resolveInfos != null) {
+ int count = resolveInfos.size();
+ for (int i = 0; i < count; i++) {
+ ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
+ if (serviceInfo != null) {
+ addPackageDeviceServer(serviceInfo);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void registerListener(IBinder token, IMidiDeviceListener listener) {
Client client = getClient(token);
if (client == null) return;
client.addListener(listener);
}
- public void unregisterListener(IBinder token, IMidiListener listener) {
+ @Override
+ public void unregisterListener(IBinder token, IMidiDeviceListener listener) {
Client client = getClient(token);
if (client == null) return;
client.removeListener(listener);
}
public MidiDeviceInfo[] getDeviceList() {
- return mDevicesByInfo.keySet().toArray(new MidiDeviceInfo[0]);
+ ArrayList<MidiDeviceInfo> deviceInfos = new ArrayList<MidiDeviceInfo>();
+ int uid = Binder.getCallingUid();
+
+ synchronized (mDevicesByInfo) {
+ for (Device device : mDevicesByInfo.values()) {
+ if (device.isUidAllowed(uid)) {
+ deviceInfos.add(device.getDeviceInfo());
+ }
+ }
+ }
+
+ return deviceInfos.toArray(new MidiDeviceInfo[0]);
}
+ @Override
public IMidiDeviceServer openDevice(IBinder token, MidiDeviceInfo deviceInfo) {
Device device = mDevicesByInfo.get(deviceInfo);
if (device == null) {
@@ -229,28 +299,64 @@
return device.getDeviceServer();
}
+ @Override
public MidiDeviceInfo registerDeviceServer(IMidiDeviceServer server, int numInputPorts,
- int numOutputPorts, Bundle properties, boolean isPrivate, int type) {
+ int numOutputPorts, Bundle properties, int type) {
if (type != MidiDeviceInfo.TYPE_VIRTUAL && Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("only system can create non-virtual devices");
}
- MidiDeviceInfo deviceInfo;
- Device device;
+ synchronized (mDevicesByInfo) {
+ return addDeviceLocked(type, numInputPorts, numOutputPorts, properties,
+ server, null, false, -1);
+ }
+ }
- synchronized (mDevicesByServer) {
- int id = mNextDeviceId++;
- deviceInfo = new MidiDeviceInfo(type, id, numInputPorts, numOutputPorts, properties);
+ @Override
+ public void unregisterDeviceServer(IMidiDeviceServer server) {
+ synchronized (mDevicesByInfo) {
+ Device device = mDevicesByServer.get(server.asBinder());
+ if (device != null) {
+ removeDeviceLocked(device);
+ }
+ }
+ }
+
+ @Override
+ public MidiDeviceInfo getServiceDeviceInfo(String packageName, String className) {
+ synchronized (mDevicesByInfo) {
+ for (Device device : mDevicesByInfo.values()) {
+ ServiceInfo serviceInfo = device.getServiceInfo();
+ if (serviceInfo != null &&
+ packageName.equals(serviceInfo.packageName) &&
+ className.equals(serviceInfo.name)) {
+ return device.getDeviceInfo();
+ }
+ }
+ return null;
+ }
+ }
+
+ // synchronize on mDevicesByInfo
+ private MidiDeviceInfo addDeviceLocked(int type, int numInputPorts, int numOutputPorts,
+ Bundle properties, IMidiDeviceServer server, ServiceInfo serviceInfo,
+ boolean isPrivate, int uid) {
+
+ int id = mNextDeviceId++;
+ MidiDeviceInfo deviceInfo = new MidiDeviceInfo(type, id, numInputPorts, numOutputPorts,
+ properties, isPrivate);
+ Device device = new Device(server, deviceInfo, serviceInfo, uid);
+
+ if (server != null) {
IBinder binder = server.asBinder();
- device = new Device(server, deviceInfo);
try {
binder.linkToDeath(device, 0);
} catch (RemoteException e) {
return null;
}
- mDevicesByInfo.put(deviceInfo, device);
- mDevicesByServer.put(server.asBinder(), device);
+ mDevicesByServer.put(binder, device);
}
+ mDevicesByInfo.put(deviceInfo, device);
synchronized (mClients) {
for (Client c : mClients.values()) {
@@ -261,16 +367,13 @@
return deviceInfo;
}
- public void unregisterDeviceServer(IMidiDeviceServer server) {
- synchronized (mDevicesByServer) {
- removeDeviceLocked(mDevicesByServer.get(server.asBinder()));
- }
- }
-
- // synchronize on mDevicesByServer
+ // synchronize on mDevicesByInfo
private void removeDeviceLocked(Device device) {
- if (mDevicesByServer.remove(device.getDeviceServer().asBinder()) != null) {
- mDevicesByInfo.remove(device.getDeviceInfo());
+ if (mDevicesByInfo.remove(device.getDeviceInfo()) != null) {
+ IMidiDeviceServer server = device.getDeviceServer();
+ if (server != null) {
+ mDevicesByServer.remove(server);
+ }
synchronized (mClients) {
for (Client c : mClients.values()) {
@@ -280,6 +383,134 @@
}
}
+ private void addPackageDeviceServers(String packageName) {
+ PackageInfo info;
+
+ try {
+ info = mPackageManager.getPackageInfo(packageName,
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "handlePackageUpdate could not find package " + packageName, e);
+ return;
+ }
+
+ ServiceInfo[] services = info.services;
+ if (services == null) return;
+ for (int i = 0; i < services.length; i++) {
+ addPackageDeviceServer(services[i]);
+ }
+ }
+
+ private void addPackageDeviceServer(ServiceInfo serviceInfo) {
+ XmlResourceParser parser = null;
+
+ try {
+ parser = serviceInfo.loadXmlMetaData(mPackageManager,
+ MidiDeviceService.SERVICE_INTERFACE);
+ if (parser == null) return;
+
+ Bundle properties = null;
+ int numInputPorts = 0;
+ int numOutputPorts = 0;
+ boolean isPrivate = false;
+
+ while (true) {
+ int eventType = parser.next();
+ if (eventType == XmlPullParser.END_DOCUMENT) {
+ break;
+ } else if (eventType == XmlPullParser.START_TAG) {
+ String tagName = parser.getName();
+ if ("device".equals(tagName)) {
+ if (properties != null) {
+ Log.w(TAG, "nested <device> elements in metadata for "
+ + serviceInfo.packageName);
+ continue;
+ }
+ properties = new Bundle();
+ properties.putParcelable(MidiDeviceInfo.PROPERTY_SERVICE_INFO, serviceInfo);
+ numInputPorts = 0;
+ numOutputPorts = 0;
+ isPrivate = false;
+
+ int count = parser.getAttributeCount();
+ for (int i = 0; i < count; i++) {
+ String name = parser.getAttributeName(i);
+ String value = parser.getAttributeValue(i);
+ if ("private".equals(name)) {
+ isPrivate = "true".equals(value);
+ } else {
+ properties.putString(name, value);
+ }
+ }
+ } else if ("input-port".equals(tagName)) {
+ if (properties == null) {
+ Log.w(TAG, "<input-port> outside of <device> in metadata for "
+ + serviceInfo.packageName);
+ continue;
+ }
+ numInputPorts++;
+ // TODO - add support for port properties
+ } else if ("output-port".equals(tagName)) {
+ if (properties == null) {
+ Log.w(TAG, "<output-port> outside of <device> in metadata for "
+ + serviceInfo.packageName);
+ continue;
+ }
+ numOutputPorts++;
+ // TODO - add support for port properties
+ }
+ } else if (eventType == XmlPullParser.END_TAG) {
+ String tagName = parser.getName();
+ if ("device".equals(tagName)) {
+ if (properties != null) {
+ if (numInputPorts == 0 && numOutputPorts == 0) {
+ Log.w(TAG, "<device> with no ports in metadata for "
+ + serviceInfo.packageName);
+ continue;
+ }
+
+ int uid = -1;
+ if (isPrivate) {
+ try {
+ ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
+ serviceInfo.packageName, 0);
+ uid = appInfo.uid;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "could not fetch ApplicationInfo for "
+ + serviceInfo.packageName);
+ continue;
+ }
+ }
+
+ synchronized (mDevicesByInfo) {
+ addDeviceLocked(MidiDeviceInfo.TYPE_VIRTUAL,
+ numInputPorts, numOutputPorts, properties,
+ null, serviceInfo, isPrivate, uid);
+ }
+ // setting properties to null signals that we are no longer
+ // processing a <device>
+ properties = null;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Unable to load component info " + serviceInfo.toString(), e);
+ } finally {
+ if (parser != null) parser.close();
+ }
+ }
+
+ private void removePackageDeviceServers(String packageName) {
+ synchronized (mDevicesByInfo) {
+ for (Device device : mDevicesByInfo.values()) {
+ if (packageName.equals(device.getPackageName())) {
+ removeDeviceLocked(device);
+ }
+ }
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 059dde1..fc95b00 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import static com.android.server.am.ActivityManagerDebugConfig.*;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
@@ -33,6 +35,7 @@
import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.ArraySet;
+
import com.android.internal.app.ProcessStats;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.TransferPipe;
@@ -67,14 +70,15 @@
import android.util.TimeUtils;
public final class ActiveServices {
- static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE;
- static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING;
- static final boolean DEBUG_DELAYED_SERVICE = ActivityManagerService.DEBUG_SERVICE;
- static final boolean DEBUG_DELAYED_STARTS = DEBUG_DELAYED_SERVICE;
- static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
- static final boolean LOG_SERVICE_START_STOP = false;
- static final String TAG = ActivityManagerService.TAG;
- static final String TAG_MU = ActivityManagerService.TAG_MU;
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM;
+ private static final String TAG_MU = TAG + POSTFIX_MU;
+ private static final String TAG_SERVICE = TAG + POSTFIX_SERVICE;
+ private static final String TAG_SERVICE_EXECUTING = TAG + POSTFIX_SERVICE_EXECUTING;
+
+ private static final boolean DEBUG_DELAYED_SERVICE = DEBUG_SERVICE;
+ private static final boolean DEBUG_DELAYED_STARTS = DEBUG_DELAYED_SERVICE;
+
+ private static final boolean LOG_SERVICE_START_STOP = false;
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20*1000;
@@ -206,11 +210,12 @@
void ensureNotStartingBackground(ServiceRecord r) {
if (mStartingBackground.remove(r)) {
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "No longer background starting: " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
+ "No longer background starting: " + r);
rescheduleDelayedStarts();
}
if (mDelayedStartList.remove(r)) {
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "No longer delaying start: " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "No longer delaying start: " + r);
}
}
@@ -229,16 +234,17 @@
while (mDelayedStartList.size() > 0
&& mStartingBackground.size() < mMaxStartingBackground) {
ServiceRecord r = mDelayedStartList.remove(0);
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "REM FR DELAY LIST (exec next): " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
+ "REM FR DELAY LIST (exec next): " + r);
if (r.pendingStarts.size() <= 0) {
Slog.w(TAG, "**** NO PENDING STARTS! " + r + " startReq=" + r.startRequested
+ " delayedStop=" + r.delayedStop);
}
if (DEBUG_DELAYED_SERVICE) {
if (mDelayedStartList.size() > 0) {
- Slog.v(TAG, "Remaining delayed list:");
+ Slog.v(TAG_SERVICE, "Remaining delayed list:");
for (int i=0; i<mDelayedStartList.size(); i++) {
- Slog.v(TAG, " #" + i + ": " + mDelayedStartList.get(i));
+ Slog.v(TAG_SERVICE, " #" + i + ": " + mDelayedStartList.get(i));
}
}
}
@@ -248,7 +254,7 @@
if (mStartingBackground.size() > 0) {
ServiceRecord next = mStartingBackground.get(0);
long when = next.startingBgTimeout > now ? next.startingBgTimeout : now;
- if (DEBUG_DELAYED_SERVICE) Slog.v(TAG, "Top bg start is " + next
+ if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Top bg start is " + next
+ ", can delay others up to " + when);
Message msg = obtainMessage(MSG_BG_START_TIMEOUT);
sendMessageAtTime(msg, when);
@@ -298,7 +304,7 @@
ComponentName startServiceLocked(IApplicationThread caller,
Intent service, String resolvedType,
int callingPid, int callingUid, int userId) {
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "startService: " + service
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
final boolean callerFg;
@@ -337,7 +343,7 @@
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null, r.userId);
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
- if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
}
r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
@@ -360,29 +366,30 @@
// service is started. This is especially the case for receivers, which
// may start a service in onReceive() to do some additional work and have
// initialized some global state as part of that.
- if (DEBUG_DELAYED_SERVICE) Slog.v(TAG, "Potential start delay of " + r + " in "
- + proc);
+ if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Potential start delay of "
+ + r + " in " + proc);
if (r.delayed) {
// This service is already scheduled for a delayed start; just leave
// it still waiting.
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Continuing to delay: " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r);
return r.name;
}
if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
// Something else is starting, delay!
- Slog.i(TAG, "Delaying start of: " + r);
+ Slog.i(TAG_SERVICE, "Delaying start of: " + r);
smap.mDelayedStartList.add(r);
r.delayed = true;
return r.name;
}
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Not delaying: " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r);
addToStarting = true;
} else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
// We slightly loosen when we will enqueue this new service as a background
// starting service we are waiting for, to also include processes that are
// currently running other services or receivers.
addToStarting = true;
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Not delaying, but counting as bg: " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
+ "Not delaying, but counting as bg: " + r);
} else if (DEBUG_DELAYED_STARTS) {
StringBuilder sb = new StringBuilder(128);
sb.append("Not potential delay (state=").append(proc.curProcState)
@@ -394,16 +401,17 @@
}
sb.append("): ");
sb.append(r.toString());
- Slog.v(TAG, sb.toString());
+ Slog.v(TAG_SERVICE, sb.toString());
}
} else if (DEBUG_DELAYED_STARTS) {
if (callerFg) {
- Slog.v(TAG, "Not potential delay (callerFg=" + callerFg + " uid="
+ Slog.v(TAG_SERVICE, "Not potential delay (callerFg=" + callerFg + " uid="
+ callingUid + " pid=" + callingPid + "): " + r);
} else if (r.app != null) {
- Slog.v(TAG, "Not potential delay (cur app=" + r.app + "): " + r);
+ Slog.v(TAG_SERVICE, "Not potential delay (cur app=" + r.app + "): " + r);
} else {
- Slog.v(TAG, "Not potential delay (user " + r.userId + " not started): " + r);
+ Slog.v(TAG_SERVICE,
+ "Not potential delay (user " + r.userId + " not started): " + r);
}
}
@@ -432,9 +440,9 @@
if (DEBUG_DELAYED_SERVICE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
- Slog.v(TAG, "Starting background (first=" + first + "): " + r, here);
+ Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
} else if (DEBUG_DELAYED_STARTS) {
- Slog.v(TAG, "Starting background (first=" + first + "): " + r);
+ Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
}
if (first) {
smap.rescheduleDelayedStarts();
@@ -451,7 +459,7 @@
// If service isn't actually running, but is is being held in the
// delayed list, then we need to keep it started but note that it
// should be stopped once no longer delayed.
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Delaying stop of pending: " + service);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Delaying stop of pending: " + service);
service.delayedStop = true;
return;
}
@@ -469,7 +477,7 @@
int stopServiceLocked(IApplicationThread caller, Intent service,
String resolvedType, int userId) {
- if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopService: " + service
+ " type=" + resolvedType);
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
@@ -525,7 +533,7 @@
boolean stopServiceTokenLocked(ComponentName className, IBinder token,
int startId) {
- if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopServiceToken: " + className
+ " " + token + " startId=" + startId);
ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
if (r != null) {
@@ -687,7 +695,7 @@
int bindServiceLocked(IApplicationThread caller, IBinder token,
Intent service, String resolvedType,
IServiceConnection connection, int flags, int userId) {
- if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
@@ -751,7 +759,7 @@
try {
if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
- if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: "
+ s);
}
@@ -819,7 +827,7 @@
mAm.updateOomAdjLocked(s.app);
}
- if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
+ ": received=" + b.intent.received
+ " apps=" + b.intent.apps.size()
+ " doRebind=" + b.intent.doRebind);
@@ -857,7 +865,7 @@
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
- if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r
+ " " + intent + ": " + service);
if (r != null) {
Intent.FilterComparison filter
@@ -873,14 +881,14 @@
ConnectionRecord c = clist.get(i);
if (!filter.equals(c.binding.intent.intent)) {
if (DEBUG_SERVICE) Slog.v(
- TAG, "Not publishing to: " + c);
+ TAG_SERVICE, "Not publishing to: " + c);
if (DEBUG_SERVICE) Slog.v(
- TAG, "Bound intent: " + c.binding.intent.intent);
+ TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
if (DEBUG_SERVICE) Slog.v(
- TAG, "Published intent: " + intent);
+ TAG_SERVICE, "Published intent: " + intent);
continue;
}
- if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
try {
c.conn.connected(r.name, service);
} catch (Exception e) {
@@ -901,7 +909,7 @@
boolean unbindServiceLocked(IServiceConnection connection) {
IBinder binder = connection.asBinder();
- if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindService: conn=" + binder);
ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
if (clist == null) {
Slog.w(TAG, "Unbind failed: could not find connection for "
@@ -945,7 +953,7 @@
Intent.FilterComparison filter
= new Intent.FilterComparison(intent);
IntentBindRecord b = r.bindings.get(filter);
- if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindFinished in " + r
+ " at " + b + ": apps="
+ (b != null ? b.apps.size() : 0));
@@ -1012,7 +1020,7 @@
String resolvedType, int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg) {
ServiceRecord r = null;
- if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service
+ " type=" + resolvedType + " callingUid=" + callingUid);
userId = mAm.handleIncomingUser(callingPid, callingUid, userId,
@@ -1036,7 +1044,7 @@
ServiceInfo sInfo =
rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
- Slog.w(TAG, "Unable to start service " + service + " U=" + userId +
+ Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
": not found");
return null;
}
@@ -1110,9 +1118,9 @@
}
private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
- if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING "
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
+ why + " of " + r + " in app " + r.app);
- else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, ">>> EXECUTING "
+ else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "
+ why + " of " + r.shortName);
long now = SystemClock.uptimeMillis();
if (r.executeNesting == 0) {
@@ -1155,7 +1163,7 @@
i.hasBound = true;
i.doRebind = false;
} catch (RemoteException e) {
- if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
return false;
}
}
@@ -1336,7 +1344,7 @@
return null;
}
- if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent);
// We are now bringing the service up, so no longer in the
// restarting state.
@@ -1347,7 +1355,7 @@
// Make sure this service is no longer considered delayed, we are starting it now.
if (r.delayed) {
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "REM FR DELAY LIST (bring up): " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
@@ -1430,7 +1438,8 @@
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Applying delayed stop (in bring up): " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
+ "Applying delayed stop (in bring up): " + r);
stopServiceLocked(r);
}
}
@@ -1509,7 +1518,7 @@
sendServiceArgsLocked(r, execInFg, true);
if (r.delayed) {
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "REM FR DELAY LIST (new proc): " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
@@ -1518,7 +1527,8 @@
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
- if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Applying delayed stop (from start): " + r);
+ if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
+ "Applying delayed stop (from start): " + r);
stopServiceLocked(r);
}
}
@@ -1534,7 +1544,7 @@
while (r.pendingStarts.size() > 0) {
try {
ServiceRecord.StartItem si = r.pendingStarts.remove(0);
- if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Sending arguments to: "
+ r + " " + r.intent + " args=" + si.intent);
if (si.intent == null && N > 1) {
// If somehow we got a dummy null intent in the middle,
@@ -1566,7 +1576,7 @@
} catch (RemoteException e) {
// Remote process gone... we'll let the normal cleanup take
// care of this.
- if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while scheduling start: " + r);
break;
} catch (Exception e) {
Slog.w(TAG, "Unexpected exception", e);
@@ -1636,7 +1646,7 @@
if (r.app != null && r.app.thread != null) {
for (int i=r.bindings.size()-1; i>=0; i--) {
IntentBindRecord ibr = r.bindings.valueAt(i);
- if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr
+ ": hasBound=" + ibr.hasBound);
if (ibr.hasBound) {
try {
@@ -1654,7 +1664,7 @@
}
}
- if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down " + r + " " + r.intent);
r.destroyTime = SystemClock.uptimeMillis();
if (LOG_SERVICE_START_STOP) {
EventLogTags.writeAmDestroyService(
@@ -1671,7 +1681,7 @@
for (int i=mPendingServices.size()-1; i>=0; i--) {
if (mPendingServices.get(i) == r) {
mPendingServices.remove(i);
- if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r);
}
}
@@ -1704,11 +1714,11 @@
}
} else {
if (DEBUG_SERVICE) Slog.v(
- TAG, "Removed service that has no process: " + r);
+ TAG_SERVICE, "Removed service that has no process: " + r);
}
} else {
if (DEBUG_SERVICE) Slog.v(
- TAG, "Removed service that is not running: " + r);
+ TAG_SERVICE, "Removed service that is not running: " + r);
}
if (r.bindings.size() > 0) {
@@ -1775,7 +1785,7 @@
}
if (!c.serviceDead) {
- if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Disconnecting binding " + b.intent
+ ": shouldUnbind=" + b.intent.hasBound);
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
@@ -1902,19 +1912,20 @@
private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
boolean finishing) {
- if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "<<< DONE EXECUTING " + r
+ ": nesting=" + r.executeNesting
+ ", inDestroying=" + inDestroying + ", app=" + r.app);
- else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);
+ else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
+ "<<< DONE EXECUTING " + r.shortName);
r.executeNesting--;
if (r.executeNesting <= 0) {
if (r.app != null) {
- if (DEBUG_SERVICE) Slog.v(TAG,
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"Nesting at 0 of " + r.shortName);
r.app.execServicesFg = false;
r.app.executingServices.remove(r);
if (r.app.executingServices.size() == 0) {
- if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,
+ if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
"No more executingServices of " + r.shortName);
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
} else if (r.executeFg) {
@@ -1927,7 +1938,7 @@
}
}
if (inDestroying) {
- if (DEBUG_SERVICE) Slog.v(TAG,
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"doneExecuting remove destroying " + r);
mDestroyingServices.remove(r);
r.bindings.clear();
@@ -2141,13 +2152,13 @@
sr.executeNesting = 0;
sr.forceClearTracker();
if (mDestroyingServices.remove(sr)) {
- if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr);
}
final int numClients = sr.bindings.size();
for (int bindingi=numClients-1; bindingi>=0; bindingi--) {
IntentBindRecord b = sr.bindings.valueAt(bindingi);
- if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Killing binding " + b
+ ": shouldUnbind=" + b.hasBound);
b.binder = null;
b.requested = b.received = b.hasBound = false;
@@ -2281,7 +2292,7 @@
if (sr.app == app) {
sr.forceClearTracker();
mDestroyingServices.remove(i);
- if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr);
+ if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
new file mode 100644
index 0000000..03f253b
--- /dev/null
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -0,0 +1,84 @@
+/*
+ * 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.am;
+
+/**
+ * Common class for the various debug {@link android.util.Log} output configuration in the activity
+ * manager package.
+ */
+class ActivityManagerDebugConfig {
+
+ // All output logs in the activity manager package use the {@link #TAG_AM} string for tagging
+ // their log output. This makes it easy to identify the origin of the log message when sifting
+ // through a large amount of log output from multiple sources. However, it also makes trying
+ // to figure-out the origin of a log message while debugging the activity manager a little
+ // painful. By setting this constant to true, log messages from the activity manager package
+ // will be tagged with their class names instead fot the generic tag.
+ static final boolean TAG_WITH_CLASS_NAME = false;
+
+ // While debugging it is sometimes useful to have the category name of the log prepended to the
+ // base log tag to make sifting through logs with the same base tag easier. By setting this
+ // constant to true, the category name of the log point will be prepended to the log tag.
+ static final boolean PREPEND_CATEGORY_NAME = false;
+
+ // Default log tag for the activity manager package.
+ static final String TAG_AM = "ActivityManager";
+
+ // Enable all debug log categories.
+ static final boolean DEBUG_ALL = false;
+
+ // Available log categories in the activity manager package.
+ static final boolean DEBUG_BACKUP = DEBUG_ALL || false;
+ static final boolean DEBUG_BROADCAST = DEBUG_ALL || false;
+ static final boolean DEBUG_BROADCAST_BACKGROUND = DEBUG_BROADCAST || false;
+ static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
+ static final boolean DEBUG_CLEANUP = DEBUG_ALL || false;
+ static final boolean DEBUG_CONFIGURATION = DEBUG_ALL || false;
+ static final boolean DEBUG_FOCUS = false;
+ static final boolean DEBUG_IMMERSIVE = DEBUG_ALL || false;
+ static final boolean DEBUG_LOCKSCREEN = DEBUG_ALL || false;
+ static final boolean DEBUG_LRU = DEBUG_ALL || false;
+ static final boolean DEBUG_MU = DEBUG_ALL || false;
+ static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
+ static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
+ static final boolean DEBUG_POWER = DEBUG_ALL || false;
+ static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
+ static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false;
+ static final boolean DEBUG_PROCESSES = DEBUG_ALL || false;
+ static final boolean DEBUG_PROVIDER = DEBUG_ALL || false;
+ static final boolean DEBUG_PSS = DEBUG_ALL || false;
+ static final boolean DEBUG_RECENTS = DEBUG_ALL || false;
+ static final boolean DEBUG_RESULTS = DEBUG_ALL || false;
+ static final boolean DEBUG_SERVICE = DEBUG_ALL || false;
+ static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false;
+ static final boolean DEBUG_STACK = DEBUG_ALL || false;
+ static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
+ static final boolean DEBUG_TASKS = DEBUG_ALL || false;
+ static final boolean DEBUG_THUMBNAILS = DEBUG_ALL || false;
+ static final boolean DEBUG_TRANSITION = DEBUG_ALL || false;
+ static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
+ static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false;
+ static final boolean DEBUG_VISBILITY = DEBUG_ALL || false;
+
+ static final String POSTFIX_BACKUP = (PREPEND_CATEGORY_NAME) ? "_Backup" : "";
+ static final String POSTFIX_BROADCAST = (PREPEND_CATEGORY_NAME) ? "_Broadcast" : "";
+ static final String POSTFIX_MU = "_MU";
+ static final String POSTFIX_SERVICE = (PREPEND_CATEGORY_NAME) ? "_Service" : "";
+ static final String POSTFIX_SERVICE_EXECUTING =
+ (PREPEND_CATEGORY_NAME) ? "_ServiceExecuting" : "";
+
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 008d718..1247105 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -30,6 +30,7 @@
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
+import static com.android.server.am.ActivityManagerDebugConfig.*;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import android.Manifest;
@@ -245,10 +246,11 @@
// File that stores last updated system version and called preboot receivers
static final String CALLED_PRE_BOOTS_FILENAME = "called_pre_boots.dat";
- static final String TAG = "ActivityManager";
- static final String TAG_MU = "ActivityManagerServiceMU";
- static final boolean DEBUG = false;
- static final boolean localLOGV = DEBUG;
+ static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM;
+ private static final String TAG_MU = TAG + POSTFIX_MU;
+
+ // TODO(ogunwale): Migrate all the constants below to use ActivityManagerDebugConfig class.
+ static final boolean localLOGV = DEBUG_ALL || false;
static final boolean DEBUG_BACKUP = localLOGV || false;
static final boolean DEBUG_BROADCAST = localLOGV || false;
static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
@@ -8347,6 +8349,9 @@
synchronized (this) {
pkg = task.intent.getComponent().getPackageName();
}
+ // isSystemInitiated is used to distinguish between locked and pinned mode, as pinned mode
+ // is initiated by system after the pinning request was shown and locked mode is initiated
+ // by an authorized app directly
boolean isSystemInitiated = Binder.getCallingUid() == Process.SYSTEM_UID;
if (!isSystemInitiated && !isLockTaskAuthorized(pkg)) {
StatusBarManagerInternal statusBarManager = LocalServices.getService(
@@ -8367,7 +8372,9 @@
|| (task != mStackSupervisor.getFocusedStack().topTask()))) {
throw new IllegalArgumentException("Invalid task, not in foreground");
}
- mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated,
+ mStackSupervisor.setLockTaskModeLocked(task, isSystemInitiated ?
+ ActivityManager.LOCK_TASK_MODE_PINNED :
+ ActivityManager.LOCK_TASK_MODE_LOCKED,
"startLockTask");
}
}
@@ -8453,7 +8460,8 @@
Log.d(TAG, "stopLockTaskMode");
// Stop lock task
synchronized (this) {
- mStackSupervisor.setLockTaskModeLocked(null, false, "stopLockTask");
+ mStackSupervisor.setLockTaskModeLocked(null, ActivityManager.LOCK_TASK_MODE_NONE,
+ "stopLockTask");
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -8474,8 +8482,13 @@
@Override
public boolean isInLockTaskMode() {
+ return getLockTaskModeState() != ActivityManager.LOCK_TASK_MODE_NONE;
+ }
+
+ @Override
+ public int getLockTaskModeState() {
synchronized (this) {
- return mStackSupervisor.isInLockTaskMode();
+ return mStackSupervisor.getLockTaskModeState();
}
}
@@ -18534,7 +18547,8 @@
return true;
}
- mStackSupervisor.setLockTaskModeLocked(null, false, "startUser");
+ mStackSupervisor.setLockTaskModeLocked(null, ActivityManager.LOCK_TASK_MODE_NONE,
+ "startUser");
final UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
if (userInfo == null) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c4234eb..8b95ae8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -20,6 +20,7 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static com.android.server.am.ActivityManagerDebugConfig.*;
import static com.android.server.am.ActivityManagerService.localLOGV;
import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS;
@@ -70,6 +71,7 @@
import android.hardware.display.VirtualDisplay;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
@@ -115,7 +117,7 @@
import java.util.List;
public final class ActivityStackSupervisor implements DisplayListener {
- static final boolean DEBUG = ActivityManagerService.DEBUG || false;
+ static final boolean DEBUG = DEBUG_ALL || false;
static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
static final boolean DEBUG_APP = DEBUG || false;
static final boolean DEBUG_CONTAINERS = DEBUG || false;
@@ -266,9 +268,11 @@
/** If non-null then the task specified remains in front and no other tasks may be started
* until the task exits or #stopLockTaskMode() is called. */
TaskRecord mLockTaskModeTask;
- /** Whether lock task has been entered by an authorized app and cannot
- * be exited. */
- private boolean mLockTaskIsLocked;
+ /** Store the current lock task mode. Possible values:
+ * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActicityManager#LOCK_TASK_MODE_LOCKED},
+ * {@link ActicityManager#LOCK_TASK_MODE_PINNED}
+ */
+ private int mLockTaskModeState;
/**
* Notifies the user when entering/exiting lock-task.
*/
@@ -876,6 +880,11 @@
ActivityContainer container = (ActivityContainer)iContainer;
synchronized (mService) {
+ if (container != null && container.mParentActivity != null &&
+ container.mParentActivity.state != ActivityState.RESUMED) {
+ // Cannot start a child activity if the parent is not resumed.
+ return ActivityManager.START_CANCELED;
+ }
final int realCallingPid = Binder.getCallingPid();
final int realCallingUid = Binder.getCallingUid();
int callingPid;
@@ -3540,10 +3549,10 @@
}
void showLockTaskToast() {
- mLockTaskNotify.showToast(mLockTaskIsLocked);
+ mLockTaskNotify.showToast(mLockTaskModeState);
}
- void setLockTaskModeLocked(TaskRecord task, boolean isLocked, String reason) {
+ void setLockTaskModeLocked(TaskRecord task, int lockTaskModeState, String reason) {
if (task == null) {
// Take out of lock task mode if necessary
if (mLockTaskModeTask != null) {
@@ -3567,7 +3576,7 @@
lockTaskMsg.obj = mLockTaskModeTask.intent.getComponent().getPackageName();
lockTaskMsg.arg1 = mLockTaskModeTask.userId;
lockTaskMsg.what = LOCK_TASK_START_MSG;
- lockTaskMsg.arg2 = !isLocked ? 1 : 0;
+ lockTaskMsg.arg2 = lockTaskModeState;
mHandler.sendMessage(lockTaskMsg);
}
@@ -3585,8 +3594,8 @@
}
}
- boolean isInLockTaskMode() {
- return mLockTaskModeTask != null;
+ int getLockTaskModeState() {
+ return mLockTaskModeState;
}
private final class ActivityStackSupervisorHandler extends Handler {
@@ -3678,13 +3687,18 @@
mLockTaskNotify = new LockTaskNotify(mService.mContext);
}
mLockTaskNotify.show(true);
- mLockTaskIsLocked = msg.arg2 == 0;
+ mLockTaskModeState = msg.arg2;
if (getStatusBarService() != null) {
- int flags =
- StatusBarManager.DISABLE_MASK ^ StatusBarManager.DISABLE_BACK;
- if (!mLockTaskIsLocked) {
- flags ^= StatusBarManager.DISABLE_HOME
- | StatusBarManager.DISABLE_RECENT;
+ int flags = 0;
+ if (mLockTaskModeState == ActivityManager.LOCK_TASK_MODE_LOCKED) {
+ flags = StatusBarManager.DISABLE_MASK
+ & (~StatusBarManager.DISABLE_BACK);
+ } else if (mLockTaskModeState ==
+ ActivityManager.LOCK_TASK_MODE_PINNED) {
+ flags = StatusBarManager.DISABLE_MASK
+ & (~StatusBarManager.DISABLE_BACK)
+ & (~StatusBarManager.DISABLE_HOME)
+ & (~StatusBarManager.DISABLE_RECENT);
}
getStatusBarService().disable(flags, mToken,
mService.mContext.getPackageName());
@@ -3718,7 +3732,8 @@
boolean shouldLockKeyguard = Settings.Secure.getInt(
mService.mContext.getContentResolver(),
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED) != 0;
- if (!mLockTaskIsLocked && shouldLockKeyguard) {
+ if (mLockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED &&
+ shouldLockKeyguard) {
mWindowManager.lockNow(null);
mWindowManager.dismissKeyguard();
new LockPatternUtils(mService.mContext)
@@ -3729,6 +3744,8 @@
}
} catch (RemoteException ex) {
throw new RuntimeException(ex);
+ } finally {
+ mLockTaskModeState = ActivityManager.LOCK_TASK_MODE_NONE;
}
} break;
case CONTAINER_CALLBACK_TASK_LIST_EMPTY: {
@@ -3883,18 +3900,21 @@
@Override
public final int startActivity(Intent intent) {
mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
- int userId = mService.handleIncomingUser(Binder.getCallingPid(),
+ final int userId = mService.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), mCurrentUser, false,
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
+
// TODO: Switch to user app stacks here.
- intent.addFlags(FORCE_NEW_TASK_FLAGS);
String mimeType = intent.getType();
- if (mimeType == null && intent.getData() != null
- && "content".equals(intent.getData().getScheme())) {
- mimeType = mService.getProviderMimeType(intent.getData(), userId);
+ final Uri data = intent.getData();
+ if (mimeType == null && data != null && "content".equals(data.getScheme())) {
+ mimeType = mService.getProviderMimeType(data, userId);
}
- return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null, 0,
- 0, null, null, null, null, userId, this, null);
+ checkEmbeddedAllowedInner(userId, intent, mimeType);
+
+ intent.addFlags(FORCE_NEW_TASK_FLAGS);
+ return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null,
+ 0, 0, null, null, null, null, userId, this, null);
}
@Override
@@ -3905,21 +3925,19 @@
throw new IllegalArgumentException("Bad PendingIntent object");
}
- return ((PendingIntentRecord)intentSender).sendInner(0, null, null, null, null, null,
- null, 0, FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
- }
-
- private void checkEmbeddedAllowedInner(Intent intent, String resolvedType) {
- int userId = mService.handleIncomingUser(Binder.getCallingPid(),
+ final int userId = mService.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), mCurrentUser, false,
ActivityManagerService.ALLOW_FULL_ONLY, "ActivityContainer", null);
- if (resolvedType == null) {
- resolvedType = intent.getType();
- if (resolvedType == null && intent.getData() != null
- && "content".equals(intent.getData().getScheme())) {
- resolvedType = mService.getProviderMimeType(intent.getData(), userId);
- }
- }
+
+ final PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
+ checkEmbeddedAllowedInner(userId, pendingIntent.key.requestIntent,
+ pendingIntent.key.requestResolvedType);
+
+ return pendingIntent.sendInner(0, null, null, null, null, null, null, 0,
+ FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
+ }
+
+ private void checkEmbeddedAllowedInner(int userId, Intent intent, String resolvedType) {
ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, userId);
if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
throw new SecurityException(
@@ -3927,23 +3945,6 @@
}
}
- /** Throw a SecurityException if allowEmbedded is not true */
- @Override
- public final void checkEmbeddedAllowed(Intent intent) {
- checkEmbeddedAllowedInner(intent, null);
- }
-
- /** Throw a SecurityException if allowEmbedded is not true */
- @Override
- public final void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
- if (!(intentSender instanceof PendingIntentRecord)) {
- throw new IllegalArgumentException("Bad PendingIntent object");
- }
- PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
- checkEmbeddedAllowedInner(pendingIntent.key.requestIntent,
- pendingIntent.key.requestResolvedType);
- }
-
@Override
public IBinder asBinder() {
return this;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index a4602a1..6eacfa9 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -751,14 +751,17 @@
private void dumpHelp(PrintWriter pw) {
pw.println("Battery stats (batterystats) dump options:");
pw.println(" [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]");
- pw.println(" [--reset] [--write] [-h] [<package.name>]");
+ pw.println(" [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]");
pw.println(" --checkin: format output for a checkin report.");
pw.println(" --history: show only history data.");
pw.println(" --history-start <num>: show only history data starting at given time offset.");
pw.println(" --unplugged: only output data since last unplugged.");
pw.println(" --charged: only output data since last charged.");
+ pw.println(" --daily: only output full daily data.");
pw.println(" --reset: reset the stats, clearing all current data.");
pw.println(" --write: force write current collected stats to disk.");
+ pw.println(" --new-daily: immediately create and write new daily stats record.");
+ pw.println(" --read-daily: read-load last written daily stats.");
pw.println(" <package.name>: optional name of package to filter output by.");
pw.println(" -h: print this help text.");
pw.println("Battery stats (batterystats) commands:");
@@ -835,6 +838,8 @@
flags |= BatteryStats.DUMP_UNPLUGGED_ONLY;
} else if ("--charged".equals(arg)) {
flags |= BatteryStats.DUMP_CHARGED_ONLY;
+ } else if ("--daily".equals(arg)) {
+ flags |= BatteryStats.DUMP_DAILY_ONLY;
} else if ("--reset".equals(arg)) {
synchronized (mStats) {
mStats.resetAllStatsCmdLocked();
@@ -847,6 +852,18 @@
pw.println("Battery stats written.");
noOutput = true;
}
+ } else if ("--new-daily".equals(arg)) {
+ synchronized (mStats) {
+ mStats.recordDailyStatsLocked();
+ pw.println("New daily stats written.");
+ noOutput = true;
+ }
+ } else if ("--read-daily".equals(arg)) {
+ synchronized (mStats) {
+ mStats.readDailyStatsLocked();
+ pw.println("Last daily stats read.");
+ noOutput = true;
+ }
} else if ("--enable".equals(arg) || "enable".equals(arg)) {
i = doEnableOrDisable(pw, i, args, true);
if (i < 0) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 5083b1d..7a29a88 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -41,6 +41,8 @@
import android.util.EventLog;
import android.util.Slog;
+import static com.android.server.am.ActivityManagerDebugConfig.*;
+
/**
* BROADCASTS
*
@@ -48,11 +50,9 @@
* foreground priority, and one for normal (background-priority) broadcasts.
*/
public final class BroadcastQueue {
- static final String TAG = "BroadcastQueue";
- static final String TAG_MU = ActivityManagerService.TAG_MU;
- static final boolean DEBUG_BROADCAST = ActivityManagerService.DEBUG_BROADCAST;
- static final boolean DEBUG_BROADCAST_LIGHT = ActivityManagerService.DEBUG_BROADCAST_LIGHT;
- static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU;
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "BroadcastQueue" : TAG_AM;
+ private static final String TAG_MU = TAG + POSTFIX_MU;
+ private static final String TAG_BROADCAST = TAG + POSTFIX_BROADCAST;
static final int MAX_BROADCAST_HISTORY = ActivityManager.isLowRamDeviceStatic() ? 10 : 50;
static final int MAX_BROADCAST_SUMMARY_HISTORY
@@ -143,7 +143,7 @@
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
if (DEBUG_BROADCAST) Slog.v(
- TAG, "Received BROADCAST_INTENT_MSG");
+ TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
@@ -196,7 +196,7 @@
public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) {
for (int i=mParallelBroadcasts.size()-1; i>=0; i--) {
if (r.intent.filterEquals(mParallelBroadcasts.get(i).intent)) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"***** DROPPING PARALLEL ["
+ mQueueName + "]: " + r.intent);
mParallelBroadcasts.set(i, r);
@@ -209,7 +209,7 @@
public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) {
for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
if (r.intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"***** DROPPING ORDERED ["
+ mQueueName + "]: " + r.intent);
mOrderedBroadcasts.set(i, r);
@@ -221,7 +221,7 @@
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " for app " + app);
if (app.thread == null) {
throw new RemoteException();
@@ -238,7 +238,7 @@
boolean started = false;
try {
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG,
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"Delivering to component " + r.curComponent
+ ": " + r);
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
@@ -246,12 +246,12 @@
mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
app.repProcState);
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
} finally {
if (!started) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
@@ -308,7 +308,7 @@
r = mPendingBroadcast;
if (r != null && r.curApp == app) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"[" + mQueueName + "] skip & discard pending app " + r);
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
@@ -321,7 +321,7 @@
}
public void scheduleBroadcastsLocked() {
- if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
@@ -391,8 +391,7 @@
// on. If there are background services currently starting, then we will go into a
// special state where we hold off on continuing this broadcast until they are done.
if (mService.mServices.hasBackgroundServices(r.userId)) {
- Slog.i(ActivityManagerService.TAG, "Delay finish: "
- + r.curComponent.flattenToShortString());
+ Slog.i(TAG, "Delay finish: " + r.curComponent.flattenToShortString());
r.state = BroadcastRecord.WAITING_SERVICES;
return false;
}
@@ -412,7 +411,7 @@
if (mOrderedBroadcasts.size() > 0) {
BroadcastRecord br = mOrderedBroadcasts.get(0);
if (br.userId == userId && br.state == BroadcastRecord.WAITING_SERVICES) {
- Slog.i(ActivityManagerService.TAG, "Resuming delayed broadcast");
+ Slog.i(TAG, "Resuming delayed broadcast");
br.curComponent = null;
br.state = BroadcastRecord.IDLE;
processNextBroadcast(false);
@@ -475,7 +474,7 @@
int mode = mService.mAppOpsService.noteOperation(r.appOp,
filter.receiverList.uid, filter.packageName);
if (mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"App op " + r.appOp + " not allowed for broadcast to uid "
+ filter.receiverList.uid + " pkg " + filter.packageName);
skip = true;
@@ -513,7 +512,7 @@
}
}
try {
- if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG, "Delivering to " + filter + " : " + r);
+ if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST, "Delivering to " + filter + " : " + r);
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
@@ -538,7 +537,7 @@
synchronized(mService) {
BroadcastRecord r;
- if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast ["
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast ["
+ mQueueName + "]: "
+ mParallelBroadcasts.size() + " broadcasts, "
+ mOrderedBroadcasts.size() + " ordered broadcasts");
@@ -555,17 +554,17 @@
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
final int N = r.receivers.size();
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast ["
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
+ mQueueName + "] " + r);
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering non-ordered on [" + mQueueName + "] to registered "
+ target + ": " + r);
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
}
addBroadcastToHistoryLocked(r);
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast ["
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
@@ -576,7 +575,7 @@
// check that the process we're waiting for still exists.
if (mPendingBroadcast != null) {
if (DEBUG_BROADCAST_LIGHT) {
- Slog.v(TAG, "processNextBroadcast ["
+ Slog.v(TAG_BROADCAST, "processNextBroadcast ["
+ mQueueName + "]: waiting for "
+ mPendingBroadcast.curApp);
}
@@ -645,7 +644,7 @@
}
if (r.state != BroadcastRecord.IDLE) {
- if (DEBUG_BROADCAST) Slog.d(TAG,
+ if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
"processNextBroadcast("
+ mQueueName + ") called when not idle (state="
+ r.state + ")");
@@ -658,7 +657,7 @@
// result if requested...
if (r.resultTo != null) {
try {
- if (DEBUG_BROADCAST) Slog.i(TAG,
+ if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
"Finishing broadcast [" + mQueueName + "] "
+ r.intent.getAction() + " app=" + r.callerApp);
performReceiveLocked(r.callerApp, r.resultTo,
@@ -675,10 +674,10 @@
}
}
- if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
cancelBroadcastTimeoutLocked();
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast "
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Finished with ordered broadcast "
+ r);
// ... and on to the next...
@@ -699,12 +698,12 @@
if (recIdx == 0) {
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
- if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast ["
+ if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
+ mQueueName + "] " + r);
}
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Submitting BROADCAST_TIMEOUT_MSG ["
+ mQueueName + "] for " + r + " at " + timeoutTime);
setBroadcastTimeoutLocked(timeoutTime);
@@ -715,7 +714,7 @@
// Simple case: this is a registered receiver who gets
// a direct call.
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering ordered ["
+ mQueueName + "] to registered "
+ filter + ": " + r);
@@ -723,7 +722,7 @@
if (r.receiver == null || !r.ordered) {
// The receiver has already finished, so schedule to
// process the next one.
- if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing ["
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing ["
+ mQueueName + "]: ordered="
+ r.ordered + " receiver=" + r.receiver);
r.state = BroadcastRecord.IDLE;
@@ -786,7 +785,7 @@
int mode = mService.mAppOpsService.noteOperation(r.appOp,
info.activityInfo.applicationInfo.uid, info.activityInfo.packageName);
if (mode != AppOpsManager.MODE_ALLOWED) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"App op " + r.appOp + " not allowed for broadcast to uid "
+ info.activityInfo.applicationInfo.uid + " pkg "
+ info.activityInfo.packageName);
@@ -836,7 +835,7 @@
}
if (!isAvailable) {
if (DEBUG_BROADCAST) {
- Slog.v(TAG, "Skipping delivery to " + info.activityInfo.packageName
+ Slog.v(TAG_BROADCAST, "Skipping delivery to " + info.activityInfo.packageName
+ " / " + info.activityInfo.applicationInfo.uid
+ " : package no longer available");
}
@@ -845,7 +844,7 @@
}
if (skip) {
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Skipping delivery of ordered ["
+ mQueueName + "] " + r + " for whatever reason");
r.receiver = null;
@@ -915,7 +914,7 @@
}
// Not running -- get it started, to be executed when the app comes up.
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Need to start app ["
+ mQueueName + "] " + targetProcess + " for broadcast " + r);
if ((r.curApp=mService.startProcessLocked(targetProcess,
@@ -990,7 +989,7 @@
// broadcast timeout message after each receiver finishes. Instead, we set up
// an initial timeout then kick it down the road a little further as needed
// when it expires.
- if (DEBUG_BROADCAST) Slog.v(TAG,
+ if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Premature timeout ["
+ mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for "
+ timeoutTime);
@@ -1005,7 +1004,7 @@
// for started services to finish as well before going on. So if we have actually
// waited long enough time timeout the broadcast, let's give up on the whole thing
// and just move on to the next.
- Slog.i(ActivityManagerService.TAG, "Waited long enough for: " + (br.curComponent != null
+ Slog.i(TAG, "Waited long enough for: " + (br.curComponent != null
? br.curComponent.flattenToShortString() : "(null)"));
br.curComponent = null;
br.state = BroadcastRecord.IDLE;
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index b3777ed..afde322 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import android.app.ActivityManager;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
@@ -44,15 +45,20 @@
mHandler = new H();
}
- public void showToast(boolean isLocked) {
- mHandler.obtainMessage(H.SHOW_TOAST, isLocked ? 1 : 0, 0 /* Not used */).sendToTarget();
+ public void showToast(int lockTaskModeState) {
+ mHandler.obtainMessage(H.SHOW_TOAST, lockTaskModeState, 0 /* Not used */).sendToTarget();
}
- public void handleShowToast(boolean isLocked) {
- String text = mContext.getString(isLocked
- ? R.string.lock_to_app_toast_locked : R.string.lock_to_app_toast);
- if (!isLocked && mAccessibilityManager.isEnabled()) {
- text = mContext.getString(R.string.lock_to_app_toast_accessible);
+ public void handleShowToast(int lockTaskModeState) {
+ String text = null;
+ if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_LOCKED) {
+ text = mContext.getString(R.string.lock_to_app_toast_locked);
+ } else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED) {
+ text = mContext.getString(mAccessibilityManager.isEnabled()
+ ? R.string.lock_to_app_toast_accessible : R.string.lock_to_app_toast);
+ }
+ if (text == null) {
+ return;
}
if (mLastToast != null) {
mLastToast.cancel();
@@ -83,7 +89,7 @@
public void handleMessage(Message msg) {
switch(msg.what) {
case SHOW_TOAST:
- handleShowToast(msg.arg1 != 0);
+ handleShowToast(msg.arg1);
break;
}
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index ffaa03d..7bdfced 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -29,6 +29,8 @@
import android.os.UserHandle;
import android.util.Slog;
+import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
+
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -201,6 +203,13 @@
IBinder resultTo, String resultWho, int requestCode,
int flagsMask, int flagsValues, Bundle options, IActivityContainer container) {
synchronized(owner) {
+ final ActivityContainer activityContainer = (ActivityContainer)container;
+ if (activityContainer != null && activityContainer.mParentActivity != null &&
+ activityContainer.mParentActivity.state
+ != ActivityStack.ActivityState.RESUMED) {
+ // Cannot start a child activity if the parent is not resumed.
+ return ActivityManager.START_CANCELED;
+ }
if (!canceled) {
sent = true;
if ((key.flags&PendingIntent.FLAG_ONE_SHOT) != 0) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 018d77a..5d386bd 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -188,7 +188,6 @@
// AudioHandler messages
private static final int MSG_SET_DEVICE_VOLUME = 0;
private static final int MSG_PERSIST_VOLUME = 1;
- private static final int MSG_PERSIST_MASTER_VOLUME = 2;
private static final int MSG_PERSIST_RINGER_MODE = 3;
private static final int MSG_MEDIA_SERVER_DIED = 4;
private static final int MSG_PLAY_SOUND_EFFECT = 5;
@@ -239,10 +238,6 @@
private final Object mSoundEffectsLock = new Object();
private static final int NUM_SOUNDPOOL_CHANNELS = 4;
- // Internally master volume is a float in the 0.0 - 1.0 range,
- // but to support integer based AudioManager API we translate it to 0 - 100
- private static final int MAX_MASTER_VOLUME = 100;
-
// Maximum volume adjust steps allowed in a single batch call.
private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4;
@@ -386,11 +381,6 @@
// Forced device usage for communications
private int mForcedUseForComm;
- // True if we have master volume support
- private final boolean mUseMasterVolume;
-
- private final int[] mMasterVolumeRamp;
-
// List of binder death handlers for setMode() client processes.
// The last process to have called setMode() is at the top of the list.
private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>();
@@ -595,10 +585,6 @@
mUseFixedVolume = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_useFixedVolume);
- mUseMasterVolume = context.getResources().getBoolean(
- com.android.internal.R.bool.config_useMasterVolume);
- mMasterVolumeRamp = context.getResources().getIntArray(
- com.android.internal.R.array.config_masterVolumeRamp);
// must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[]
// array initialized by updateStreamVolumeAlias()
@@ -647,8 +633,6 @@
context.registerReceiver(mReceiver, intentFilter);
- restoreMasterVolume();
-
LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
}
@@ -882,7 +866,7 @@
UserHandle.USER_CURRENT);
boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE,
- 0, UserHandle.USER_CURRENT) == 1;
+ 0, UserHandle.USER_CURRENT) == 1;
if (mUseFixedVolume) {
masterMute = false;
AudioSystem.setMasterVolume(1.0f);
@@ -1050,7 +1034,7 @@
// If either the client forces allowing ringer modes for this adjustment,
// or the stream type is one that is affected by ringer modes
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
- (streamTypeAlias == getMasterStreamType())) {
+ (streamTypeAlias == getUiSoundsStreamType())) {
int ringerMode = getRingerModeInternal();
// do not vibrate if already in vibrate mode
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
@@ -1183,33 +1167,6 @@
}
}
- /** @see AudioManager#adjustMasterVolume(int, int) */
- public void adjustMasterVolume(int steps, int flags, String callingPackage) {
- adjustMasterVolume(steps, flags, callingPackage, Binder.getCallingUid());
- }
-
- public void adjustMasterVolume(int steps, int flags, String callingPackage, int uid) {
- if (mUseFixedVolume) {
- return;
- }
- if (isMuteAdjust(steps)) {
- setMasterMuteInternal(steps, flags, callingPackage, uid);
- return;
- }
- ensureValidSteps(steps);
- int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
- int delta = 0;
- int numSteps = Math.abs(steps);
- int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER;
- for (int i = 0; i < numSteps; ++i) {
- delta = findVolumeDelta(direction, volume);
- volume += delta;
- }
-
- //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps);
- setMasterVolume(volume, flags, callingPackage, uid);
- }
-
// StreamVolumeCommand contains the information needed to defer the process of
// setStreamVolume() in case the user has to acknowledge the safe volume warning message.
class StreamVolumeCommand {
@@ -1235,9 +1192,9 @@
private void onSetStreamVolume(int streamType, int index, int flags, int device) {
setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false);
- // setting volume on master stream type also controls silent mode
+ // setting volume on ui sounds stream type also controls silent mode
if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
- (mStreamVolumeAlias[streamType] == getMasterStreamType())) {
+ (mStreamVolumeAlias[streamType] == getUiSoundsStreamType())) {
int newRingerMode;
if (index == 0) {
newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE
@@ -1381,41 +1338,6 @@
}
}
- private int findVolumeDelta(int direction, int volume) {
- int delta = 0;
- if (direction == AudioManager.ADJUST_RAISE) {
- if (volume == MAX_MASTER_VOLUME) {
- return 0;
- }
- // This is the default value if we make it to the end
- delta = mMasterVolumeRamp[1];
- // If we're raising the volume move down the ramp array until we
- // find the volume we're above and use that groups delta.
- for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) {
- if (volume >= mMasterVolumeRamp[i - 1]) {
- delta = mMasterVolumeRamp[i];
- break;
- }
- }
- } else if (direction == AudioManager.ADJUST_LOWER){
- if (volume == 0) {
- return 0;
- }
- int length = mMasterVolumeRamp.length;
- // This is the default value if we make it to the end
- delta = -mMasterVolumeRamp[length - 1];
- // If we're lowering the volume move up the ramp array until we
- // find the volume we're below and use the group below it's delta
- for (int i = 2; i < length; i += 2) {
- if (volume <= mMasterVolumeRamp[i]) {
- delta = -mMasterVolumeRamp[i - 1];
- break;
- }
- }
- }
- return delta;
- }
-
private void sendBroadcastToAll(Intent intent) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -1464,16 +1386,6 @@
}
// UI update and Broadcast Intent
- private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) {
- mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags));
-
- Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION);
- intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume);
- intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume);
- sendBroadcastToAll(intent);
- }
-
- // UI update and Broadcast Intent
private void sendMasterMuteUpdate(boolean muted, int flags) {
mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
broadcastMasterMuteStatus(muted);
@@ -1641,27 +1553,21 @@
}
}
- private void setMasterMuteInternal(int adjust, int flags, String callingPackage, int uid) {
+ private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid) {
if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
!= AppOpsManager.MODE_ALLOWED) {
return;
}
- boolean state;
- if (adjust == AudioManager.ADJUST_TOGGLE_MUTE) {
- state = !AudioSystem.getMasterMute();
- } else {
- state = adjust == AudioManager.ADJUST_MUTE;
- }
- if (state != AudioSystem.getMasterMute()) {
- setSystemAudioMute(state);
- AudioSystem.setMasterMute(state);
+ if (mute != AudioSystem.getMasterMute()) {
+ setSystemAudioMute(mute);
+ AudioSystem.setMasterMute(mute);
// Post a persist master volume msg
- sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1
+ sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1
: 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY);
- sendMasterMuteUpdate(state, flags);
+ sendMasterMuteUpdate(mute, flags);
Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
- intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, state);
+ intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute);
sendBroadcastToAll(intent);
}
}
@@ -1671,6 +1577,10 @@
return AudioSystem.getMasterMute();
}
+ public void setMasterMute(boolean mute, int flags, String callingPackage) {
+ setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid());
+ }
+
protected static int getMaxStreamVolume(int streamType) {
return MAX_STREAM_VOLUME[streamType];
}
@@ -1694,63 +1604,12 @@
}
}
- @Override
- public int getMasterVolume() {
- if (isMasterMute()) return 0;
- return getLastAudibleMasterVolume();
- }
-
- @Override
- public void setMasterVolume(int volume, int flags, String callingPackage) {
- setMasterVolume(volume, flags, callingPackage, Binder.getCallingUid());
- }
-
- public void setMasterVolume(int volume, int flags, String callingPackage, int uid) {
- if (mUseFixedVolume) {
- return;
- }
-
- if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage)
- != AppOpsManager.MODE_ALLOWED) {
- return;
- }
-
- if (volume < 0) {
- volume = 0;
- } else if (volume > MAX_MASTER_VOLUME) {
- volume = MAX_MASTER_VOLUME;
- }
- doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags);
- }
-
- private void doSetMasterVolume(float volume, int flags) {
- // don't allow changing master volume when muted
- if (!AudioSystem.getMasterMute()) {
- int oldVolume = getMasterVolume();
- AudioSystem.setMasterVolume(volume);
-
- int newVolume = getMasterVolume();
- if (newVolume != oldVolume) {
- // Post a persist master volume msg
- sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE,
- Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY);
- setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags);
- }
- // Send the volume update regardless whether there was a change.
- sendMasterVolumeUpdate(flags, oldVolume, newVolume);
- }
- }
-
/** @see AudioManager#getStreamMaxVolume(int) */
public int getStreamMaxVolume(int streamType) {
ensureValidStreamType(streamType);
return (mStreamStates[streamType].getMaxIndex() + 5) / 10;
}
- public int getMasterMaxVolume() {
- return MAX_MASTER_VOLUME;
- }
-
/** Get last audible volume before stream was muted. */
public int getLastAudibleStreamVolume(int streamType) {
ensureValidStreamType(streamType);
@@ -1758,13 +1617,8 @@
return (mStreamStates[streamType].getIndex(device) + 5) / 10;
}
- /** Get last audible master volume before it was muted. */
- public int getLastAudibleMasterVolume() {
- return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME);
- }
-
- /** @see AudioManager#getMasterStreamType() */
- public int getMasterStreamType() {
+ /** @see AudioManager#getUiSoundsStreamType() */
+ public int getUiSoundsStreamType() {
return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM];
}
@@ -1932,20 +1786,6 @@
}
}
- private void restoreMasterVolume() {
- if (mUseFixedVolume) {
- AudioSystem.setMasterVolume(1.0f);
- return;
- }
- if (mUseMasterVolume) {
- float volume = Settings.System.getFloatForUser(mContentResolver,
- Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT);
- if (volume >= 0.0f) {
- AudioSystem.setMasterVolume(volume);
- }
- }
- }
-
/** @see AudioManager#shouldVibrate(int) */
public boolean shouldVibrate(int vibrateType) {
if (!mHasVibrator) return false;
@@ -3510,9 +3350,8 @@
public void readSettings() {
synchronized (VolumeStreamState.class) {
- // force maximum volume on all streams if fixed volume property
- // or master volume property is set
- if (mUseFixedVolume || mUseMasterVolume) {
+ // force maximum volume on all streams if fixed volume property is set
+ if (mUseFixedVolume) {
mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
return;
}
@@ -3747,7 +3586,7 @@
private int getValidIndex(int index) {
if (index < 0) {
return 0;
- } else if (mUseFixedVolume || mUseMasterVolume || index > mIndexMax) {
+ } else if (mUseFixedVolume || index > mIndexMax) {
return mIndexMax;
}
@@ -3777,6 +3616,19 @@
final int index = (mIndexMap.valueAt(i) + 5) / 10;
pw.print(index);
}
+ pw.println();
+ pw.print(" Devices: ");
+ final int devices = AudioSystem.getDevicesForStream(mStreamType);
+ int device, i = 0, n = 0;
+ while ((device = 1 << i) <= AudioSystem.DEVICE_OUT_DEFAULT) {
+ if ((devices & device) != 0) {
+ if (n++ > 0) {
+ pw.print(", ");
+ }
+ pw.print(AudioSystem.getOutputDeviceName(device));
+ }
+ i++;
+ }
}
}
@@ -4119,16 +3971,6 @@
persistVolume((VolumeStreamState) msg.obj, msg.arg1);
break;
- case MSG_PERSIST_MASTER_VOLUME:
- if (mUseFixedVolume) {
- return;
- }
- Settings.System.putFloatForUser(mContentResolver,
- Settings.System.VOLUME_MASTER,
- msg.arg1 / (float)1000.0,
- UserHandle.USER_CURRENT);
- break;
-
case MSG_PERSIST_MASTER_VOLUME_MUTE:
if (mUseFixedVolume) {
return;
@@ -4197,9 +4039,6 @@
// Restore ringer mode
setRingerModeInt(getRingerModeInternal(), false);
- // Restore master volume
- restoreMasterVolume();
-
// Reset device orientation (if monitored for this device)
if (mMonitorOrientation) {
setOrientationForAudioSystem();
@@ -5666,16 +5505,6 @@
}
}
- public void postMasterVolumeChanged(int flags) {
- if (mController == null)
- return;
- try {
- mController.masterVolumeChanged(flags);
- } catch (RemoteException e) {
- Log.w(TAG, "Error calling masterVolumeChanged", e);
- }
- }
-
public void postMasterMuteChanged(int flags) {
if (mController == null)
return;
@@ -5741,12 +5570,6 @@
}
@Override
- public void adjustMasterVolumeForUid(int steps, int flags, String callingPackage,
- int uid) {
- adjustMasterVolume(steps, flags, callingPackage, uid);
- }
-
- @Override
public int getRingerModeInternal() {
return AudioService.this.getRingerModeInternal();
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 82c99f78..7c93e56 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -202,7 +202,6 @@
reason != HdmiControlService.INITIATED_BY_BOOT_UP);
mLocalDeviceAddresses = initLocalDeviceAddresses();
launchDeviceDiscovery();
- startQueuedActions();
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 3345e46..5363968 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -90,14 +90,12 @@
private final SessionStub mSession;
private final SessionCb mSessionCb;
private final MediaSessionService mService;
- private final boolean mUseMasterVolume;
private final Object mLock = new Object();
private final ArrayList<ISessionControllerCallback> mControllerCallbacks =
new ArrayList<ISessionControllerCallback>();
private long mFlags;
- private IMediaRouter mMediaRouter;
private PendingIntent mMediaButtonReceiver;
private PendingIntent mLaunchIntent;
@@ -141,8 +139,6 @@
mAudioManager = (AudioManager) service.getContext().getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
- mUseMasterVolume = service.getContext().getResources().getBoolean(
- com.android.internal.R.bool.config_useMasterVolume);
}
/**
@@ -247,13 +243,6 @@
flags &= ~AudioManager.FLAG_PLAY_SOUND;
}
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
- if (mUseMasterVolume) {
- // If this device only uses master volume and playback is local
- // just adjust the master volume and return.
- mAudioManagerInternal.adjustMasterVolumeForUid(direction, flags, packageName,
- uid);
- return;
- }
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
if (useSuggested) {
if (AudioSystem.isStreamActive(stream, 0)) {
@@ -729,7 +718,6 @@
@Override
public void setMediaRouter(IMediaRouter router) {
- mMediaRouter = router;
mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 4383bb1..72205d6 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -89,11 +89,9 @@
private final Object mLock = new Object();
private final MessageHandler mHandler = new MessageHandler();
private final PowerManager.WakeLock mMediaEventWakeLock;
- private final boolean mUseMasterVolume;
private KeyguardManager mKeyguardManager;
private IAudioService mAudioService;
- private AudioManager mAudioManager;
private AudioManagerInternal mAudioManagerInternal;
private ContentResolver mContentResolver;
private SettingsObserver mSettingsObserver;
@@ -110,8 +108,6 @@
mPriorityStack = new MediaSessionStack();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
- mUseMasterVolume = context.getResources().getBoolean(
- com.android.internal.R.bool.config_useMasterVolume);
}
@Override
@@ -121,7 +117,6 @@
mKeyguardManager =
(KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
mAudioService = getAudioService();
- mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mContentResolver = getContext().getContentResolver();
mSettingsObserver = new SettingsObserver();
@@ -468,11 +463,6 @@
return -1;
}
- private boolean isSessionDiscoverable(MediaSessionRecord record) {
- // TODO probably want to check more than if it's active.
- return record.isActive();
- }
-
private void pushSessionsChanged(int userId) {
synchronized (mLock) {
List<MediaSessionRecord> records = mPriorityStack.getActiveSessions(userId);
@@ -889,12 +879,8 @@
}
try {
String packageName = getContext().getOpPackageName();
- if (mUseMasterVolume) {
- mAudioService.adjustMasterVolume(direction, flags, packageName);
- } else {
- mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
- flags, packageName);
- }
+ mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream,
+ flags, packageName);
} catch (RemoteException e) {
Log.e(TAG, "Error adjusting default volume.", e);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9b6b5fb..bedcabe 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2584,8 +2584,8 @@
@Override
public void run() {
String listenerName = listener == null ? null : listener.component.toShortString();
- EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, id, tag, userId,
- mustHaveFlags, mustNotHaveFlags, reason, listenerName);
+ if (DBG) EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, id, tag,
+ userId, mustHaveFlags, mustNotHaveFlags, reason, listenerName);
synchronized (mNotificationList) {
int index = indexOfNotificationLocked(pkg, tag, id, userId);
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index 773b164..aa63932 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -414,9 +414,9 @@
// Get the package's known keys and KeySets
ArraySet<Long> deletableKeySets = getOriginalKeySetsByPackageNameLPr(packageName);
ArraySet<Long> deletableKeys = new ArraySet<Long>();
- ArraySet<Long> knownKeys = null;
- for (Long ks : deletableKeySets) {
- knownKeys = mKeySetMapping.get(ks);
+ final int origDksSize = deletableKeySets.size();
+ for (int i = 0; i < origDksSize; i++) {
+ ArraySet<Long> knownKeys = mKeySetMapping.get(deletableKeySets.valueAt(i));
if (knownKeys != null) {
deletableKeys.addAll(knownKeys);
}
@@ -429,9 +429,9 @@
}
ArraySet<Long> knownKeySets = getOriginalKeySetsByPackageNameLPr(pkgName);
deletableKeySets.removeAll(knownKeySets);
- knownKeys = new ArraySet<Long>();
- for (Long ks : knownKeySets) {
- knownKeys = mKeySetMapping.get(ks);
+ final int kksSize = knownKeySets.size();
+ for (int i = 0; i < kksSize; i++) {
+ ArraySet<Long> knownKeys = mKeySetMapping.get(knownKeySets.valueAt(i));
if (knownKeys != null) {
deletableKeys.removeAll(knownKeys);
}
@@ -440,18 +440,22 @@
// The remaining keys and KeySets are not relied on by any other
// application and so can be safely deleted.
- for (Long ks : deletableKeySets) {
+ final int dksSize = deletableKeySets.size();
+ for (int i = 0; i < dksSize; i++) {
+ Long ks = deletableKeySets.valueAt(i);
mKeySets.delete(ks);
mKeySetMapping.delete(ks);
}
- for (Long keyId : deletableKeys) {
- mPublicKeys.delete(keyId);
+ final int dkSize = deletableKeys.size();
+ for (int i = 0; i < dkSize; i++) {
+ mPublicKeys.delete(deletableKeys.valueAt(i));
}
// Now remove the deleted KeySets from each package's signingKeySets
for (String pkgName : mPackages.keySet()) {
PackageSetting p = mPackages.get(pkgName);
- for (Long ks : deletableKeySets) {
+ for (int i = 0; i < dksSize; i++) {
+ Long ks = deletableKeySets.valueAt(i);
p.keySetData.removeSigningKeySet(ks);
}
}
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index e511346..e720f3e 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -40,6 +40,7 @@
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
import android.widget.Button;
import android.widget.FrameLayout;
@@ -170,7 +171,7 @@
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_TOAST,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
0
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
@@ -179,8 +180,7 @@
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("ImmersiveModeConfirmation");
- lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
- lp.gravity = Gravity.FILL;
+ lp.windowAnimations = com.android.internal.R.style.Animation_ImmersiveModeConfirmation;
return lp;
}
@@ -194,10 +194,12 @@
private class ClingWindowView extends FrameLayout {
private static final int BGCOLOR = 0x80000000;
- private static final int OFFSET_DP = 48;
+ private static final int OFFSET_DP = 96;
+ private static final int ANIMATION_DURATION = 250;
private final Runnable mConfirm;
private final ColorDrawable mColor = new ColorDrawable(0);
+ private final Interpolator mInterpolator;
private ValueAnimator mColorAnim;
private ViewGroup mClingLayout;
@@ -222,8 +224,10 @@
public ClingWindowView(Context context, Runnable confirm) {
super(context);
mConfirm = confirm;
- setClickable(true);
setBackground(mColor);
+ setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+ mInterpolator = AnimationUtils
+ .loadInterpolator(mContext, android.R.interpolator.linear_out_slow_in);
}
@Override
@@ -248,40 +252,40 @@
addView(mClingLayout, getBubbleLayoutParams());
if (ActivityManager.isHighEndGfx()) {
- final View bubble = mClingLayout.findViewById(R.id.text);
- bubble.setAlpha(0f);
- bubble.setTranslationY(-OFFSET_DP*density);
- bubble.animate()
- .alpha(1f)
- .translationY(0)
- .setDuration(300)
- .setInterpolator(new DecelerateInterpolator())
- .start();
+ final View cling = mClingLayout;
+ cling.setAlpha(0f);
+ cling.setTranslationY(-OFFSET_DP * density);
- ok.setAlpha(0f);
- ok.setTranslationY(-OFFSET_DP*density);
- ok.animate().alpha(1f)
- .translationY(0)
- .setDuration(300)
- .setStartDelay(200)
- .setInterpolator(new DecelerateInterpolator())
- .start();
-
- mColorAnim = ValueAnimator.ofObject(new ArgbEvaluator(), 0, BGCOLOR);
- mColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ postOnAnimation(new Runnable() {
@Override
- public void onAnimationUpdate(ValueAnimator animation) {
- final int c = (Integer) animation.getAnimatedValue();
- mColor.setColor(c);
+ public void run() {
+ cling.animate()
+ .alpha(1f)
+ .translationY(0)
+ .setDuration(ANIMATION_DURATION)
+ .setInterpolator(mInterpolator)
+ .withLayer()
+ .start();
+
+ mColorAnim = ValueAnimator.ofObject(new ArgbEvaluator(), 0, BGCOLOR);
+ mColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final int c = (Integer) animation.getAnimatedValue();
+ mColor.setColor(c);
+ }
+ });
+ mColorAnim.setDuration(ANIMATION_DURATION);
+ mColorAnim.setInterpolator(mInterpolator);
+ mColorAnim.start();
}
});
- mColorAnim.setDuration(1000);
- mColorAnim.start();
} else {
mColor.setColor(BGCOLOR);
}
- mContext.registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
+ mContext.registerReceiver(mReceiver,
+ new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
}
@Override
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5185cf6..1e64017 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -380,7 +380,6 @@
boolean mHasSoftInput = false;
boolean mTranslucentDecorEnabled = true;
boolean mUseTvRouting;
- boolean mUseMasterVolume;
int mPointerLocationMode = 0; // guarded by mLock
@@ -1270,8 +1269,6 @@
com.android.internal.R.integer.config_triplePressOnPowerBehavior);
mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION;
- mUseMasterVolume = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_useMasterVolume);
readConfigurationDependentBehaviors();
@@ -4859,26 +4856,16 @@
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
try {
- if (mUseMasterVolume) {
- getAudioService().adjustMasterVolume(AudioManager.ADJUST_RAISE, flags,
- pkgName);
- } else {
- getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
- AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
- }
+ getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE,
+ AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
} catch (RemoteException e) {
Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e);
}
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
try {
- if (mUseMasterVolume) {
- getAudioService().adjustMasterVolume(AudioManager.ADJUST_LOWER, flags,
- pkgName);
- } else {
- getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
- AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
- }
+ getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER,
+ AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
} catch (RemoteException e) {
Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e);
}
@@ -4886,14 +4873,9 @@
case KeyEvent.KEYCODE_VOLUME_MUTE:
try {
if (event.getRepeatCount() == 0) {
- if (mUseMasterVolume) {
- getAudioService().adjustMasterVolume(AudioManager.ADJUST_TOGGLE_MUTE,
- flags, pkgName);
- } else {
- getAudioService().adjustSuggestedStreamVolume(
- AudioManager.ADJUST_TOGGLE_MUTE,
- AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
- }
+ getAudioService().adjustSuggestedStreamVolume(
+ AudioManager.ADJUST_TOGGLE_MUTE,
+ AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName);
}
} catch (RemoteException e) {
Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e);
@@ -5032,8 +5014,8 @@
boolean sb = mStatusBarController.checkShowTransientBarLw();
boolean nb = mNavigationBarController.checkShowTransientBarLw();
if (sb || nb) {
- WindowState barTarget = sb ? mStatusBar : mNavigationBar;
- if (sb ^ nb && barTarget != swipeTarget) {
+ // Don't show status bar when swiping on already visible navigation bar
+ if (!nb && swipeTarget == mNavigationBar) {
if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
return;
}
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index e57396f..ac8ad30 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -102,7 +102,6 @@
};
private int mCurrentIndex = 0;
private int mCurrentMaxIndex = 0;
- private final boolean mUseMasterVolume;
// TODO: Should handle STANDBY case.
private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray();
@@ -117,8 +116,6 @@
mContext = context;
mListener = listener;
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- mUseMasterVolume = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_useMasterVolume);
mHal.init();
}
@@ -139,12 +136,10 @@
} else {
Slog.w(TAG, "HdmiControlService is not available");
}
- if (!mUseMasterVolume) {
- final IntentFilter filter = new IntentFilter();
- filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
- filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
- mContext.registerReceiver(mVolumeReceiver, filter);
- }
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
+ filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION);
+ mContext.registerReceiver(mVolumeReceiver, filter);
updateVolume();
}
}
@@ -545,7 +540,7 @@
}
private float getMediaStreamVolume() {
- return mUseMasterVolume ? 1.0f : ((float) mCurrentIndex / (float) mCurrentMaxIndex);
+ return (float) mCurrentIndex / (float) mCurrentMaxIndex;
}
private class Connection implements IBinder.DeathRecipient {
diff --git a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
index 3de1bba..4e53687 100644
--- a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
@@ -47,39 +47,6 @@
super("/data/security/bundle", "sepolicy_bundle", "metadata/", "version");
}
- private void backupContexts(File contexts) {
- new File(contexts, versionPath).renameTo(
- new File(contexts, versionPath + "_backup"));
-
- new File(contexts, macPermissionsPath).renameTo(
- new File(contexts, macPermissionsPath + "_backup"));
-
- new File(contexts, seappContextsPath).renameTo(
- new File(contexts, seappContextsPath + "_backup"));
-
- new File(contexts, propertyContextsPath).renameTo(
- new File(contexts, propertyContextsPath + "_backup"));
-
- new File(contexts, fileContextsPath).renameTo(
- new File(contexts, fileContextsPath + "_backup"));
-
- new File(contexts, sepolicyPath).renameTo(
- new File(contexts, sepolicyPath + "_backup"));
-
- new File(contexts, serviceContextsPath).renameTo(
- new File(contexts, serviceContextsPath + "_backup"));
- }
-
- private void copyUpdate(File contexts) {
- new File(updateDir, versionPath).renameTo(new File(contexts, versionPath));
- new File(updateDir, macPermissionsPath).renameTo(new File(contexts, macPermissionsPath));
- new File(updateDir, seappContextsPath).renameTo(new File(contexts, seappContextsPath));
- new File(updateDir, propertyContextsPath).renameTo(new File(contexts, propertyContextsPath));
- new File(updateDir, fileContextsPath).renameTo(new File(contexts, fileContextsPath));
- new File(updateDir, sepolicyPath).renameTo(new File(contexts, sepolicyPath));
- new File(updateDir, serviceContextsPath).renameTo(new File(contexts, serviceContextsPath));
- }
-
private int readInt(BufferedInputStream reader) throws IOException {
int value = 0;
for (int i=0; i < 4; i++) {
@@ -107,17 +74,27 @@
writeUpdate(updateDir, destination, Base64.decode(chunk, Base64.DEFAULT));
}
+ private void deleteRecursive(File fileOrDirectory) {
+ if (fileOrDirectory.isDirectory())
+ for (File child : fileOrDirectory.listFiles())
+ deleteRecursive(child);
+ fileOrDirectory.delete();
+ }
+
private void unpackBundle() throws IOException {
BufferedInputStream stream = new BufferedInputStream(new FileInputStream(updateContent));
+ File tmp = new File(updateDir.getParentFile(), "tmp");
try {
int[] chunkLengths = readChunkLengths(stream);
- installFile(new File(updateDir, versionPath), stream, chunkLengths[0]);
- installFile(new File(updateDir, macPermissionsPath), stream, chunkLengths[1]);
- installFile(new File(updateDir, seappContextsPath), stream, chunkLengths[2]);
- installFile(new File(updateDir, propertyContextsPath), stream, chunkLengths[3]);
- installFile(new File(updateDir, fileContextsPath), stream, chunkLengths[4]);
- installFile(new File(updateDir, sepolicyPath), stream, chunkLengths[5]);
- installFile(new File(updateDir, serviceContextsPath), stream, chunkLengths[6]);
+ deleteRecursive(tmp);
+ tmp.mkdirs();
+ installFile(new File(tmp, versionPath), stream, chunkLengths[0]);
+ installFile(new File(tmp, macPermissionsPath), stream, chunkLengths[1]);
+ installFile(new File(tmp, seappContextsPath), stream, chunkLengths[2]);
+ installFile(new File(tmp, propertyContextsPath), stream, chunkLengths[3]);
+ installFile(new File(tmp, fileContextsPath), stream, chunkLengths[4]);
+ installFile(new File(tmp, sepolicyPath), stream, chunkLengths[5]);
+ installFile(new File(tmp, serviceContextsPath), stream, chunkLengths[6]);
} finally {
IoUtils.closeQuietly(stream);
}
@@ -125,22 +102,22 @@
private void applyUpdate() throws IOException, ErrnoException {
Slog.i(TAG, "Applying SELinux policy");
- File contexts = new File(updateDir.getParentFile(), "contexts");
+ File backup = new File(updateDir.getParentFile(), "backup");
File current = new File(updateDir.getParentFile(), "current");
- File update = new File(updateDir.getParentFile(), "update");
File tmp = new File(updateDir.getParentFile(), "tmp");
if (current.exists()) {
- Os.symlink(updateDir.getPath(), update.getPath());
- Os.rename(update.getPath(), current.getPath());
- } else {
- Os.symlink(updateDir.getPath(), current.getPath());
+ deleteRecursive(backup);
+ Os.rename(current.getPath(), backup.getPath());
}
- contexts.mkdirs();
- backupContexts(contexts);
- copyUpdate(contexts);
- Os.symlink(contexts.getPath(), tmp.getPath());
- Os.rename(tmp.getPath(), current.getPath());
- SystemProperties.set("selinux.reload_policy", "1");
+ try {
+ Os.rename(tmp.getPath(), current.getPath());
+ SystemProperties.set("selinux.reload_policy", "1");
+ } catch (ErrnoException e) {
+ Slog.e(TAG, "Could not update selinux policy: ", e);
+ if (backup.exists()) {
+ Os.rename(backup.getPath(), current.getPath());
+ }
+ }
}
@Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index 57ed876..ea59d4b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -53,6 +53,7 @@
private static final String DEVICE_OWNER_XML = "device_owner.xml";
private static final String TAG_DEVICE_OWNER = "device-owner";
+ private static final String TAG_DEVICE_INITIALIZER = "device-initializer";
private static final String TAG_PROFILE_OWNER = "profile-owner";
private static final String ATTR_NAME = "name";
private static final String ATTR_PACKAGE = "package";
@@ -68,6 +69,9 @@
// Internal state for the device owner package.
private OwnerInfo mDeviceOwner;
+ // Internal state for the device initializer package.
+ private OwnerInfo mDeviceInitializer;
+
// Internal state for the profile owner packages.
private final HashMap<Integer, OwnerInfo> mProfileOwners = new HashMap<Integer, OwnerInfo>();
@@ -104,6 +108,15 @@
}
/**
+ * Creates an instance of the device owner object with the device initializer set.
+ */
+ static DeviceOwner createWithDeviceInitializer(String packageName, String ownerName) {
+ DeviceOwner owner = new DeviceOwner();
+ owner.mDeviceInitializer = new OwnerInfo(ownerName, packageName);
+ return owner;
+ }
+
+ /**
* Creates an instance of the device owner object with the profile owner set.
*/
static DeviceOwner createWithProfileOwner(ComponentName admin, String ownerName, int userId) {
@@ -128,6 +141,26 @@
mDeviceOwner = null;
}
+ String getDeviceInitializerPackageName() {
+ return mDeviceInitializer != null ? mDeviceInitializer.packageName : null;
+ }
+
+ String getDeviceInitializerName() {
+ return mDeviceInitializer != null ? mDeviceInitializer.name : null;
+ }
+
+ void setDeviceInitializer(String packageName, String ownerName) {
+ mDeviceInitializer = new OwnerInfo(ownerName, packageName);
+ }
+
+ void clearDeviceInitializer() {
+ mDeviceInitializer = null;
+ }
+
+ boolean hasDeviceInitializer() {
+ return mDeviceInitializer != null;
+ }
+
void setProfileOwner(ComponentName admin, String ownerName, int userId) {
mProfileOwners.put(userId, new OwnerInfo(ownerName, admin));
}
@@ -199,6 +232,10 @@
String name = parser.getAttributeValue(null, ATTR_NAME);
String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
mDeviceOwner = new OwnerInfo(name, packageName);
+ } else if (tag.equals(TAG_DEVICE_INITIALIZER)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+ mDeviceInitializer = new OwnerInfo(name, packageName);
} else if (tag.equals(TAG_PROFILE_OWNER)) {
String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME);
@@ -259,6 +296,16 @@
out.endTag(null, TAG_DEVICE_OWNER);
}
+ // Write device initializer tag
+ if (mDeviceInitializer != null) {
+ out.startTag(null, TAG_DEVICE_INITIALIZER);
+ out.attribute(null, ATTR_PACKAGE, mDeviceInitializer.packageName);
+ if (mDeviceInitializer.name != null) {
+ out.attribute(null, ATTR_NAME, mDeviceInitializer.name);
+ }
+ out.endTag(null, TAG_DEVICE_INITIALIZER);
+ }
+
// Write profile owner tags
if (mProfileOwners.size() > 0) {
for (HashMap.Entry<Integer, OwnerInfo> owner : mProfileOwners.entrySet()) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a19cd9f..b90666f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
+import android.graphics.Bitmap;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.media.IAudioService;
@@ -1139,13 +1140,15 @@
boolean ownsProfile = (getProfileOwner(userHandle) != null
&& getProfileOwner(userHandle).getPackageName()
.equals(admin.info.getPackageName()));
+ boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName())
+ && !hasUserSetupCompleted(userHandle);
if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
- if (ownsDevice) {
+ if (ownsDevice || (userHandle == UserHandle.USER_OWNER && ownsInitialization)) {
return admin;
}
} else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
- if (ownsDevice || ownsProfile) {
+ if (ownsDevice || ownsProfile || ownsInitialization) {
return admin;
}
} else {
@@ -1899,7 +1902,7 @@
return;
}
if (admin.getUid() != Binder.getCallingUid()) {
- // If trying to remove device owner, refuse when the caller is not the owner.
+ // Active device owners must remain active admins.
if (isDeviceOwner(adminReceiver.getPackageName())) {
return;
}
@@ -3866,6 +3869,110 @@
}
@Override
+ public boolean setDeviceInitializer(ComponentName who, ComponentName initializer,
+ String ownerName) {
+ if (!mHasFeature) {
+ return false;
+ }
+ if (initializer == null || !DeviceOwner.isInstalled(
+ initializer.getPackageName(), mContext.getPackageManager())) {
+ throw new IllegalArgumentException("Invalid component name " + initializer
+ + " for device initializer");
+ }
+ synchronized (this) {
+ enforceCanSetDeviceInitializer(who);
+
+ if (mDeviceOwner != null && mDeviceOwner.hasDeviceInitializer()) {
+ throw new IllegalStateException(
+ "Trying to set device initializer but device initializer is already set.");
+ }
+
+ if (mDeviceOwner == null) {
+ // Device owner state does not exist, create it.
+ mDeviceOwner = DeviceOwner.createWithDeviceInitializer(
+ initializer.getPackageName(), ownerName);
+ mDeviceOwner.writeOwnerFile();
+ return true;
+ } else {
+ // Device owner already exists, update it.
+ mDeviceOwner.setDeviceInitializer(initializer.getPackageName(), ownerName);
+ mDeviceOwner.writeOwnerFile();
+ return true;
+ }
+ }
+ }
+
+ private void enforceCanSetDeviceInitializer(ComponentName who) {
+ if (who == null) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
+ if (hasUserSetupCompleted(UserHandle.USER_OWNER)) {
+ throw new IllegalStateException(
+ "Trying to set device initializer but device is already provisioned.");
+ }
+ } else {
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+ }
+ }
+
+ @Override
+ public boolean isDeviceInitializer(String packageName) {
+ if (!mHasFeature) {
+ return false;
+ }
+ synchronized (this) {
+ return mDeviceOwner != null
+ && mDeviceOwner.hasDeviceInitializer()
+ && mDeviceOwner.getDeviceInitializerPackageName().equals(packageName);
+ }
+ }
+
+ @Override
+ public String getDeviceInitializer() {
+ if (!mHasFeature) {
+ return null;
+ }
+ synchronized (this) {
+ if (mDeviceOwner != null && mDeviceOwner.hasDeviceInitializer()) {
+ return mDeviceOwner.getDeviceInitializerPackageName();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void clearDeviceInitializer(ComponentName who) {
+ if (!mHasFeature) {
+ return;
+ }
+ Preconditions.checkNotNull(who, "ComponentName is null");
+
+ ActiveAdmin admin = getActiveAdminUncheckedLocked(who, UserHandle.getCallingUserId());
+
+ if (admin.getUid() != Binder.getCallingUid()) {
+ throw new SecurityException("Admin " + who + " is not owned by uid "
+ + Binder.getCallingUid());
+ }
+
+ if (!isDeviceInitializer(admin.info.getPackageName())
+ && !isDeviceOwner(admin.info.getPackageName())) {
+ throw new SecurityException(
+ "clearDeviceInitializer can only be called by the device initializer/owner");
+ }
+ synchronized (this) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (mDeviceOwner != null) {
+ mDeviceOwner.clearDeviceInitializer();
+ mDeviceOwner.writeOwnerFile();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ @Override
public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
if (!mHasFeature) {
return false;
@@ -3938,7 +4045,7 @@
Bundle userRestrictions = mUserManager.getUserRestrictions();
mUserManager.setUserRestrictions(new Bundle(), userHandle);
if (userRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)) {
- audioManager.adjustMasterVolume(AudioManager.ADJUST_UNMUTE, 0);
+ audioManager.setMasterMute(false, 0);
}
if (userRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE)) {
audioManager.setMicrophoneMute(false);
@@ -3960,6 +4067,51 @@
}
@Override
+ public boolean setUserEnabled(ComponentName who) {
+ if (!mHasFeature) {
+ return false;
+ }
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ int userId = UserHandle.getCallingUserId();
+
+ ActiveAdmin activeAdmin =
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ if (!isDeviceInitializer(activeAdmin.info.getPackageName())) {
+ throw new SecurityException(
+ "This method can only be called by device initializers");
+ }
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ if (!isDeviceOwner(activeAdmin.info.getPackageName())) {
+ IPackageManager ipm = AppGlobals.getPackageManager();
+ ipm.setComponentEnabledSetting(who,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP, userId);
+
+ removeActiveAdmin(who, userId);
+ }
+
+ if (userId == UserHandle.USER_OWNER) {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.DEVICE_PROVISIONED, 1);
+ }
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE, 1, userId);
+ } catch (RemoteException e) {
+ Log.i(LOG_TAG, "Can't talk to package manager", e);
+ return false;
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ return true;
+ }
+ }
+
+ @Override
public void setProfileEnabled(ComponentName who) {
if (!mHasFeature) {
return;
@@ -4815,8 +4967,7 @@
if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
iAudioService.setMicrophoneMute(true, who.getPackageName());
} else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
- iAudioService.adjustMasterVolume(AudioManager.ADJUST_MUTE, 0,
- who.getPackageName());
+ iAudioService.setMasterMute(true, 0, who.getPackageName());
}
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
@@ -4881,8 +5032,7 @@
if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
iAudioService.setMicrophoneMute(false, who.getPackageName());
} else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
- iAudioService.adjustMasterVolume(AudioManager.ADJUST_UNMUTE, 0,
- who.getPackageName());
+ iAudioService.setMasterMute(false, 0, who.getPackageName());
}
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
@@ -5322,10 +5472,8 @@
IAudioService iAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
- try{
- iAudioService.adjustMasterVolume(
- on ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE, 0,
- who.getPackageName());
+ try {
+ iAudioService.setMasterMute(on, 0, who.getPackageName());
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Failed to setMasterMute", re);
}
@@ -5344,6 +5492,22 @@
}
}
+ @Override
+ public void setUserIcon(ComponentName who, Bitmap icon) {
+ synchronized (this) {
+ Preconditions.checkNotNull(who, "ComponentName is null");
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ int userId = UserHandle.getCallingUserId();
+ long id = Binder.clearCallingIdentity();
+ try {
+ mUserManager.setUserIcon(userId, icon);
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
+
/**
* We need to update the internal state of whether a user has completed setup once. After
* that, we ignore any changes that reset the Settings.Secure.USER_SETUP_COMPLETE changes
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index cd6e786..a0c7f86 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -669,7 +669,8 @@
mSystemServiceManager.startService("com.android.server.wifi.RttService");
- if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) {
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
}
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index b3900b9..8849acd 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -96,7 +96,7 @@
}
try {
listenToSocket();
- } catch (IOException e) {
+ } catch (Exception e) {
/* Don't loop too fast if adbd dies, before init restarts it */
SystemClock.sleep(1000);
}
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index e17abc0..a6e9677 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiDeviceServer;
+import android.media.midi.MidiDispatcher;
import android.media.midi.MidiManager;
import android.media.midi.MidiPort;
import android.media.midi.MidiReceiver;
@@ -30,6 +31,8 @@
import android.system.StructPollfd;
import android.util.Log;
+import libcore.io.IoUtils;
+
import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -39,8 +42,9 @@
public final class UsbMidiDevice implements Closeable {
private static final String TAG = "UsbMidiDevice";
- private final MidiDeviceServer mServer;
- private final MidiReceiver[] mOutputPortReceivers;
+ private MidiDeviceServer mServer;
+
+ private final MidiReceiver[] mInputPortReceivers;
// for polling multiple FileDescriptors for MIDI events
private final StructPollfd[] mPollFDs;
@@ -50,12 +54,6 @@
private final FileOutputStream[] mOutputStreams;
public static UsbMidiDevice create(Context context, Bundle properties, int card, int device) {
- MidiManager midiManager = (MidiManager)context.getSystemService(Context.MIDI_SERVICE);
- if (midiManager == null) {
- Log.e(TAG, "No MidiManager in UsbMidiDevice.create()");
- return null;
- }
-
// FIXME - support devices with different number of input and output ports
int subDevices = nativeGetSubdeviceCount(card, device);
if (subDevices <= 0) {
@@ -70,19 +68,16 @@
return null;
}
- MidiDeviceServer server = midiManager.createDeviceServer(subDevices, subDevices, properties,
- false, MidiDeviceInfo.TYPE_USB);
- if (server == null) {
+ UsbMidiDevice midiDevice = new UsbMidiDevice(fileDescriptors, fileDescriptors);
+ if (!midiDevice.register(context, properties)) {
+ IoUtils.closeQuietly(midiDevice);
Log.e(TAG, "createDeviceServer failed");
return null;
}
-
- return new UsbMidiDevice(server, fileDescriptors, fileDescriptors);
+ return midiDevice;
}
- private UsbMidiDevice(MidiDeviceServer server, FileDescriptor[] inputFiles,
- FileDescriptor[] outputFiles) {
- mServer = server;
+ private UsbMidiDevice(FileDescriptor[] inputFiles, FileDescriptor[] outputFiles) {
int inputCount = inputFiles.length;
int outputCount = outputFiles.length;
@@ -102,26 +97,36 @@
mOutputStreams[i] = new FileOutputStream(outputFiles[i]);
}
- mOutputPortReceivers = new MidiReceiver[outputCount];
- for (int port = 0; port < outputCount; port++) {
- mOutputPortReceivers[port] = server.openOutputPortReceiver(port);
- }
-
+ mInputPortReceivers = new MidiReceiver[inputCount];
for (int port = 0; port < inputCount; port++) {
- final int portNumberF = port;
- MidiReceiver receiver = new MidiReceiver() {
-
+ final int portF = port;
+ mInputPortReceivers[port] = new MidiReceiver() {
@Override
public void post(byte[] data, int offset, int count, long timestamp)
throws IOException {
// FIXME - timestamps are ignored, future posting not supported yet.
- mOutputStreams[portNumberF].write(data, offset, count);
+ mOutputStreams[portF].write(data, offset, count);
}
};
- MidiSender sender = server.openInputPortSender(port);
- sender.connect(receiver);
+ }
+ }
+
+ private boolean register(Context context, Bundle properties) {
+ MidiManager midiManager = (MidiManager)context.getSystemService(Context.MIDI_SERVICE);
+ if (midiManager == null) {
+ Log.e(TAG, "No MidiManager in UsbMidiDevice.create()");
+ return false;
}
+ int outputCount = mOutputStreams.length;
+ mServer = midiManager.createDeviceServer(mInputPortReceivers, outputCount,
+ properties, MidiDeviceInfo.TYPE_USB);
+ if (mServer == null) {
+ return false;
+ }
+ final MidiReceiver[] outputReceivers = mServer.getOutputPortReceivers();
+
+ // FIXME can we only run this when we have a dispatcher that has listeners?
new Thread() {
@Override
public void run() {
@@ -137,8 +142,8 @@
pfd.revents = 0;
int count = mInputStreams[index].read(buffer);
- mOutputPortReceivers[index].post(buffer, 0, count,
- System.nanoTime());
+ long timestamp = System.nanoTime();
+ outputReceivers[index].post(buffer, 0, count, timestamp);
} else if ((pfd.revents & (OsConstants.POLLERR
| OsConstants.POLLHUP)) != 0) {
done = true;
@@ -155,11 +160,15 @@
}
}
}.start();
+
+ return true;
}
@Override
public void close() throws IOException {
- mServer.close();
+ if (mServer != null) {
+ mServer.close();
+ }
for (int i = 0; i < mInputStreams.length; i++) {
mInputStreams[i].close();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0a4b787..f3b2d2e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3716,6 +3716,34 @@
}
/**
+ * Whether the device supports configuring the DTMF tone length.
+ *
+ * @return {@code true} if the DTMF tone length can be changed, and {@code false} otherwise.
+ */
+ public boolean canChangeDtmfToneLength() {
+ try {
+ return getITelephony().canChangeDtmfToneLength();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#canChangeDtmfToneLength", e);
+ }
+ return false;
+ }
+
+ /**
+ * Whether the device is a world phone.
+ *
+ * @return {@code true} if the device is a world phone, and {@code false} otherwise.
+ */
+ public boolean isWorldPhone() {
+ try {
+ return getITelephony().isWorldPhone();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#isWorldPhone", e);
+ }
+ return false;
+ }
+
+ /**
* This function retrieves value for setting "name+subId", and if that is not found
* retrieves value for setting "name", and if that is not found uses def as default
*
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 62c8746..3769dee 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -863,11 +863,25 @@
/**
* Whether video calling has been enabled by the user.
*
- * @return {@code True} if the user has enabled video calling, {@code false} otherwise.
+ * @return {@code true} if the user has enabled video calling, {@code false} otherwise.
*/
boolean isVideoCallingEnabled();
/**
+ * Whether the DTMF tone length can be changed.
+ *
+ * @return {@code true} if the DTMF tone length can be changed.
+ */
+ boolean canChangeDtmfToneLength();
+
+ /**
+ * Whether the device is a world phone.
+ *
+ * @return {@code true} if the devices is a world phone.
+ */
+ boolean isWorldPhone();
+
+ /**
* Get IMS Registration Status
*/
boolean isImsRegistered();
diff --git a/test-runner/src/android/test/RenamingDelegatingContext.java b/test-runner/src/android/test/RenamingDelegatingContext.java
index 3d763c7..3c4da9e 100644
--- a/test-runner/src/android/test/RenamingDelegatingContext.java
+++ b/test-runner/src/android/test/RenamingDelegatingContext.java
@@ -107,7 +107,7 @@
}
/**
- * @param context : the context that will be delagated.
+ * @param context : the context that will be delegated.
* @param filePrefix : a prefix with which database and file names will be
* prefixed.
*/
@@ -118,8 +118,8 @@
}
/**
- * @param context : the context that will be delagated.
- * @param fileContext : the context that file and db methods will be delgated to
+ * @param context : the context that will be delegated.
+ * @param fileContext : the context that file and db methods will be delegated to
* @param filePrefix : a prefix with which database and file names will be
* prefixed.
*/
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 5ab177b..063b4e6 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -481,8 +481,9 @@
// assuming the image is a round rect, compute the radius by marching
// diagonally from the top left corner towards the center
- image->outlineAlpha = max(max_alpha_over_row(image->rows[innerMidY], innerStartX, innerEndX),
- max_alpha_over_col(image->rows, innerMidX, innerStartY, innerStartY));
+ image->outlineAlpha = std::max(
+ max_alpha_over_row(image->rows[innerMidY], innerStartX, innerEndX),
+ max_alpha_over_col(image->rows, innerMidX, innerStartY, innerStartY));
int diagonalInset = 0;
find_max_opacity(image->rows, innerStartX, innerStartY, innerMidX, innerMidY, 1, 1,
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 6fbc17c..941a288 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1807,7 +1807,7 @@
}
const ResTable& featureTable = featureAssetManager.getResources(false);
- mTypeIdOffset = max(mTypeIdOffset,
+ mTypeIdOffset = std::max(mTypeIdOffset,
findLargestTypeIdForPackage(featureTable, mAssetsPackage));
}
@@ -2703,20 +2703,16 @@
const String8 defaultLocale;
// For all strings...
- for (map<String16, map<String8, SourcePos> >::iterator nameIter = mLocalizations.begin();
- nameIter != mLocalizations.end();
- nameIter++) {
- const map<String8, SourcePos>& configSrcMap = nameIter->second;
+ for (const auto& nameIter : mLocalizations) {
+ const std::map<String8, SourcePos>& configSrcMap = nameIter.second;
// Look for strings with no default localization
if (configSrcMap.count(defaultLocale) == 0) {
SourcePos().warning("string '%s' has no default translation.",
- String8(nameIter->first).string());
+ String8(nameIter.first).string());
if (mBundle->getVerbose()) {
- for (map<String8, SourcePos>::const_iterator locales = configSrcMap.begin();
- locales != configSrcMap.end();
- locales++) {
- locales->second.printf("locale %s found", locales->first.string());
+ for (const auto& locale : configSrcMap) {
+ locale.second.printf("locale %s found", locale.first.string());
}
}
// !!! TODO: throw an error here in some circumstances
@@ -2727,8 +2723,8 @@
const char* allConfigs = mBundle->getConfigurations().string();
const char* start = allConfigs;
const char* comma;
-
- set<String8> missingConfigs;
+
+ std::set<String8> missingConfigs;
AaptLocaleValue locale;
do {
String8 config;
@@ -2762,13 +2758,11 @@
if (!missingConfigs.empty()) {
String8 configStr;
- for (set<String8>::iterator iter = missingConfigs.begin();
- iter != missingConfigs.end();
- iter++) {
- configStr.appendFormat(" %s", iter->string());
+ for (const auto& iter : missingConfigs) {
+ configStr.appendFormat(" %s", iter.string());
}
SourcePos().warning("string '%s' is missing %u required localizations:%s",
- String8(nameIter->first).string(),
+ String8(nameIter.first).string(),
(unsigned int)missingConfigs.size(),
configStr.string());
}
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index eef0ae1..9644224 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -17,8 +17,6 @@
#include "StringPool.h"
#include "Symbol.h"
-using namespace std;
-
class XMLNode;
class ResourceTable;
@@ -29,7 +27,7 @@
XML_COMPILE_STRIP_WHITESPACE = 1<<3,
XML_COMPILE_STRIP_RAW_VALUES = 1<<4,
XML_COMPILE_UTF8 = 1<<5,
-
+
XML_COMPILE_STANDARD_RESOURCE =
XML_COMPILE_STRIP_COMMENTS | XML_COMPILE_ASSIGN_ATTRIBUTE_IDS
| XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES
@@ -116,7 +114,7 @@
* and would mess up iteration order for the existing
* resources.
*/
- queue<CompileResourceWorkItem>& getWorkQueue() {
+ std::queue<CompileResourceWorkItem>& getWorkQueue() {
return mWorkQueue;
}
@@ -587,10 +585,10 @@
size_t mNumLocal;
SourcePos mCurrentXmlPos;
Bundle* mBundle;
-
+
// key = string resource name, value = set of locales in which that name is defined
- map<String16, map<String8, SourcePos> > mLocalizations;
- queue<CompileResourceWorkItem> mWorkQueue;
+ std::map<String16, std::map<String8, SourcePos>> mLocalizations;
+ std::queue<CompileResourceWorkItem> mWorkQueue;
};
#endif
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 8d24d38..970b9d0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -76,13 +76,6 @@
// ---- Public Helper methods ----
/**
- * Returns the native delegate associated to a given {@link Bitmap_Delegate} object.
- */
- public static Bitmap_Delegate getDelegate(Bitmap bitmap) {
- return sManager.getDelegate(bitmap.mNativeBitmap);
- }
-
- /**
* Returns the native delegate associated to a given an int referencing a {@link Bitmap} object.
*/
public static Bitmap_Delegate getDelegate(long native_bitmap) {
@@ -187,19 +180,6 @@
return createBitmap(delegate, createFlags, density.getDpiValue());
}
- /**
- * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
- */
- public static BufferedImage getImage(Bitmap bitmap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(bitmap.mNativeBitmap);
- if (delegate == null) {
- return null;
- }
-
- return delegate.mImage;
- }
-
public static int getBufferedImageType(int nativeBitmapConfig) {
switch (Config.nativeToConfig(nativeBitmapConfig)) {
case ALPHA_8:
diff --git a/tools/layoutlib/bridge/src/android/view/ShadowPainter.java b/tools/layoutlib/bridge/src/android/view/ShadowPainter.java
index 38846bd..a0db7bf 100644
--- a/tools/layoutlib/bridge/src/android/view/ShadowPainter.java
+++ b/tools/layoutlib/bridge/src/android/view/ShadowPainter.java
@@ -65,6 +65,9 @@
@SuppressWarnings({"SuspiciousNameCombination", "UnnecessaryLocalVariable"}) // Imported code
public static BufferedImage createDropShadow(BufferedImage source, int shadowSize,
float shadowOpacity, int shadowRgb) {
+ if (shadowSize == 0) {
+ return source;
+ }
// This code is based on
// http://www.jroller.com/gfx/entry/non_rectangular_shadow
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 4d2c2fc..c6d60f8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -181,7 +181,7 @@
*/
private static LayoutLog sCurrentLog = sDefaultLog;
- private static final int LAST_SUPPORTED_FEATURE = Features.PREFERENCES_RENDERING;
+ private static final int LAST_SUPPORTED_FEATURE = Features.RENDER_ALL_DRAWABLE_STATES;
@Override
public int getApiLevel() {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
new file mode 100644
index 0000000..cfc8f40
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
@@ -0,0 +1,39 @@
+/*
+ * 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.layoutlib.bridge.android;
+
+import com.android.ide.common.rendering.api.SessionParams.Key;
+
+/**
+ * This contains all known keys for the {@link RenderParams#getFlag(Key)}.
+ * <p/>
+ * The IDE has its own copy of this class which may be newer or older than this one.
+ * <p/>
+ * Constants should never be modified or removed from this class.
+ */
+public final class RenderParamsFlags {
+
+ public static final Key<String> FLAG_KEY_ROOT_TAG =
+ new Key<String>("rootTag", String.class);
+ public static final Key<Boolean> FLAG_KEY_DISABLE_BITMAP_CACHING =
+ new Key<Boolean>("disableBitmapCaching", Boolean.class);
+ public static final Key<Boolean> FLAG_KEY_RENDER_ALL_DRAWABLE_STATES =
+ new Key<Boolean>("renderAllDrawableStates", Boolean.class);
+
+ // Disallow instances.
+ private RenderParamsFlags() {}
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java
deleted file mode 100644
index 51a0104..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java
+++ /dev/null
@@ -1,37 +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.layoutlib.bridge.android;
-
-import com.android.ide.common.rendering.api.SessionParams;
-
-/**
- * This contains all known keys for the {@link SessionParams#getFlag(SessionParams.Key)}.
- * <p/>
- * The IDE has its own copy of this class which may be newer or older than this one.
- * <p/>
- * Constants should never be modified or removed from this class.
- */
-public final class SessionParamsFlags {
-
- public static final SessionParams.Key<String> FLAG_KEY_ROOT_TAG =
- new SessionParams.Key<String>("rootTag", String.class);
- public static final SessionParams.Key<Boolean> FLAG_KEY_DISABLE_BITMAP_CACHING =
- new SessionParams.Key<Boolean>("disableBitmapCaching", Boolean.class);
-
- // Disallow instances.
- private SessionParamsFlags() {}
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
index 669e6b5..3dee1e2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
@@ -16,20 +16,20 @@
package com.android.layoutlib.bridge.impl;
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
-
import com.android.ide.common.rendering.api.DrawableParams;
import com.android.ide.common.rendering.api.HardwareConfig;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.Result.Status;
import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.resources.ResourceType;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.StateListDrawable;
import android.view.AttachInfo_Accessor;
import android.view.View.MeasureSpec;
import android.widget.FrameLayout;
@@ -38,7 +38,9 @@
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
-import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
/**
* Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}.
@@ -71,11 +73,37 @@
return Status.ERROR_NOT_A_DRAWABLE.createResult();
}
+ Drawable d = ResourceHelper.getDrawable(drawableResource, context);
+
+ final Boolean allStates =
+ params.getFlag(RenderParamsFlags.FLAG_KEY_RENDER_ALL_DRAWABLE_STATES);
+ if (allStates == Boolean.TRUE) {
+ final List<BufferedImage> result;
+
+ if (d instanceof StateListDrawable) {
+ result = new ArrayList<BufferedImage>();
+ final StateListDrawable stateList = (StateListDrawable) d;
+ for (int i = 0; i < stateList.getStateCount(); i++) {
+ final Drawable stateDrawable = stateList.getStateDrawable(i);
+ result.add(renderImage(hardwareConfig, stateDrawable, context));
+ }
+ } else {
+ result = Collections.singletonList(renderImage(hardwareConfig, d, context));
+ }
+
+ return Status.SUCCESS.createResult(result);
+ } else {
+ BufferedImage image = renderImage(hardwareConfig, d, context);
+ return Status.SUCCESS.createResult(image);
+ }
+ }
+
+ private BufferedImage renderImage(HardwareConfig hardwareConfig, Drawable d,
+ BridgeContext context) {
// create a simple FrameLayout
FrameLayout content = new FrameLayout(context);
// get the actual Drawable object to draw
- Drawable d = ResourceHelper.getDrawable(drawableResource, context);
content.setBackground(d);
// set the AttachInfo on the root view.
@@ -83,8 +111,27 @@
// measure
- int w = hardwareConfig.getScreenWidth();
- int h = hardwareConfig.getScreenHeight();
+ int w = d.getIntrinsicWidth();
+ int h = d.getIntrinsicHeight();
+
+ final int screenWidth = hardwareConfig.getScreenWidth();
+ final int screenHeight = hardwareConfig.getScreenHeight();
+
+ if (w == -1 || h == -1) {
+ // Use screen size when either intrinsic width or height isn't available
+ w = screenWidth;
+ h = screenHeight;
+ } else if (w > screenWidth || h > screenHeight) {
+ // If image wouldn't fit to the screen, resize it to avoid cropping.
+
+ // We need to find scale such that scale * w <= screenWidth, scale * h <= screenHeight
+ double scale = Math.min((double) screenWidth / w, (double) screenHeight / h);
+
+ // scale * w / scale * h = w / h, so, proportions are preserved.
+ w = (int) Math.floor(scale * w);
+ h = (int) Math.floor(scale * h);
+ }
+
int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
content.measure(w_spec, h_spec);
@@ -108,8 +155,7 @@
// and draw
content.draw(canvas);
-
- return Status.SUCCESS.createResult(image);
+ return image;
}
protected BufferedImage getImage(int w, int h) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 875cc87..607563a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -50,7 +50,7 @@
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.android.SessionParamsFlags;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.bars.BridgeActionBar;
import com.android.layoutlib.bridge.bars.AppCompatActionBar;
import com.android.layoutlib.bridge.bars.Config;
@@ -400,7 +400,7 @@
// it can instantiate the custom Fragment.
Fragment_Delegate.setProjectCallback(params.getProjectCallback());
- String rootTag = params.getFlag(SessionParamsFlags.FLAG_KEY_ROOT_TAG);
+ String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG);
boolean isPreference = "PreferenceScreen".equals(rootTag);
View view;
if (isPreference) {
@@ -557,7 +557,7 @@
// This is useful when mImage is just a wrapper of Graphics2D so
// it doesn't get cached.
boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag(
- SessionParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING));
+ RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING));
if (newRenderSize || mCanvas == null || disableBitmapCaching) {
if (params.getImageFactory() != null) {
mImage = params.getImageFactory().getImage(